// 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.google.gerrit.server.schema;

import static com.google.gerrit.server.project.ProjectConfig.RULES_PL_FILE;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.LabelFunction;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelValue;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.entities.SubmitRequirement;
import com.google.gerrit.entities.SubmitRequirementExpression;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.RepoMetaDataUpdater;
import com.google.gerrit.server.project.RepoMetaDataUpdater.ConfigUpdater;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;

/**
 * A class with logic for migrating existing label functions to submit requirements and resetting
 * the label functions to {@link LabelFunction#NO_BLOCK}.
 *
 * <p>Important note: Callers should do this migration only if this gerrit installation has no
 * Prolog submit rules (i.e. no rules.pl file in refs/meta/config). Otherwise, the newly created
 * submit requirements might not behave as intended.
 *
 * <p>The conversion is done as follows:
 *
 * <ul>
 *   <li>MaxWithBlock is translated to submittableIf = label:$lbl=MAX AND -label:$lbl=MIN
 *   <li>MaxNoBlock is translated to submittableIf = label:$lbl=MAX
 *   <li>AnyWithBlock is translated to submittableIf = -label:$lbl=MIN
 *   <li>NoBlock/NoOp are translated to applicableIf = is:false (not applicable)
 *   <li>PatchSetLock labels are left as is
 * </ul>
 *
 * If the label has {@link LabelType#isIgnoreSelfApproval()}, the max vote is appended with the
 * 'user=non_uploader' argument.
 *
 * <p>For labels that were skipped, i.e. had only one "zero" predefined value, the migrator creates
 * a non-applicable submit-requirement for them. This is done so that if a parent project had a
 * submit-requirement with the same name, then it's not inherited by this project.
 *
 * <p>If there is an existing label and there exists a "submit requirement" with the same name, the
 * migrator checks if the submit-requirement to be created matches the one in project.config. If
 * they don't match, a warning message is printed, otherwise nothing happens. In either cases, the
 * existing submit-requirement is not altered.
 */
public class MigrateLabelFunctionsToSubmitRequirement {
  public static final String COMMIT_MSG = "Migrate label functions to submit requirements";

  private final RepoMetaDataUpdater repoMetaDataUpdater;
  private final GitRepositoryManager repoManager;

  public enum Status {
    /**
     * The migrator updated the project config and created new submit requirements and/or did reset
     * label functions.
     */
    MIGRATED,

    /** The project had prolog rules, and the migration was skipped. */
    HAS_PROLOG,

    /**
     * The project was migrated with a previous run of this class. The migration for this run was
     * skipped.
     */
    PREVIOUSLY_MIGRATED,

    /**
     * Migration was run for the project but did not update the project.config because it was
     * up-to-date.
     */
    NO_CHANGE
  }

  @Inject
  public MigrateLabelFunctionsToSubmitRequirement(
      RepoMetaDataUpdater repoMetaDataUpdater, GitRepositoryManager repoManager) {
    this.repoMetaDataUpdater = repoMetaDataUpdater;
    this.repoManager = repoManager;
  }

  /**
   * For each label function, create a corresponding submit-requirement and set the label function
   * to NO_BLOCK. Blocking label functions are substituted with blocking submit-requirements.
   * Non-blocking label functions are substituted with non-applicable submit requirements, allowing
   * the label vote to be surfaced as a trigger vote (optional label).
   *
   * @return {@link Status} reflecting the status of the migration.
   */
  public Status executeMigration(Project.NameKey project, UpdateUI ui)
      throws IOException,
          ConfigInvalidException,
          MethodNotAllowedException,
          PermissionBackendException {
    try (ConfigUpdater updater =
        repoMetaDataUpdater.configUpdaterWithoutPermissionsCheck(project, null, COMMIT_MSG)) {
      Status result = updateConfig(project, updater.getConfig(), ui);
      if (result == Status.MIGRATED) {
        updater.commitConfigUpdate();
      }
      return result;
    }
  }

