// Copyright (C) 2017 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.api.group;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.common.testing.CommitInfoSubject.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupById;
import com.google.gerrit.reviewdb.client.AccountGroupByIdAud;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.git.CommitUtil;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.group.db.GroupBundle;
import com.google.gerrit.server.group.db.GroupRebuilder;
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.notedb.GroupsMigration;
import com.google.gerrit.testing.TestTimeUtil;
import com.google.gerrit.testing.TestTimeUtil.TempClockStep;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

@NoHttpd
public class GroupRebuilderIT extends AbstractDaemonTest {
  @Inject @GerritServerId private String serverId;
  @Inject @ServerInitiated private Provider<GroupsUpdate> groupsUpdate;
  @Inject private GroupBundle.Factory bundleFactory;
  @Inject private GroupRebuilder rebuilder;
  @Inject private GroupsMigration migration;

  @Before
  public void setUp() {
    // This test is explicitly testing the migration from ReviewDb to NoteDb, and handles reading
    // from NoteDb manually. It should work regardless of the value of noteDb.groups.write, however.
    assume().that(migration.readFromNoteDb()).isFalse();
  }

  @Before
  public void setTimeForTesting() {
    TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
  }

  @After
  public void resetTime() {
    TestTimeUtil.useSystemTime();
  }

  @Test
  public void basicGroupProperties() throws Exception {
    GroupInfo createdGroup = gApi.groups().create(name("group")).get();
    GroupBundle reviewDbBundle =
        GroupBundle.Factory.fromReviewDb(db, new AccountGroup.UUID(createdGroup.id));
    deleteGroupRefs(reviewDbBundle);

    assertMigratedCleanly(rebuild(reviewDbBundle), reviewDbBundle);
  }

  @Test
  public void logFormat() throws Exception {
    TestAccount user2 = accountCreator.user2();
    GroupInfo group1 = gApi.groups().create(name("group1")).get();
    GroupInfo group2 = gApi.groups().create(name("group2")).get();

    try (TempClockStep step = TestTimeUtil.freezeClock()) {
      gApi.groups().id(group1.id).addMembers(user.id.toString(), user2.id.toString());
    }
    TimeUtil.nowTs();

    try (TempClockStep step = TestTimeUtil.freezeClock()) {
      gApi.groups().id(group1.id).addGroups(group2.id, SystemGroupBackend.REGISTERED_USERS.get());
    }

    GroupBundle reviewDbBundle =
        GroupBundle.Factory.fromReviewDb(db, new AccountGroup.UUID(group1.id));
    deleteGroupRefs(reviewDbBundle);

    GroupBundle noteDbBundle = rebuild(reviewDbBundle);
    assertMigratedCleanly(noteDbBundle, reviewDbBundle);

    ImmutableList<CommitInfo> log = log(group1);
    assertThat(log).hasSize(4);

    assertThat(log.get(0)).message().isEqualTo("Create group");
    assertThat(log.get(0)).author().name().isEqualTo(serverIdent.get().getName());
    assertThat(log.get(0)).author().email().isEqualTo(serverIdent.get().getEmailAddress());
    assertThat(log.get(0)).author().date().isEqualTo(noteDbBundle.group().getCreatedOn());
    assertThat(log.get(0)).author().tz().isEqualTo(serverIdent.get().getTimeZoneOffset());
    assertThat(log.get(0)).committer().isEqualTo(log.get(0).author);

    assertThat(log.get(1))
        .message()
        .isEqualTo("Update group\n\nAdd: Administrator <" + admin.id + "@" + serverId + ">");
    assertThat(log.get(1)).author().name().isEqualTo(admin.fullName);
    assertThat(log.get(1)).author().email().isEqualTo(admin.id + "@" + serverId);
    assertThat(log.get(1)).committer().hasSameDateAs(log.get(1).author);

    assertThat(log.get(2))
        .message()
        .isEqualTo(
            "Update group\n"
                + "\n"
                + ("Add: User <" + user.id + "@" + serverId + ">\n")
                + ("Add: User2 <" + user2.id + "@" + serverId + ">"));
    assertThat(log.get(2)).author().name().isEqualTo(admin.fullName);
    assertThat(log.get(2)).author().email().isEqualTo(admin.id + "@" + serverId);
    assertThat(log.get(2)).committer().hasSameDateAs(log.get(2).author);

    assertThat(log.get(3))
        .message()
        .isEqualTo(
            "Update group\n"
                + "\n"
                + ("Add-group: " + group2.name + " <" + group2.id + ">\n")
                + ("Add-group: Registered Users <global:Registered-Users>"));
    assertThat(log.get(3)).author().name().isEqualTo(admin.fullName);
    assertThat(log.get(3)).author().email().isEqualTo(admin.id + "@" + serverId);
    assertThat(log.get(3)).committer().hasSameDateAs(log.get(3).author);
  }

