// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.googlesource.gerrit.owners;

import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toSet;

import com.google.common.base.Joiner;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.LabelFunction;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelTypes;
import com.google.gerrit.entities.LegacySubmitRequirement;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.extensions.annotations.Exports;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.server.approval.ApprovalsUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.DiffNotAvailableException;
import com.google.gerrit.server.patch.DiffOperations;
import com.google.gerrit.server.patch.DiffOptions;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.rules.SubmitRule;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.owners.common.Accounts;
import com.googlesource.gerrit.owners.common.LabelDefinition;
import com.googlesource.gerrit.owners.common.PathOwners;
import com.googlesource.gerrit.owners.common.PathOwnersEntriesCache;
import com.googlesource.gerrit.owners.common.PluginSettings;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;

@Singleton
public class OwnersSubmitRequirement implements SubmitRule {
  public static class OwnersSubmitRequirementModule extends AbstractModule {
    @Override
    public void configure() {
      bind(SubmitRule.class)
          .annotatedWith(Exports.named("OwnersSubmitRequirement"))
          .to(OwnersSubmitRequirement.class);
    }
  }

  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  private static final LegacySubmitRequirement SUBMIT_REQUIREMENT =
      LegacySubmitRequirement.builder().setFallbackText("Owners").setType("owners").build();

  private final OwnersMetrics metrics;
  private final PluginSettings pluginSettings;
  private final ProjectCache projectCache;
  private final Accounts accounts;
  private final GitRepositoryManager repoManager;
  private final DiffOperations diffOperations;
  private final ApprovalsUtil approvalsUtil;
  private final PathOwnersEntriesCache cache;

  @Inject
  OwnersSubmitRequirement(
      OwnersMetrics metrics,
      PluginSettings pluginSettings,
      ProjectCache projectCache,
      Accounts accounts,
      GitRepositoryManager repoManager,
      DiffOperations diffOperations,
      ApprovalsUtil approvalsUtil,
      PathOwnersEntriesCache cache) {
    this.metrics = metrics;
    this.pluginSettings = pluginSettings;
    this.projectCache = projectCache;
    this.accounts = accounts;
    this.repoManager = repoManager;
    this.diffOperations = diffOperations;
    this.approvalsUtil = approvalsUtil;
    this.cache = cache;
  }

  @Override
  public Optional<SubmitRecord> evaluate(ChangeData cd) {
    requireNonNull(cd, "changeData");

    Change change = cd.change();
    Project.NameKey project = cd.project();
    int changeId = cd.getId().get();
    if (change.isClosed()) {
      logger.atFine().log(
          "Project '%s': change #%d is closed therefore OWNERS submit requirements are skipped.",
          project, changeId);
      return Optional.empty();
    }

    metrics.countSubmitRuleRuns.increment();
    try (Timer0.Context ctx = metrics.runSubmitRule.start()) {
      ProjectState projectState = getProjectState(project);
      PathOwners pathOwners = getPathOwners(cd, projectState);
      Map<String, Set<Account.Id>> fileOwners = pathOwners.getFileOwners();
      if (fileOwners.isEmpty()) {
        logger.atFinest().log(
            "Project '%s': change #%d has no OWNERS submit requirements defined. "
                + "Skipping submit requirements.",
            project, changeId);
        return Optional.empty();
      }

      ChangeNotes notes = cd.notes();
      requireNonNull(notes, "notes");
      LabelTypes labelTypes = projectState.getLabelTypes(notes);
      LabelDefinition label = resolveLabel(labelTypes, pathOwners.getLabel());
      Optional<LabelAndScore> ownersLabel = ownersLabel(labelTypes, label, project);

      Map<Account.Id, List<PatchSetApproval>> approvalsByAccount =
          Streams.stream(approvalsUtil.byPatchSet(notes, cd.currentPatchSet().id()))
              .collect(Collectors.groupingBy(PatchSetApproval::accountId));

      Account.Id uploader = notes.getCurrentPatchSet().uploader();

      Set<String> missingApprovals =
          fileOwners.entrySet().stream()
              .filter(
                  requiredApproval ->
                      ownersLabel
                          .map(
                              ol ->
                                  isApprovalMissing(
                                      requiredApproval, uploader, approvalsByAccount, ol))
                          .orElse(true))
              .map(Map.Entry::getKey)
              .collect(toSet());

      return Optional.of(
          missingApprovals.isEmpty()
              ? ok()
              : notReady(
                  label.getName(),
                  String.format(
                      "Missing approvals for path(s): [%s]",
                      Joiner.on(", ").join(missingApprovals))));
    } catch (IOException e) {
      String msg =
          String.format(
              "Project '%s': repository cannot be opened to evaluate OWNERS submit requirements.",
              project);
      logger.atSevere().withCause(e).log("%s", msg);
      throw new IllegalStateException(msg, e);
    } catch (DiffNotAvailableException e) {
      String msg =
          String.format(
              "Project '%s' change #%d: unable to get diff to evaluate OWNERS submit requirements.",
              project, changeId);
      logger.atSevere().withCause(e).log("%s", msg);
      throw new IllegalStateException(msg, e);
    }
  }