  public Status updateConfig(Project.NameKey project, ProjectConfig projectConfig, UpdateUI ui)
      throws IOException {
    boolean updated = false;
    if (hasPrologRules(project)) {
      ui.message(String.format("Skipping project %s because it has prolog rules", project));
      return Status.HAS_PROLOG;
    }

    if (hasMigrationAlreadyRun(project)) {
      ui.message(
          String.format(
              "Skipping migrating label functions to submit requirements for project '%s'"
                  + " because it has been previously migrated",
              project));
      return Status.PREVIOUSLY_MIGRATED;
    }

    Map<String, LabelType> labelSections = projectConfig.getLabelSections();
    SubmitRequirementMap existingSubmitRequirements =
        new SubmitRequirementMap(projectConfig.getSubmitRequirementSections());

    for (Map.Entry<String, LabelType> section : labelSections.entrySet()) {
      String labelName = section.getKey();
      LabelType labelType = section.getValue();

      if (labelType.getFunction() == LabelFunction.PATCH_SET_LOCK) {
        // PATCH_SET_LOCK functions should be left as is
        continue;
      }

      // If the function is other than "NoBlock" we want to reset the label function regardless
      // of whether there exists a "submit requirement".
      if (labelType.getFunction() != LabelFunction.NO_BLOCK) {
        section.setValue(labelType.toBuilder().setNoBlockFunction().build());
        updated = true;
      }

      Optional<SubmitRequirement> sr = createSrFromLabelDef(labelType);
      if (!sr.isPresent()) {
        continue;
      }
      // Make the operation idempotent by skipping creating the submit-requirement if one was
      // already created or previously existed.
      if (existingSubmitRequirements.containsKey(labelName)) {
        SubmitRequirement existing = existingSubmitRequirements.get(labelName);
        if (!sr.get().equals(existing)) {
          ui.message(
              String.format(
                  "Warning: Skipping creating a submit requirement for label '%s'. An existing "
                      + "submit requirement is already present but its definition is not "
                      + "identical to the existing label definition.",
                  labelName));
        }
        continue;
      }
      updated = true;
      ui.message(
          String.format(
              "Project %s: Creating a submit requirement for label %s", project, labelName));
      existingSubmitRequirements.put(sr.get());
    }
    return updated ? Status.MIGRATED : Status.NO_CHANGE;
  }

  private static Optional<SubmitRequirement> createSrFromLabelDef(LabelType lt) {
    if (isLabelSkipped(lt)) {
      return Optional.of(createNonApplicableSr(lt));
    } else if (isBlockingOrRequiredLabel(lt)) {
      return Optional.of(createBlockingOrRequiredSr(lt));
    }
    return Optional.empty();
  }

  private static SubmitRequirement createNonApplicableSr(LabelType lt) {
    return SubmitRequirement.builder()
        .setName(lt.getName())
        .setApplicabilityExpression(SubmitRequirementExpression.of("is:false"))
        .setSubmittabilityExpression(SubmitRequirementExpression.create("is:true"))
        .setAllowOverrideInChildProjects(lt.isCanOverride())
        .build();
  }

  /**
   * Create a "submit requirement" that is only satisfied if the label is voted with the max votes
   * and/or not voted by the min vote, according to the label attributes.
   */
  private static SubmitRequirement createBlockingOrRequiredSr(LabelType lt) {
    SubmitRequirement.Builder builder =
        SubmitRequirement.builder()
            .setName(lt.getName())
            .setAllowOverrideInChildProjects(lt.isCanOverride());
    String maxPart =
        String.format("label:%s=MAX", lt.getName())
            + (lt.isIgnoreSelfApproval() ? ",user=non_uploader" : "");
    switch (lt.getFunction()) {
      case MAX_WITH_BLOCK ->
          builder.setSubmittabilityExpression(
              SubmitRequirementExpression.create(
                  String.format("%s AND -label:%s=MIN", maxPart, lt.getName())));
      case ANY_WITH_BLOCK ->
          builder.setSubmittabilityExpression(
              SubmitRequirementExpression.create(String.format("-label:%s=MIN", lt.getName())));
      case MAX_NO_BLOCK ->
          builder.setSubmittabilityExpression(SubmitRequirementExpression.create(maxPart));
      default -> {}
    }
    ImmutableList<String> refPatterns = lt.getRefPatterns();
    if (refPatterns != null && !refPatterns.isEmpty()) {
      builder.setApplicabilityExpression(
          SubmitRequirementExpression.of(
              String.join(
                  " OR ",
                  lt.getRefPatterns().stream()
                      .map(b -> "branch:\\\"" + b + "\\\"")
                      .collect(Collectors.toList()))));
    }
    return builder.build();
  }

