// Copyright (C) 2020 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.acceptance.testsuite.change;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.testing.TestActionRefUpdateContext.openTestRefUpdateContext;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
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.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.ChangeIdentifier;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.edit.tree.TreeCreator;
import com.google.gerrit.server.edit.tree.TreeModification;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.util.CommitMessageUtil;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import java.io.IOException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.Merger;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.ChangeIdUtil;

/**
 * The implementation of {@link ChangeOperations}.
 *
 * <p>There is only one implementation of {@link ChangeOperations}. Nevertheless, we keep the
 * separation between interface and implementation to enhance clarity.
 */
public class ChangeOperationsImpl implements ChangeOperations {
  private final Sequences seq;
  private final ChangeInserter.Factory changeInserterFactory;
  private final PatchSetInserter.Factory patchsetInserterFactory;
  private final GitRepositoryManager repositoryManager;
  private final AccountResolver resolver;
  private final IdentifiedUser.GenericFactory userFactory;
  private final PersonIdent serverIdent;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final ChangeFinder changeFinder;
  private final PerPatchsetOperationsImpl.Factory perPatchsetOperationsFactory;
  private final PerCommentOperationsImpl.Factory perCommentOperationsFactory;
  private final PerDraftCommentOperationsImpl.Factory perDraftCommentOperationsFactory;
  private final ProjectOperations projectOperations;
  private final ProjectCache projectCache;
  private final AccountCache accountCache;

  @Inject
  public ChangeOperationsImpl(
      Sequences seq,
      ChangeInserter.Factory changeInserterFactory,
      PatchSetInserter.Factory patchsetInserterFactory,
      GitRepositoryManager repositoryManager,
      AccountResolver resolver,
      IdentifiedUser.GenericFactory userFactory,
      @GerritPersonIdent PersonIdent serverIdent,
      BatchUpdate.Factory batchUpdateFactory,
      ChangeFinder changeFinder,
      PerPatchsetOperationsImpl.Factory perPatchsetOperationsFactory,
      PerCommentOperationsImpl.Factory perCommentOperationsFactory,
      PerDraftCommentOperationsImpl.Factory perDraftCommentOperationsFactory,
      ProjectOperations projectOperations,
      ProjectCache projectCache,
      AccountCache accountCache) {
    this.seq = seq;
    this.changeInserterFactory = changeInserterFactory;
    this.patchsetInserterFactory = patchsetInserterFactory;
    this.repositoryManager = repositoryManager;
    this.resolver = resolver;
    this.userFactory = userFactory;
    this.serverIdent = serverIdent;
    this.batchUpdateFactory = batchUpdateFactory;
    this.changeFinder = changeFinder;
    this.perPatchsetOperationsFactory = perPatchsetOperationsFactory;
    this.perCommentOperationsFactory = perCommentOperationsFactory;
    this.perDraftCommentOperationsFactory = perDraftCommentOperationsFactory;
    this.projectOperations = projectOperations;
    this.projectCache = projectCache;
    this.accountCache = accountCache;
  }

  @Override
  public PerChangeOperations change(Change.Id changeId) {
    return new PerChangeOperationsImpl(ChangeIdentifier.byNumericChangeId(changeId.get()));
  }

  @Override
  public PerChangeOperations change(ChangeIdentifier changeIdentifier) {
    return new PerChangeOperationsImpl(changeIdentifier);
  }

  @Override
  public TestChangeCreation.Builder newChange() {
    return TestChangeCreation.builder(this::createChange, changeId -> this.change(changeId).get());
  }