  private ProjectState getProjectState(Project.NameKey project) {
    ProjectState projectState = projectCache.get(project).orElseThrow(illegalState(project));
    if (projectState.hasPrologRules()) {
      logger.atInfo().atMostEvery(1, TimeUnit.DAYS).log(
          "Project '%s' has prolog rules enabled. "
              + "It may interfere with the OWNERS submit requirements evaluation.",
          project);
    }
    return projectState;
  }

  private PathOwners getPathOwners(ChangeData cd, ProjectState projectState)
      throws IOException, DiffNotAvailableException {
    metrics.countConfigLoads.increment();
    try (Timer0.Context ctx = metrics.loadConfig.start()) {
      String branch = cd.change().getDest().branch();

      List<Project.NameKey> parents =
          Optional.<Project.NameKey>ofNullable(projectState.getProject().getParent())
              .map(Arrays::asList)
              .orElse(Collections.emptyList());

      Project.NameKey nameKey = projectState.getNameKey();
      try (Repository repo = repoManager.openRepository(nameKey)) {
        PathOwners pathOwners =
            new PathOwners(
                accounts,
                repoManager,
                repo,
                parents,
                pluginSettings.isBranchDisabled(branch) ? Optional.empty() : Optional.of(branch),
                getDiff(nameKey, cd.currentPatchSet().commitId()),
                pluginSettings.expandGroups(),
                nameKey.get(),
                cache);

        return pathOwners;
      }
    }
  }

  /**
   * The idea is to select the label type that is configured for owner to cast the vote. If nothing
   * is configured in the OWNERS file then `Code-Review` will be selected.
   *
   * @param labelTypes labels configured for project
   * @param label and score definition that is configured in the OWNERS file
   */
  static LabelDefinition resolveLabel(LabelTypes labelTypes, Optional<LabelDefinition> label) {
    return label.orElse(LabelDefinition.CODE_REVIEW);
  }

  /**
   * Create {@link LabelAndScore} definition with a label LabelType if label can be found or empty
   * otherwise. Note that score definition is copied from the OWNERS.
   *
   * @param labelTypes labels configured for project
   * @param label and score definition (optional) that is resolved from the OWNERS file
   * @param project that change is evaluated for
   */
  static Optional<LabelAndScore> ownersLabel(
      LabelTypes labelTypes, LabelDefinition label, Project.NameKey project) {
    return labelTypes
        .byLabel(label.getName())
        .map(type -> new LabelAndScore(type, label.getScore()))
        .or(
            () -> {
              logger.atSevere().log(
                  "OWNERS label '%s' is not configured for '%s' project. Change is not submittable.",
                  label, project);
              return Optional.empty();
            });
  }

