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

import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.server.notedb.ChangeNoteJson;
import com.google.gerrit.server.notedb.DeleteZombieCommentsRefs;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gson.JsonParser;
import com.google.inject.Inject;
import java.util.List;
import org.apache.commons.lang3.reflect.TypeLiteral;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.junit.Before;
import org.junit.Test;

/** Test for {@link com.google.gerrit.server.notedb.DeleteZombieCommentsRefs}. */
public class DeleteZombieDraftIT extends AbstractDaemonTest {
  private static final String TEST_PARAMETER_MARKER = "test_only_parameter";

  @Inject private DeleteZombieCommentsRefs.Factory deleteZombieDraftsFactory;
  @Inject private ChangeNoteJson changeNoteJson;
  private boolean dryRun;

  @ConfigSuite.Default
  public static Config dryRunMode() {
    Config config = new Config();
    config.setBoolean(TEST_PARAMETER_MARKER, null, "dryRun", true);
    return config;
  }

  @ConfigSuite.Config
  public static Config deleteMode() {
    Config config = new Config();
    config.setBoolean(TEST_PARAMETER_MARKER, null, "dryRun", false);
    return config;
  }

  @Before
  public void setUp() throws Exception {
    dryRun = baseConfig.getBoolean(TEST_PARAMETER_MARKER, "dryRun", true);
  }