  private Change.Id createChange(TestChangeCreation changeCreation) throws Exception {
    try (RefUpdateContext ctx = openTestRefUpdateContext()) {
      Change.Id changeId = Change.id(seq.nextChangeId());
      Project.NameKey project = getTargetProject(changeCreation);

      try (Repository repository = repositoryManager.openRepository(project);
          ObjectInserter objectInserter = repository.newObjectInserter();
          RevWalk revWalk = new RevWalk(objectInserter.newReader())) {
        Instant creationTimestamp = changeCreation.createdOn().orElse(TimeUtil.now());
        IdentifiedUser changeOwner = getChangeOwner(changeCreation);
        PersonIdent author = getAuthorIdent(creationTimestamp, changeCreation);
        PersonIdent committer = getCommitterIdent(creationTimestamp, changeCreation);
        ObjectId commitId =
            createCommit(repository, revWalk, objectInserter, changeCreation, author, committer);

        String refName = RefNames.fullName(changeCreation.branch());
        ChangeInserter inserter = getChangeInserter(changeId, refName, commitId);
        inserter.setGroups(getGroups(changeCreation));
        changeCreation.topic().ifPresent(t -> inserter.setTopic(t));
        inserter.setApprovals(changeCreation.approvals());
        inserter.setValidationOptions(changeCreation.validationOptions());

        try (BatchUpdate batchUpdate =
            batchUpdateFactory.create(project, changeOwner, creationTimestamp)) {
          batchUpdate.setRepository(repository, revWalk, objectInserter);
          batchUpdate.insertChange(inserter);
          batchUpdate.execute();
        }
        return changeId;
      }
    }
  }

  private Project.NameKey getTargetProject(TestChangeCreation changeCreation) {
    if (changeCreation.project().isPresent()) {
      return changeCreation.project().get();
    }

    return projectOperations.newProject().create();
  }

  private IdentifiedUser getChangeOwner(TestChangeCreation changeCreation)
      throws IOException, ConfigInvalidException {
    if (changeCreation.owner().isPresent()) {
      return userFactory.create(changeCreation.owner().get());
    }

    return getArbitraryUser();
  }

  private PersonIdent getAuthorIdent(Instant when, TestChangeCreation changeCreation)
      throws IOException, ConfigInvalidException {
    if (changeCreation.authorIdent().isPresent()) {
      return new PersonIdent(changeCreation.authorIdent().get(), when);
    }

    return (changeCreation.author().isPresent()
            ? userFactory.create(changeCreation.author().get())
            : getChangeOwner(changeCreation))
        .newCommitterIdent(when, serverIdent.getZoneId());
  }

  private PersonIdent getCommitterIdent(Instant when, TestChangeCreation changeCreation)
      throws IOException, ConfigInvalidException {
    if (changeCreation.committerIdent().isPresent()) {
      return new PersonIdent(changeCreation.committerIdent().get(), when);
    }

    return (changeCreation.committer().isPresent()
            ? userFactory.create(changeCreation.committer().get())
            : getChangeOwner(changeCreation))
        .newCommitterIdent(when, serverIdent.getZoneId());
  }

  private IdentifiedUser getArbitraryUser() throws ConfigInvalidException, IOException {
    return getArbitraryUser(Predicates.alwaysTrue());
  }

  private IdentifiedUser getArbitraryUser(Predicate<Account.Id> filter)
      throws ConfigInvalidException, IOException {
    ImmutableSet<Account.Id> foundAccounts =
        resolver.resolveIgnoreVisibility("").asIdSet().stream()
            .filter(filter)
            .collect(toImmutableSet());
    checkState(
        !foundAccounts.isEmpty(),
        "At least one user account must be available on the Gerrit server");
    return userFactory.create(foundAccounts.iterator().next());
  }

  private ObjectId createCommit(
      Repository repository,
      RevWalk revWalk,
      ObjectInserter objectInserter,
      TestChangeCreation changeCreation,
      PersonIdent author,
      PersonIdent committer)
      throws IOException, BadRequestException {
    ImmutableList<ObjectId> parentCommits = getParentCommits(repository, revWalk, changeCreation);
    TreeCreator treeCreator =
        getTreeCreator(objectInserter, parentCommits, changeCreation.mergeStrategy());
    ObjectId tree = createNewTree(repository, treeCreator, changeCreation.treeModifications());
    String commitMessage = correctCommitMessage(changeCreation.commitMessage());
    return createCommit(objectInserter, tree, parentCommits, author, committer, commitMessage);
  }

  private ImmutableList<String> getGroups(TestChangeCreation changeCreation) {
    return changeCreation
        .parents()
        .map(parents -> getGroups(parents))
        .orElseGet(() -> ImmutableList.of());
  }

  private ImmutableList<String> getGroups(ImmutableList<TestCommitIdentifier> parents) {
    return parents.stream()
        .map(parent -> getGroups(parent))
        .flatMap(groups -> groups.stream())
        .collect(toImmutableList());
  }