  @Test
  public void unknownGroupUuid() throws Exception {
    GroupInfo group = gApi.groups().create(name("group")).get();

    AccountGroup.UUID subgroupUuid = new AccountGroup.UUID("mybackend:foo");

    AccountGroupById byId =
        new AccountGroupById(
            new AccountGroupById.Key(new AccountGroup.Id(group.groupId), subgroupUuid));
    assertThat(groupBackend.handles(byId.getIncludeUUID())).isFalse();
    db.accountGroupById().insert(Collections.singleton(byId));

    AccountGroupByIdAud audit = new AccountGroupByIdAud(byId, admin.id, TimeUtil.nowTs());
    db.accountGroupByIdAud().insert(Collections.singleton(audit));

    GroupBundle reviewDbBundle =
        GroupBundle.Factory.fromReviewDb(db, new AccountGroup.UUID(group.id));
    deleteGroupRefs(reviewDbBundle);

    GroupBundle noteDbBundle = rebuild(reviewDbBundle);
    assertMigratedCleanly(noteDbBundle, reviewDbBundle);

    ImmutableList<CommitInfo> log = log(group);
    assertThat(log).hasSize(3);

    assertThat(log.get(0)).message().isEqualTo("Create group");
    assertThat(log.get(1))
        .message()
        .isEqualTo("Update group\n\nAdd: Administrator <" + admin.id + "@" + serverId + ">");
    assertThat(log.get(2))
        .message()
        .isEqualTo("Update group\n\nAdd-group: mybackend:foo <mybackend:foo>");
  }

  private void deleteGroupRefs(GroupBundle bundle) throws Exception {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      String refName = RefNames.refsGroups(bundle.uuid());
      RefUpdate ru = repo.updateRef(refName);
      ru.setForceUpdate(true);
      Ref oldRef = repo.exactRef(refName);
      if (oldRef == null) {
        return;
      }
      ru.setExpectedOldObjectId(oldRef.getObjectId());
      ru.setNewObjectId(ObjectId.zeroId());
      assertThat(ru.delete()).isEqualTo(RefUpdate.Result.FORCED);
    }
  }

  private GroupBundle rebuild(GroupBundle reviewDbBundle) throws Exception {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      rebuilder.rebuild(repo, reviewDbBundle, null);
      return bundleFactory.fromNoteDb(repo, reviewDbBundle.uuid());
    }
  }

  private void assertMigratedCleanly(GroupBundle noteDbBundle, GroupBundle expectedReviewDbBundle) {
    assertThat(GroupBundle.compareWithAudits(expectedReviewDbBundle, noteDbBundle)).isEmpty();
  }

  private ImmutableList<CommitInfo> log(GroupInfo g) throws Exception {
    ImmutableList.Builder<CommitInfo> result = ImmutableList.builder();
    List<Date> commitDates = new ArrayList<>();
    try (Repository repo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(repo)) {
      Ref ref = repo.exactRef(RefNames.refsGroups(new AccountGroup.UUID(g.id)));
      if (ref != null) {
        rw.sort(RevSort.REVERSE);
        rw.setRetainBody(true);
        rw.markStart(rw.parseCommit(ref.getObjectId()));
        for (RevCommit c : rw) {
          result.add(CommitUtil.toCommitInfo(c));
          commitDates.add(c.getCommitterIdent().getWhen());
        }
      }
    }
    assertThat(commitDates).named("commit timestamps for %s", result).isOrdered();
    return result.build();
  }
}
