// 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.server.notedb;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.entities.RefNames.REFS_DRAFT_COMMENTS;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;
import static org.eclipse.jgit.lib.Constants.EMPTY_TREE_ID;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.DeleteZombieComments;
import com.google.gerrit.server.DraftCommentsReader;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.ReceiveCommand;

/**
 * This class can be used to clean zombie draft comments from NoteDB.
 *
 * <p>See {@link DeleteZombieComments} for more info.
 */
public class DeleteZombieCommentsRefs extends DeleteZombieComments<Ref> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  // Number of refs deleted at once in a batch ref-update.
  // Log progress after deleting every CHUNK_SIZE refs
  private static final int CHUNK_SIZE = 3000;

  private final GitRepositoryManager repoManager;
  private final AllUsersName allUsers;

  @Nullable private final ChangeUpdate.Factory changeUpdateFactory;
  @Nullable private final IdentifiedUser.GenericFactory userFactory;

  private Repository allUsersRepo;

  public interface Factory {
    DeleteZombieCommentsRefs create(int cleanupPercentage);

    DeleteZombieCommentsRefs create(int cleanupPercentage, boolean dryRun);
  }

  @AssistedInject
  public DeleteZombieCommentsRefs(
      @Assisted Integer cleanupPercentage,
      GitRepositoryManager repoManager,
      AllUsersName allUsers,
      DraftCommentsReader draftCommentsReader,
      ChangeNotes.Factory changeNotesFactory,
      CommentsUtil commentsUtil,
      ChangeUpdate.Factory changeUpdateFactory,
      IdentifiedUser.GenericFactory userFactory) {
    this(
        cleanupPercentage,
        /* dryRun= */ false,
        (msg) -> {},
        repoManager,
        allUsers,
        draftCommentsReader,
        changeNotesFactory,
        commentsUtil,
        changeUpdateFactory,
        userFactory);
  }

  @AssistedInject
  public DeleteZombieCommentsRefs(
      @Assisted Integer cleanupPercentage,
      @Assisted boolean dryRun,
      GitRepositoryManager repoManager,
      AllUsersName allUsers,
      DraftCommentsReader draftCommentsReader,
      ChangeNotes.Factory changeNotesFactory,
      CommentsUtil commentsUtil,
      ChangeUpdate.Factory changeUpdateFactory,
      IdentifiedUser.GenericFactory userFactory) {
    this(
        cleanupPercentage,
        dryRun,
        (msg) -> {},
        repoManager,
        allUsers,
        draftCommentsReader,
        changeNotesFactory,
        commentsUtil,
        changeUpdateFactory,
        userFactory);
  }

  public DeleteZombieCommentsRefs(
      AllUsersName allUsers,
      GitRepositoryManager repoManager,
      Integer cleanupPercentage,
      Consumer<String> uiConsumer) {
    this(
        cleanupPercentage,
        /* dryRun= */ false,
        uiConsumer,
        repoManager,
        allUsers,
        null,
        null,
        null,
        null,
        null);
  }

  private DeleteZombieCommentsRefs(
      Integer cleanupPercentage,
      boolean dryRun,
      Consumer<String> uiConsumer,
      GitRepositoryManager repoManager,
      AllUsersName allUsers,
      @Nullable DraftCommentsReader draftCommentsReader,
      @Nullable ChangeNotes.Factory changeNotesFactory,
      @Nullable CommentsUtil commentsUtil,
      @Nullable ChangeUpdate.Factory changeUpdateFactory,
      @Nullable IdentifiedUser.GenericFactory userFactory) {
    super(
        cleanupPercentage,
        dryRun,
        uiConsumer,
        repoManager,
        draftCommentsReader,
        changeNotesFactory,
        commentsUtil);
    this.allUsers = allUsers;
    this.repoManager = repoManager;
    this.changeUpdateFactory = changeUpdateFactory;
    this.userFactory = userFactory;
  }

  @Override
  public void setup() throws IOException {
    allUsersRepo = repoManager.openRepository(allUsers);
  }

  @Override
  public void close() throws IOException {
    allUsersRepo.close();
  }

  @Override
  protected List<Ref> listAllDrafts() throws IOException {
    return allUsersRepo.getRefDatabase().getRefsByPrefix(REFS_DRAFT_COMMENTS);
  }

  @Override
  protected List<Ref> listEmptyDrafts() throws IOException {
    List<Ref> zombieRefs = filterZombieRefs(allUsersRepo, listAllDrafts());
    logInfo(
        String.format(
            "Found a total of %d zombie draft refs in %s repo.",
            zombieRefs.size(), allUsers.get()));
    return zombieRefs;
  }

  /**
   * An earlier bug in the deletion of draft comments {@code
   * refs/draft-comments/$change_id_short/$change_id/$user_id} caused some draft refs to remain in
   * Git and not get deleted. These refs point to an empty tree. We delete such refs.
   */
  @Override
  protected void deleteEmptyDraftsByKey(Collection<Ref> refs) {
    long zombieRefsCnt = refs.size();
    long deletedRefsCnt = 0;
    long startTime = System.currentTimeMillis();

    for (List<Ref> refsBatch : Iterables.partition(refs, CHUNK_SIZE)) {
      try {
        deleteZombieDraftsBatch(refsBatch);
        long elapsed = (System.currentTimeMillis() - startTime) / 1000;
        deletedRefsCnt += refsBatch.size();
        logProgress(deletedRefsCnt, zombieRefsCnt, elapsed);
      } catch (Exception error) {
        logger.atWarning().withCause(error).log("Failed to delete drafts as a batch");
      }
    }
  }

  @Override
  protected void deleteZombieDrafts(ListMultimap<Ref, HumanComment> drafts) {
    for (Map.Entry<Ref, Collection<HumanComment>> e : drafts.asMap().entrySet()) {
      try {
        deleteZombieDraftsForChange(
            getAccountId(e.getKey()), getChangeNotes(getChangeId(e.getKey())), e.getValue());
      } catch (Exception error) {
        logger.atWarning().withCause(error).log(
            "Failed to delete draft for change %s account %s",
            getChangeId(e.getKey()), getAccountId(e.getKey()));
      }
    }
  }

  @Override
  protected Change.Id getChangeId(Ref ref) {
    return Change.Id.fromAllUsersRef(ref.getName());
  }

  @Override
  protected Account.Id getAccountId(Ref ref) {
    return Account.Id.fromRef(ref.getName());
  }

  @Override
  protected String loggable(Ref ref) {
    return ref.getName();
  }

  private List<Ref> filterZombieRefs(Repository allUsersRepo, List<Ref> allDraftRefs)
      throws IOException {
    List<Ref> zombieRefs = new ArrayList<>((int) (allDraftRefs.size() * 0.5));
    for (Ref ref : allDraftRefs) {
      if (isZombieRef(allUsersRepo, ref)) {
        zombieRefs.add(ref);
      }
    }
    return zombieRefs;
  }

  private boolean isZombieRef(Repository allUsersRepo, Ref ref) throws IOException {
    return allUsersRepo.parseCommit(ref.getObjectId()).getTree().getId().equals(EMPTY_TREE_ID);
  }

  private void logProgress(long deletedRefsCount, long allRefsCount, long elapsed) {
    logInfo(
        String.format(
            "Deleted %d/%d zombie draft refs (%d seconds)",
            deletedRefsCount, allRefsCount, elapsed));
  }

  private void deleteZombieDraftsBatch(Collection<Ref> refsBatch) throws IOException {
    try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
      ImmutableList<ReceiveCommand> deleteCommands =
          refsBatch.stream()
              .map(
                  zombieRef ->
                      new ReceiveCommand(
                          zombieRef.getObjectId(), ObjectId.zeroId(), zombieRef.getName()))
              .collect(toImmutableList());
      BatchRefUpdate bru = allUsersRepo.getRefDatabase().newBatchUpdate();
      bru.setAtomic(true);
      bru.addCommand(deleteCommands);
      RefUpdateUtil.executeChecked(bru, allUsersRepo);
    }
  }

  /**
   * Accepts a list of draft (zombie) comments for the same change and delete them by executing a
   * {@link ChangeUpdate} on NoteDb. The update is executed using the user account who created this
   * draft.
   */
  private void deleteZombieDraftsForChange(
      Account.Id accountId, ChangeNotes changeNotes, Collection<HumanComment> draftsToDelete)
      throws IOException {
    if (changeUpdateFactory == null || userFactory == null) {
      return;
    }
    ChangeUpdate changeUpdate =
        changeUpdateFactory.create(changeNotes, userFactory.create(accountId), TimeUtil.now());
    draftsToDelete.forEach(c -> changeUpdate.deleteComment(c));
    changeUpdate.commit();
    logger.atInfo().log(
        "Deleted zombie draft comments with UUIDs %s",
        draftsToDelete.stream().map(d -> d.key.uuid).collect(toImmutableList()));
  }
}