  private ImmutableList<String> getGroups(TestCommitIdentifier parentCommit) {
    return switch (parentCommit.getKind()) {
      case BRANCH -> ImmutableList.of();
      case CHANGE_ID -> getGroupsFromChange(parentCommit.changeId());
      case CHANGE_IDENTIFIER -> getGroupsFromChange(parentCommit.changeIdentifier());
      case COMMIT_SHA_1 -> ImmutableList.of();
      case PATCHSET_ID -> getGroupsFromPatchset(parentCommit.patchsetId());
      default ->
          throw new IllegalStateException(
              String.format("No parent behavior implemented for %s.", parentCommit.getKind()));
    };
  }

  private ImmutableList<String> getGroupsFromChange(ChangeIdentifier changeIdentifier) {
    Optional<ChangeNotes> changeNotes = changeFinder.findOne(changeIdentifier.id());

    if (changeNotes.isPresent() && changeNotes.get().getChange().isClosed()) {
      return ImmutableList.of();
    }

    return changeNotes
        .map(ChangeNotes::getCurrentPatchSet)
        .map(PatchSet::groups)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Change %s not found and hence can't be used as parent.",
                        changeIdentifier)));
  }

  private ImmutableList<String> getGroupsFromChange(Change.Id changeId) {
    Optional<ChangeNotes> changeNotes = changeFinder.findOne(changeId);

    if (changeNotes.isPresent() && changeNotes.get().getChange().isClosed()) {
      return ImmutableList.of();
    }

    return changeNotes
        .map(ChangeNotes::getCurrentPatchSet)
        .map(PatchSet::groups)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Change %s not found and hence can't be used as parent.", changeId)));
  }

  private ImmutableList<String> getGroupsFromPatchset(PatchSet.Id patchsetId) {
    Optional<ChangeNotes> changeNotes = changeFinder.findOne(patchsetId.changeId());

    if (changeNotes.isPresent() && changeNotes.get().getChange().isClosed()) {
      return ImmutableList.of();
    }

    return changeNotes
        .map(ChangeNotes::getPatchSets)
        .map(patchsets -> patchsets.get(patchsetId))
        .map(PatchSet::groups)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Patchset %s not found and hence can't be used as parent.", patchsetId)));
  }

  private ImmutableList<ObjectId> getParentCommits(
      Repository repository, RevWalk revWalk, TestChangeCreation changeCreation) {
    return changeCreation
        .parents()
        .map(parents -> resolveParents(repository, revWalk, parents))
        .orElseGet(() -> asImmutableList(getTip(repository, changeCreation.branch())));
  }

  private ImmutableList<ObjectId> resolveParents(
      Repository repository, RevWalk revWalk, ImmutableList<TestCommitIdentifier> parents) {
    return parents.stream()
        .map(parent -> resolveCommit(repository, revWalk, parent))
        .collect(toImmutableList());
  }

  private ObjectId resolveCommit(
      Repository repository, RevWalk revWalk, TestCommitIdentifier parentCommit) {
    return switch (parentCommit.getKind()) {
      case BRANCH -> resolveBranchTip(repository, parentCommit.branch());
      case CHANGE_ID -> resolveChange(parentCommit.changeId());
      case CHANGE_IDENTIFIER -> resolveChange(parentCommit.changeIdentifier());
      case COMMIT_SHA_1 -> resolveCommitFromSha1(revWalk, parentCommit.commitSha1());
      case PATCHSET_ID -> resolvePatchset(parentCommit.patchsetId());
      default ->
          throw new IllegalStateException(
              String.format("No parent behavior implemented for %s.", parentCommit.getKind()));
    };
  }

  private static ObjectId resolveBranchTip(Repository repository, String branchName) {
    return getTip(repository, branchName)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Tip of branch %s not found and hence can't be used as parent.",
                        branchName)));
  }

  private static Optional<ObjectId> getTip(Repository repository, String branch) {
    try {
      Optional<Ref> ref = Optional.ofNullable(repository.findRef(branch));
      return ref.map(Ref::getObjectId);
    } catch (IOException e) {
      throw new StorageException(e);
    }
  }

  private ObjectId resolveChange(ChangeIdentifier changeIdentifier) {
    Optional<ChangeNotes> changeNotes = changeFinder.findOne(changeIdentifier.id());
    return changeNotes
        .map(ChangeNotes::getCurrentPatchSet)
        .map(PatchSet::commitId)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Change %s not found and hence can't be used as parent.",
                        changeIdentifier)));
  }

  private ObjectId resolveChange(Change.Id changeId) {
    Optional<ChangeNotes> changeNotes = changeFinder.findOne(changeId);
    return changeNotes
        .map(ChangeNotes::getCurrentPatchSet)
        .map(PatchSet::commitId)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Change %s not found and hence can't be used as parent.", changeId)));
  }

  private static RevCommit resolveCommitFromSha1(RevWalk revWalk, ObjectId commitSha1) {
    try {
      return revWalk.parseCommit(commitSha1);
    } catch (Exception e) {
      throw new IllegalStateException(
          String.format("Commit %s not found and hence can't be used as parent/base.", commitSha1),
          e);
    }
  }

  private ObjectId resolvePatchset(PatchSet.Id patchsetId) {
    Optional<ChangeNotes> changeNotes = changeFinder.findOne(patchsetId.changeId());
    return changeNotes
        .map(ChangeNotes::getPatchSets)
        .map(patchsets -> patchsets.get(patchsetId))
        .map(PatchSet::commitId)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Patchset %s not found and hence can't be used as parent.", patchsetId)));
  }

  private static <T> ImmutableList<T> asImmutableList(Optional<T> value) {
    return value.stream().collect(toImmutableList());
  }

  private static TreeCreator getTreeCreator(
      RevWalk revWalk, ObjectId customBaseCommit, ImmutableList<ObjectId> parentCommits) {
    RevCommit commit = resolveCommitFromSha1(revWalk, customBaseCommit);
    // Use actual parents; relevant for example when a file is restored (->
    // RestoreFileModification).
    return TreeCreator.basedOnTree(commit.getTree(), parentCommits);
  }

  private static TreeCreator getTreeCreator(
      ObjectInserter objectInserter,
      ImmutableList<ObjectId> parentCommits,
      MergeStrategy mergeStrategy) {
    if (parentCommits.isEmpty()) {
      return TreeCreator.basedOnEmptyTree();
    }
    ObjectId baseTreeId = merge(objectInserter, parentCommits, mergeStrategy);
    return TreeCreator.basedOnTree(baseTreeId, parentCommits);
  }

  private static ObjectId merge(
      ObjectInserter objectInserter,
      ImmutableList<ObjectId> parentCommits,
      MergeStrategy mergeStrategy) {
    try {
      Merger merger = mergeStrategy.newMerger(objectInserter, new Config());
      boolean mergeSuccessful = merger.merge(parentCommits.toArray(new AnyObjectId[0]));
      if (!mergeSuccessful) {
        throw new IllegalStateException(
            "Conflicts encountered while merging the specified parents. Use"
                + " mergeOfButBaseOnFirst() instead to avoid these conflicts and define any"
                + " other desired file contents with file().content().");
      }
      return merger.getResultTreeId();
    } catch (IOException e) {
      throw new IllegalStateException(
          "Creating the merge commits of the specified parents failed for an unknown reason.", e);
    }
  }

  private static ObjectId createNewTree(
      Repository repository,
      TreeCreator treeCreator,
      ImmutableList<TreeModification> treeModifications)
      throws IOException {
    treeCreator.addTreeModifications(treeModifications);
    return treeCreator.createNewTreeAndGetId(repository);
  }

  private String correctCommitMessage(String desiredCommitMessage) throws BadRequestException {
    String commitMessage = CommitMessageUtil.checkAndSanitizeCommitMessage(desiredCommitMessage);

    if (ChangeIdUtil.indexOfChangeId(commitMessage, "\n") == -1) {
      ObjectId id = CommitMessageUtil.generateChangeId();
      commitMessage = ChangeIdUtil.insertId(commitMessage, id);
    }

    return commitMessage;
  }

  private ObjectId createCommit(
      ObjectInserter objectInserter,
      ObjectId tree,
      ImmutableList<ObjectId> parentCommitIds,
      PersonIdent author,
      PersonIdent committer,
      String commitMessage)
      throws IOException {
    CommitBuilder builder = new CommitBuilder();
    builder.setTreeId(tree);
    builder.setParentIds(parentCommitIds);
    builder.setAuthor(author);
    builder.setCommitter(committer);
    builder.setMessage(commitMessage);
    ObjectId newCommitId = objectInserter.insert(builder);
    objectInserter.flush();
    return newCommitId;
  }

  private ChangeInserter getChangeInserter(Change.Id changeId, String refName, ObjectId commitId) {
    ChangeInserter inserter = changeInserterFactory.create(changeId, commitId, refName);
    inserter.setMessage(String.format("Uploaded patch set %d.", inserter.getPatchSetId().get()));
    return inserter;
  }

  private class PerChangeOperationsImpl implements PerChangeOperations {

    private final ChangeIdentifier changeIdentifier;

    public PerChangeOperationsImpl(ChangeIdentifier changeIdentifier) {
      this.changeIdentifier = changeIdentifier;
    }

    @Override
    public boolean exists() {
      return changeFinder.findOne(changeIdentifier.id()).isPresent();
    }

    @Override
    public TestChange get() {
      return toTestChange(getChangeNotes().getChange());
    }

    private ChangeNotes getChangeNotes() {
      Optional<ChangeNotes> changeNotes = changeFinder.findOne(changeIdentifier.id());
      checkState(changeNotes.isPresent(), "Tried to get non-existing test change.");
      return changeNotes.get();
    }

    private TestChange toTestChange(Change change) {
      return TestChange.builder()
          .numericChangeId(change.getId())
          .changeId(change.getKey().get())
          .project(change.getProject())
          .dest(change.getDest())
          .subject(change.getSubject())
          .owner(change.getOwner())
          .createdOn(change.getCreatedOn())
          .lastUpdatedOn(change.getLastUpdatedOn())
          .build();
    }

    @Override
    public TestPatchsetCreation.Builder newPatchset() {
      return TestPatchsetCreation.builder(this::createPatchset);
    }

    private PatchSet.Id createPatchset(TestPatchsetCreation patchsetCreation)
        throws IOException, RestApiException, UpdateException {
      try (RefUpdateContext ctx = openTestRefUpdateContext()) {
        ChangeNotes changeNotes = getChangeNotes();
        Project.NameKey project = changeNotes.getProjectName();
        try (Repository repository = repositoryManager.openRepository(project);
            ObjectInserter objectInserter = repository.newObjectInserter();
            RevWalk revWalk = new RevWalk(objectInserter.newReader())) {
          Instant now = TimeUtil.now();
          PersonIdent authorIdent = getAuthorIdent(now, patchsetCreation);
          PersonIdent committerIdent = getCommitterIdent(now, patchsetCreation);
          ObjectId newPatchsetCommit =
              createPatchsetCommit(
                  repository,
                  revWalk,
                  objectInserter,
                  changeNotes,
                  patchsetCreation,
                  authorIdent,
                  committerIdent,
                  now);

          PatchSet.Id patchsetId =
              ChangeUtil.nextPatchSetId(repository, changeNotes.getCurrentPatchSet().id());
          PatchSetInserter patchSetInserter =
              getPatchSetInserter(changeNotes, newPatchsetCommit, patchsetId);

          Account.Id uploaderId =
              patchsetCreation.uploader().orElse(changeNotes.getChange().getOwner());
          IdentifiedUser uploader = userFactory.create(uploaderId);
          try (BatchUpdate batchUpdate = batchUpdateFactory.create(project, uploader, now)) {
            batchUpdate.setRepository(repository, revWalk, objectInserter);
            batchUpdate.addOp(changeNotes.getChangeId(), patchSetInserter);
            batchUpdate.execute();
          }
          return patchsetId;
        }
      }
    }

    @Nullable
    private PersonIdent getAuthorIdent(Instant when, TestPatchsetCreation patchsetCreation) {
      if (patchsetCreation.authorIdent().isPresent()) {
        return new PersonIdent(patchsetCreation.authorIdent().get(), when);
      }

      if (patchsetCreation.author().isPresent()) {
        return userFactory
            .create(patchsetCreation.author().get())
            .newCommitterIdent(when, serverIdent.getZoneId());
      }

      return null;
    }

    @Nullable
    private PersonIdent getCommitterIdent(Instant when, TestPatchsetCreation patchsetCreation) {
      if (patchsetCreation.committerIdent().isPresent()) {
        return new PersonIdent(patchsetCreation.committerIdent().get(), when);
      }

      if (patchsetCreation.committer().isPresent()) {
        return userFactory
            .create(patchsetCreation.committer().get())
            .newCommitterIdent(when, serverIdent.getZoneId());
      }

      return null;
    }

    private ObjectId createPatchsetCommit(
        Repository repository,
        RevWalk revWalk,
        ObjectInserter objectInserter,
        ChangeNotes changeNotes,
        TestPatchsetCreation patchsetCreation,
        @Nullable PersonIdent author,
        @Nullable PersonIdent committer,
        Instant now)
        throws IOException, BadRequestException {
      ObjectId oldPatchsetCommitId = changeNotes.getCurrentPatchSet().commitId();
      RevCommit oldPatchsetCommit = repository.parseCommit(oldPatchsetCommitId);

      ImmutableList<ObjectId> parentCommitIds =
          getParents(repository, revWalk, patchsetCreation, oldPatchsetCommit);
      TreeCreator treeCreator = getTreeCreator(revWalk, oldPatchsetCommit, parentCommitIds);
      ObjectId tree = createNewTree(repository, treeCreator, patchsetCreation.treeModifications());

      String commitMessage =
          correctCommitMessage(
              changeNotes.getChange().getKey().get(),
              patchsetCreation.commitMessage().orElseGet(oldPatchsetCommit::getFullMessage));

      return createCommit(
          objectInserter,
          tree,
          parentCommitIds,
          Optional.ofNullable(author).orElse(getAuthor(oldPatchsetCommit)),
          Optional.ofNullable(committer).orElse(getCommitter(oldPatchsetCommit, now)),
          commitMessage);
    }

    private String correctCommitMessage(String oldChangeId, String desiredCommitMessage)
        throws BadRequestException {
      String commitMessage = CommitMessageUtil.checkAndSanitizeCommitMessage(desiredCommitMessage);

      // Remove initial 'I' and treat the rest as ObjectId. This is not the cleanest approach but
      // unfortunately, we don't seem to have other utility code which takes the string-based
      // change-id and ensures that it is part of the commit message.
      ObjectId id = ObjectId.fromString(oldChangeId.substring(1));
      commitMessage = ChangeIdUtil.insertId(commitMessage, id, false);

      return commitMessage;
    }

    private PersonIdent getAuthor(RevCommit oldPatchsetCommit) {
      return Optional.ofNullable(oldPatchsetCommit.getAuthorIdent()).orElse(serverIdent);
    }

    private PersonIdent getCommitter(RevCommit oldPatchsetCommit, Instant now) {
      PersonIdent oldPatchsetCommitter =
          Optional.ofNullable(oldPatchsetCommit.getCommitterIdent()).orElse(serverIdent);
      if (asSeconds(now) == asSeconds(oldPatchsetCommitter.getWhenAsInstant())) {
        /* We need to ensure that the resulting commit SHA-1 is different from the old patchset.
         * In real situations, this automatically happens as two patchsets won't have exactly the
         * same commit timestamp even when the tree and commit message are the same. In tests,
         * we can easily end up with the same timestamp as Git uses second precision for timestamps.
         * We could of course require that tests must use TestTimeUtil#setClockStep but
         * that would be an unnecessary nuisance for test writers. Hence, go with a simple solution
         * here and simply add a second. */
        now = now.plusSeconds(1);
      }
      return new PersonIdent(oldPatchsetCommitter, now);
    }

    private long asSeconds(Instant date) {
      return date.getEpochSecond();
    }

    private ImmutableList<ObjectId> getParents(
        Repository repository,
        RevWalk revWalk,
        TestPatchsetCreation patchsetCreation,
        RevCommit oldPatchsetCommit) {
      return patchsetCreation
          .parents()
          .map(parents -> resolveParents(repository, revWalk, parents))
          .orElseGet(
              () -> Arrays.stream(oldPatchsetCommit.getParents()).collect(toImmutableList()));
    }

    private PatchSetInserter getPatchSetInserter(
        ChangeNotes changeNotes, ObjectId newPatchsetCommit, PatchSet.Id patchsetId) {
      PatchSetInserter patchSetInserter =
          patchsetInserterFactory.create(changeNotes, patchsetId, newPatchsetCommit);
      patchSetInserter.setCheckAddPatchSetPermission(false);
      patchSetInserter.setMessage(String.format("Uploaded patch set %d.", patchsetId.get()));
      return patchSetInserter;
    }

    @Override
    public PerPatchsetOperations patchset(PatchSet.Id patchsetId) {
      return perPatchsetOperationsFactory.create(getChangeNotes(), patchsetId);
    }

    @Override
    public PerPatchsetOperations currentPatchset() {
      ChangeNotes changeNotes = getChangeNotes();
      return perPatchsetOperationsFactory.create(
          changeNotes, changeNotes.getChange().currentPatchSetId());
    }

    @Override
    public TestVoteCreation.Builder newVote() {
      return TestVoteCreation.builder(this::createVote);
    }

    private TestVote createVote(TestVoteCreation voteCreation)
        throws IOException, RestApiException, UpdateException, ConfigInvalidException {
      ChangeNotes changeNotes = getChangeNotes();
      Project.NameKey project = changeNotes.getProjectName();
      IdentifiedUser voter = getVoter(changeNotes.getChange().getOwner(), voteCreation);
      LabelType label = getLabel(changeNotes.getChange().getDest(), voteCreation);
      short value = getLabelValue(label, voteCreation);
      try (RefUpdateContext ctx = openTestRefUpdateContext();
          Repository repository = repositoryManager.openRepository(project);
          ObjectInserter objectInserter = repository.newObjectInserter();
          RevWalk revWalk = new RevWalk(objectInserter.newReader());
          BatchUpdate batchUpdate = batchUpdateFactory.create(project, voter, TimeUtil.now())) {
        batchUpdate.setRepository(repository, revWalk, objectInserter);
        batchUpdate.addOp(
            changeNotes.getChangeId(),
            new BatchUpdateOp() {
              @Override
              public boolean updateChange(ChangeContext ctx) throws Exception {
                ctx.getUpdate(changeNotes.getCurrentPatchSet().id())
                    .putApproval(label.getName(), value);
                return true;
              }
            });
        batchUpdate.execute();

        return TestVote.builder()
            .userId(voter.getAccountId())
            .label(label.getName())
            .value(value)
            .build();
      }
    }

    private IdentifiedUser getVoter(Account.Id changeOwnerId, TestVoteCreation voteCreation)
        throws IOException, ConfigInvalidException {
      if (voteCreation.user().isPresent()) {
        checkState(
            accountCache.get(voteCreation.user().get()).isPresent(),
            "account %s not found",
            voteCreation.user().get());
        return userFactory.create(voteCreation.user().get());
      }

      return getArbitraryUser(accountId -> !accountId.equals(changeOwnerId));
    }

    private LabelType getLabel(BranchNameKey dest, TestVoteCreation voteCreation) {
      ProjectState state =
          projectCache.get(dest.project()).orElseThrow(illegalState(dest.project()));
      LabelTypes labelTypes = state.getLabelTypes(dest);
      if (voteCreation.label().isPresent()) {
        Optional<LabelType> labelType = labelTypes.byLabel(voteCreation.label().get());
        checkState(labelType.isPresent(), "label %s not found", voteCreation.label().get());
        return labelType.get();
      }

      return labelTypes.getLabelTypes().stream()
          .filter(labelType -> !LabelFunction.PATCH_SET_LOCK.equals(labelType.getFunction()))
          .findAny()
          .orElseThrow(() -> new IllegalStateException("At least one label must be available"));
    }

    private short getLabelValue(LabelType labelType, TestVoteCreation voteCreation) {
      if (voteCreation.value().isPresent()) {
        checkState(
            labelType.getByValue().keySet().contains(voteCreation.value().get().shortValue()),
            "value %s not found for label %s",
            voteCreation.value().get(),
            labelType.getName());
        return voteCreation.value().get().shortValue();
      }

      return labelType.getByValue().keySet().stream()
          .filter(value -> value != 0)
          .findAny()
          .orElseThrow(() -> new IllegalStateException("At least one value must be available"));
    }

    @Override
    public PerCommentOperations comment(String commentUuid) {
      ChangeNotes changeNotes = getChangeNotes();
      return perCommentOperationsFactory.create(changeNotes, commentUuid);
    }

    @Override
    public PerDraftCommentOperations draftComment(String commentUuid) {
      ChangeNotes changeNotes = getChangeNotes();
      return perDraftCommentOperationsFactory.create(changeNotes, commentUuid);
    }
  }
}