  private static boolean isBlockingOrRequiredLabel(LabelType lt) {
    return switch (lt.getFunction()) {
      case ANY_WITH_BLOCK, MAX_WITH_BLOCK, MAX_NO_BLOCK -> true;
      case NO_BLOCK, NO_OP, PATCH_SET_LOCK -> false;
    };
  }

  private static boolean isLabelSkipped(LabelType lt) {
    ImmutableList<LabelValue> values = lt.getValues();
    return values.isEmpty() || (values.size() == 1 && values.get(0).getValue() == 0);
  }

  public boolean anyProjectHasProlog(Collection<Project.NameKey> allProjects) throws IOException {
    for (Project.NameKey p : allProjects) {
      if (hasPrologRules(p)) {
        return true;
      }
    }
    return false;
  }

  private boolean hasPrologRules(Project.NameKey project) throws IOException {
    try (Repository repo = repoManager.openRepository(project);
        RevWalk rw = new RevWalk(repo);
        ObjectReader reader = rw.getObjectReader()) {
      Ref refsConfig = repo.exactRef(RefNames.REFS_CONFIG);
      if (refsConfig == null) {
        // Project does not have a refs/meta/config and no rules.pl consequently.
        return false;
      }
      RevCommit commit = repo.parseCommit(refsConfig.getObjectId());
      try (TreeWalk tw = TreeWalk.forPath(reader, RULES_PL_FILE, commit.getTree())) {
        if (tw != null) {
          return true;
        }
      }

      return false;
    }
  }

  private boolean hasMigrationAlreadyRun(Project.NameKey project) throws IOException {
    try (Repository repo = repoManager.openRepository(project)) {
      try (RevWalk revWalk = new RevWalk(repo)) {
        Ref refsMetaConfig = repo.exactRef(RefNames.REFS_CONFIG);
        if (refsMetaConfig == null) {
          return false;
        }
        revWalk.markStart(revWalk.parseCommit(refsMetaConfig.getObjectId()));
        RevCommit commit;
        while ((commit = revWalk.next()) != null) {
          if (COMMIT_MSG.equals(commit.getShortMessage())) {
            return true;
          }
        }
        return false;
      }
    }
  }

  /**
   * Helper "Map" to of submit requirements with case-preserving keys and case-insensitive lookup
   */
  private static class SubmitRequirementMap {
    private final Map<String, SubmitRequirement> submitRequirements;
    private final Map<String, String> lowerCaseToOriginalNames;

    SubmitRequirementMap(Map<String, SubmitRequirement> submitRequirements) {
      this.submitRequirements = submitRequirements;
      this.lowerCaseToOriginalNames =
          submitRequirements.keySet().stream()
              .collect(Collectors.toMap(k -> k.toLowerCase(Locale.ROOT), k -> k));
    }

    boolean containsKey(String name) {
      return lowerCaseToOriginalNames.containsKey(name.toLowerCase(Locale.ROOT));
    }

    @Nullable
    SubmitRequirement get(String name) {
      String orig = lowerCaseToOriginalNames.get(name.toLowerCase(Locale.ROOT));
      return orig != null ? submitRequirements.get(orig) : null;
    }

    void put(SubmitRequirement sr) {
      String name = sr.name();
      submitRequirements.put(name, sr);
      lowerCaseToOriginalNames.put(name.toLowerCase(Locale.ROOT), name);
    }
  }
}