  static boolean isApprovalMissing(
      Map.Entry<String, Set<Account.Id>> requiredApproval,
      Account.Id uploader,
      Map<Account.Id, List<PatchSetApproval>> approvalsByAccount,
      LabelAndScore ownersLabel) {
    return requiredApproval.getValue().stream()
        .noneMatch(
            fileOwner -> isApprovedByOwner(fileOwner, uploader, approvalsByAccount, ownersLabel));
  }

  static boolean isApprovedByOwner(
      Account.Id fileOwner,
      Account.Id uploader,
      Map<Account.Id, List<PatchSetApproval>> approvalsByAccount,
      LabelAndScore ownersLabel) {
    return Optional.ofNullable(approvalsByAccount.get(fileOwner))
        .map(
            approvals ->
                approvals.stream()
                    .anyMatch(
                        approval ->
                            hasSufficientApproval(approval, ownersLabel, fileOwner, uploader)))
        .orElse(false);
  }

  static boolean hasSufficientApproval(
      PatchSetApproval approval,
      LabelAndScore ownersLabel,
      Account.Id fileOwner,
      Account.Id uploader) {
    return ownersLabel.getLabelType().getLabelId().equals(approval.labelId())
        && isLabelApproved(
            ownersLabel.getLabelType(), ownersLabel.getScore(), fileOwner, uploader, approval);
  }

  static boolean isLabelApproved(
      LabelType label,
      Optional<Short> score,
      Account.Id fileOwner,
      Account.Id uploader,
      PatchSetApproval approval) {
    if (label.isIgnoreSelfApproval() && fileOwner.equals(uploader)) {
      return false;
    }

    return score
        .map(value -> approval.value() >= value)
        .orElseGet(
            () -> {
              LabelFunction function = label.getFunction();
              if (function.isMaxValueRequired()) {
                return label.isMaxPositive(approval);
              }

              if (function.isBlock() && label.isMaxNegative(approval)) {
                return false;
              }

              return approval.value() > label.getDefaultValue();
            });
  }

  static class LabelAndScore {
    private final LabelType labelType;
    private final Optional<Short> score;

    LabelAndScore(LabelType labelType, Optional<Short> score) {
      this.labelType = labelType;
      this.score = score;
    }

    LabelType getLabelType() {
      return labelType;
    }

    Optional<Short> getScore() {
      return score;
    }
  }

  private Map<String, FileDiffOutput> getDiff(Project.NameKey project, ObjectId revision)
      throws DiffNotAvailableException {
    requireNonNull(project, "project");
    requireNonNull(revision, "revision");

    // Use parentNum=0 to do the comparison against the default base.
    // For non-merge commits the default base is the only parent (aka parent 1, initial commits
    // are not supported).
    // For merge commits the default base is the auto-merge commit which should be used as base IOW
    // only the changes from it should be reviewed as changes against the parent 1 were already
    // reviewed
    return diffOperations.listModifiedFilesAgainstParent(
        project, revision, 0, DiffOptions.DEFAULTS);
  }

  private static SubmitRecord notReady(String ownersLabel, String missingApprovals) {
    SubmitRecord submitRecord = new SubmitRecord();
    submitRecord.status = SubmitRecord.Status.NOT_READY;
    submitRecord.errorMessage = missingApprovals;
    submitRecord.requirements = List.of(SUBMIT_REQUIREMENT);
    SubmitRecord.Label label = new SubmitRecord.Label();
    label.label = String.format("%s from owners", ownersLabel);
    label.status = SubmitRecord.Label.Status.NEED;
    submitRecord.labels = List.of(label);
    return submitRecord;
  }

  private static SubmitRecord ok() {
    SubmitRecord submitRecord = new SubmitRecord();
    submitRecord.status = SubmitRecord.Status.OK;
    submitRecord.requirements = List.of(SUBMIT_REQUIREMENT);
    return submitRecord;
  }
}