  @Test
  public void draftRefWithOneZombie() throws Exception {
    PushOneCommit.Result r = createChange();
    String changeId = r.getChangeId();
    String revId = r.getCommit().getName();

    // Create a draft. A draft ref is created for this draft comment.
    addDraft(changeId, revId, "comment 1");
    Ref draftRef = getOnlyDraftRef();
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), revId)).hasSize(1);
    // Publish the draft. The draft ref is deleted.
    publishAllDrafts(r);
    assertNumDrafts(changeId, 0);
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), revId)).isEmpty();
    assertNumPublishedComments(changeId, 1);

    // Restore the draft ref. Now the same comment exists as draft and published -> zombie.
    restoreRef(draftRef.getName(), draftRef.getObjectId());
    draftRef = getOnlyDraftRef();
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), revId)).hasSize(1);

    // Run the cleanup logic. The zombie draft is cleared. The published comment is untouched.
    DeleteZombieCommentsRefs worker =
        deleteZombieDraftsFactory.create(/* cleanupPercentage= */ 100, dryRun);
    assertThat(worker.deleteDraftCommentsThatAreAlsoPublished()).isEqualTo(1);
    if (dryRun) {
      assertThat(getDraftsByParsingDraftRef(draftRef.getName(), revId)).hasSize(1);
    } else {
      assertThat(getDraftsByParsingDraftRef(draftRef.getName(), revId)).isEmpty();
    }
    assertNumPublishedComments(changeId, 1);
  }

  @Test
  public void draftRefWithOneDraftAndOneZombie() throws Exception {
    PushOneCommit.Result r1 = createChange();
    String changeId = r1.getChangeId();
    PushOneCommit.Result r2 = amendChange(changeId);

    // Add two draft comments: one on PS1, the other on PS2
    addDraft(changeId, r1.getCommit().getName(), "comment 1");
    CommentInfo c2 = addDraft(changeId, r2.getCommit().getName(), "comment 2");
    Ref draftRef = getOnlyDraftRef();

    // Publish the draft on PS2. Now PS1 still has one draft, PS2 has no drafts
    publishDraft(r2, c2.id);
    assertNumDrafts(changeId, 1);
    assertNumPublishedComments(changeId, 1);
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r1.getCommit().name())).hasSize(1);
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r2.getCommit().name())).isEmpty();

    // Restore the draft ref for PS2 draft. Now draft on PS2 is zombie because it is also published.
    restoreRef(draftRef.getName(), draftRef.getObjectId());
    draftRef = getOnlyDraftRef();
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r1.getCommit().name())).hasSize(1);
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r2.getCommit().name())).hasSize(1);

    // Run the zombie cleanup logic. Zombie draft ref for PS2 will be removed.
    DeleteZombieCommentsRefs worker =
        deleteZombieDraftsFactory.create(/* cleanupPercentage= */ 100, dryRun);
    assertThat(worker.deleteDraftCommentsThatAreAlsoPublished()).isEqualTo(1);
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r1.getCommit().name())).hasSize(1);
    if (dryRun) {
      assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r2.getCommit().name())).hasSize(1);
    } else {
      assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r2.getCommit().name())).isEmpty();
    }
    assertNumPublishedComments(changeId, 1);

    // Re-run the worker: nothing happens.
    assertThat(worker.deleteDraftCommentsThatAreAlsoPublished()).isEqualTo(dryRun ? 1 : 0);
    assertNumDrafts(changeId, 1);
    assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r1.getCommit().name())).hasSize(1);
    if (dryRun) {
      assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r2.getCommit().name())).hasSize(1);
    } else {
      assertThat(getDraftsByParsingDraftRef(draftRef.getName(), r2.getCommit().name())).isEmpty();
    }
    assertNumPublishedComments(changeId, 1);
  }

  private Ref getOnlyDraftRef() throws Exception {
    try (Repository allUsersRepo = repoManager.openRepository(allUsers)) {
      return Iterables.getOnlyElement(
          allUsersRepo.getRefDatabase().getRefsByPrefix(RefNames.REFS_DRAFT_COMMENTS));
    }
  }

  private void publishAllDrafts(PushOneCommit.Result r) throws Exception {
    ReviewInput reviewInput = new ReviewInput();
    reviewInput.drafts = DraftHandling.PUBLISH_ALL_REVISIONS;
    reviewInput.message = "foo";
    revision(r).review(reviewInput);
  }

  private void publishDraft(PushOneCommit.Result r, String draftId) throws Exception {
    ReviewInput reviewInput = new ReviewInput();
    reviewInput.drafts = DraftHandling.PUBLISH_ALL_REVISIONS;
    reviewInput.message = "foo";
    reviewInput.draftIdsToPublish = ImmutableList.of(draftId);
    revision(r).review(reviewInput);
  }

  private List<CommentInfo> getDraftComments(String changeId) throws Exception {
    return gApi.changes().id(changeId).draftsRequest().getAsList();
  }

  private List<CommentInfo> getPublishedComments(String changeId) throws Exception {
    return gApi.changes().id(changeId).commentsRequest().getAsList();
  }

  private CommentInfo addDraft(String changeId, String revId, String commentText) throws Exception {
    DraftInput comment = CommentsUtil.newDraft("f1.txt", Side.REVISION, /* line= */ 1, commentText);
    return gApi.changes().id(changeId).revision(revId).createDraft(comment).get();
  }

  private void restoreRef(String refName, ObjectId id) throws Exception {
    try (Repository allUsersRepo = repoManager.openRepository(allUsers)) {
      RefUpdate u = allUsersRepo.updateRef(refName);
      u.setNewObjectId(id);
      u.forceUpdate();
    }
  }

  /**
   * Returns all draft comments that are stored in {@code draftRefStr} for a specific revision
   * (patchset) identified by its {@code blobFile} SHA-1.
   *
   * <p>Background: This ref points to a tree containing one or more blob files, each named after
   * the patchset revision SHA-1, that is drafts for each patchset are stored in a separate blob
   * file.
   */
  private List<HumanComment> getDraftsByParsingDraftRef(String draftRefStr, String blobFile)
      throws Exception {
    try (Repository allUsersRepo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(allUsersRepo)) {
      Ref draftRef = allUsersRepo.exactRef(draftRefStr);
      if (draftRef == null) {
        // draft ref does not exist, i.e. no draft comments stored for this ref.
        return ImmutableList.of();
      }
      RevTree revTree = rw.parseTree(draftRef.getObjectId());
      TreeWalk tw = TreeWalk.forPath(allUsersRepo, blobFile, revTree);
      if (tw == null) {
        // blobFile does not exist, i.e. no draft comments for this revision.
        return ImmutableList.of();
      }
      ObjectLoader open = allUsersRepo.open(tw.getObjectId(0));
      String content = new String(open.getBytes(), UTF_8);
      List<HumanComment> drafts =
          changeNoteJson
              .getGson()
              .fromJson(
                  JsonParser.parseString(content)
                      .getAsJsonObject()
                      .getAsJsonArray("comments")
                      .toString(),
                  new TypeLiteral<ImmutableList<HumanComment>>() {}.getType());
      return drafts;
    }
  }

  private void assertNumDrafts(String changeId, int num) throws Exception {
    assertThat(getDraftComments(changeId)).hasSize(num);
  }

  private void assertNumPublishedComments(String changeId, int num) throws Exception {
    assertThat(getPublishedComments(changeId)).hasSize(num);
  }
}
