// 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 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.Date;
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);
      clean.execute();

      /* 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);
      clean.execute();

      /* 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 */
      clean.execute();
      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);

      clean.execute();

      /* 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);
      clean.execute();

      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);
    }
    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);
    update.update();
    return repo.exactRef(refName);
  }

  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
  // Instants
  @SuppressWarnings("JdkObsolete")
  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"), Date.from(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;
    }
  }
}
