// 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.git;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.TestActionRefUpdateContext.testRefAction;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.notedb.DeleteZombieCommentsRefs;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.testing.InMemoryRepositoryManager;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
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.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TreeFormatter;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class DeleteZombieCommentsRefsTest {
  private InMemoryRepositoryManager repoManager = new InMemoryRepositoryManager();
  private Project.NameKey allUsersProject = Project.nameKey("All-Users");

  @Test
  public void cleanZombieDraftsSmall() throws Exception {
    try (Repository usersRepo = repoManager.createRepository(allUsersProject)) {
      Ref ref1 = createRefWithNonEmptyTreeCommit(usersRepo, 1, 1000001);
      Ref ref2 = createRefWithEmptyTreeCommit(usersRepo, 1, 1000002);

      DeleteZombieCommentsRefs clean =
          new DeleteZombieCommentsRefs(
              new AllUsersName("All-Users"), repoManager, null, (msg) -> {});
      int deletedDrafts = clean.execute();
      assertThat(deletedDrafts).isEqualTo(1);

      /* Check that ref1 still exists, and ref2 is deleted */
      assertThat(usersRepo.exactRef(ref1.getName())).isNotNull();
      assertThat(usersRepo.exactRef(ref2.getName())).isNull();
    }
  }

  @Test
  public void cleanZombieDraftsWithPercentage() throws Exception {
    try (Repository usersRepo = repoManager.createRepository(allUsersProject)) {
      Ref ref1 = createRefWithNonEmptyTreeCommit(usersRepo, 1005, 1000001);
      Ref ref2 = createRefWithEmptyTreeCommit(usersRepo, 1006, 1000002);
      Ref ref3 = createRefWithEmptyTreeCommit(usersRepo, 1060, 1000002);

      assertThat(usersRepo.getRefDatabase().getRefs()).hasSize(3);

      int cleanupPercentage = 50;
      DeleteZombieCommentsRefs clean =
          new DeleteZombieCommentsRefs(
              new AllUsersName("All-Users"), repoManager, cleanupPercentage, (msg) -> {});
      int deletedDrafts = clean.execute();
      assertThat(deletedDrafts).isEqualTo(1);

      /* ref1 not deleted, ref2 deleted, ref3 not deleted because of the clean percentage */
      assertThat(usersRepo.getRefDatabase().getRefs()).hasSize(2);
      assertThat(usersRepo.exactRef(ref1.getName())).isNotNull();
      assertThat(usersRepo.exactRef(ref2.getName())).isNull();
      assertThat(usersRepo.exactRef(ref3.getName())).isNotNull();

      /* Re-execute the cleanup and make sure nothing's changed */
      deletedDrafts = clean.execute();
      assertThat(deletedDrafts).isEqualTo(0);
      assertThat(usersRepo.getRefDatabase().getRefs()).hasSize(2);
      assertThat(usersRepo.exactRef(ref1.getName())).isNotNull();
      assertThat(usersRepo.exactRef(ref2.getName())).isNull();
      assertThat(usersRepo.exactRef(ref3.getName())).isNotNull();

      /* Increase the cleanup percentage */
      cleanupPercentage = 70;
      clean =
          new DeleteZombieCommentsRefs(
              new AllUsersName("All-Users"), repoManager, cleanupPercentage, (msg) -> {});

      deletedDrafts = clean.execute();
      assertThat(deletedDrafts).isEqualTo(1);

      /* Now ref3 is deleted */
      assertThat(usersRepo.getRefDatabase().getRefs()).hasSize(1);
      assertThat(usersRepo.exactRef(ref1.getName())).isNotNull();
      assertThat(usersRepo.exactRef(ref2.getName())).isNull();
      assertThat(usersRepo.exactRef(ref3.getName())).isNull();
    }
  }

  @Test
  public void cleanZombieDraftsLarge() throws Exception {
    try (Repository usersRepo = repoManager.createRepository(allUsersProject)) {
      int goodRefsCnt = 5000;
      int zombieRefsCnt = 5000;
      int userIdGoodRefs = 1000001;
      int userIdBadRefs = 1000002;

      Ref nonEmptyBaseRef = createRefWithNonEmptyTreeCommit(usersRepo, 1, userIdGoodRefs);
      Ref emptyBaseRef = createRefWithEmptyTreeCommit(usersRepo, 1, userIdBadRefs);

      List<String> goodRefs =
          createNRefsOnCommit(
              usersRepo, nonEmptyBaseRef.getObjectId(), goodRefsCnt, userIdGoodRefs);
      List<String> badRefs =
          createNRefsOnCommit(usersRepo, emptyBaseRef.getObjectId(), zombieRefsCnt, userIdBadRefs);

      goodRefs.add(0, nonEmptyBaseRef.getName());
      badRefs.add(0, emptyBaseRef.getName());

      assertThat(usersRepo.getRefDatabase().getRefs().size())
          .isEqualTo(goodRefs.size() + badRefs.size());

      DeleteZombieCommentsRefs clean =
          new DeleteZombieCommentsRefs(
              new AllUsersName("All-Users"), repoManager, null, (msg) -> {});
      int deletedDrafts = clean.execute();
      assertThat(deletedDrafts).isEqualTo(5001);

      assertThat(
              usersRepo.getRefDatabase().getRefs().stream()
                  .map(Ref::getName)
                  .collect(toImmutableList()))
          .containsExactlyElementsIn(goodRefs);

      assertThat(
              usersRepo.getRefDatabase().getRefs().stream()
                  .map(Ref::getName)
                  .collect(toImmutableList()))
          .containsNoneIn(badRefs);
    }
  }

  private static List<String> createNRefsOnCommit(
      Repository usersRepo, ObjectId commitId, int n, int uuid) throws IOException {
    List<String> refNames = new ArrayList<>();
    BatchRefUpdate bru = usersRepo.getRefDatabase().newBatchUpdate();
    bru.setAtomic(true);
    for (int i = 2; i <= n + 1; i++) {
      String refName = getRefName(i, uuid);
      bru.addCommand(
          new ReceiveCommand(ObjectId.zeroId(), commitId, refName, ReceiveCommand.Type.CREATE));
      refNames.add(refName);
    }
    testRefAction(() -> RefUpdateUtil.executeChecked(bru, usersRepo));
    return refNames;
  }

  private static String getRefName(int changeId, int userId) {
    Change.Id cId = Change.id(changeId);
    Account.Id aId = Account.id(userId);
    return RefNames.refsDraftComments(cId, aId);
  }

  private static Ref createRefWithNonEmptyTreeCommit(Repository usersRepo, int changeId, int userId)
      throws IOException {
    try (RevWalk rw = new RevWalk(usersRepo)) {
      ObjectId fileObj = createBlob(usersRepo, String.format("file %d content", changeId));
      ObjectId treeObj =
          createTree(usersRepo, rw.lookupBlob(fileObj), String.format("file%d.txt", changeId));
      ObjectId commitObj = createCommit(usersRepo, treeObj, null);
      Ref refObj = createRef(usersRepo, commitObj, getRefName(changeId, userId));
      return refObj;
    }
  }

  private static Ref createRefWithEmptyTreeCommit(Repository usersRepo, int changeId, int userId)
      throws IOException {
    ObjectId treeEmpty = createTree(usersRepo, null, "");
    ObjectId commitObj = createCommit(usersRepo, treeEmpty, null);
    Ref refObj = createRef(usersRepo, commitObj, getRefName(changeId, userId));
    return refObj;
  }

  private static Ref createRef(Repository repo, ObjectId commitId, String refName)
      throws IOException {
    RefUpdate update = repo.updateRef(refName);
    update.setNewObjectId(commitId);
    update.setForceUpdate(true);
    testRefAction(() -> update.update());
    return repo.exactRef(refName);
  }

  private static ObjectId createCommit(Repository repo, ObjectId treeId, ObjectId parentCommit)
      throws IOException {
    try (ObjectInserter oi = repo.newObjectInserter()) {
      PersonIdent committer =
          new PersonIdent(new PersonIdent("Foo Bar", "foo.bar@baz.com"), TimeUtil.now());
      CommitBuilder cb = new CommitBuilder();
      cb.setTreeId(treeId);
      cb.setCommitter(committer);
      cb.setAuthor(committer);
      cb.setMessage("Test commit");
      if (parentCommit != null) {
        cb.setParentIds(parentCommit);
      }
      ObjectId commitId = oi.insert(cb);
      oi.flush();
      oi.close();
      return commitId;
    }
  }

  private static ObjectId createTree(Repository repo, RevBlob blob, String blobName)
      throws IOException {
    try (ObjectInserter oi = repo.newObjectInserter()) {
      TreeFormatter formatter = new TreeFormatter();
      if (blob != null) {
        formatter.append(blobName, blob);
      }
      ObjectId treeId = oi.insert(formatter);
      oi.flush();
      oi.close();
      return treeId;
    }
  }

  private static ObjectId createBlob(Repository repo, String content) throws IOException {
    try (ObjectInserter oi = repo.newObjectInserter()) {
      ObjectId blobId = oi.insert(Constants.OBJ_BLOB, content.getBytes(UTF_8));
      oi.flush();
      oi.close();
      return blobId;
    }
  }
}
