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

import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.GROUPS_UPDATE;
import static org.eclipse.jgit.lib.Constants.R_REFS;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.DuplicateKeyException;
import com.google.gerrit.exceptions.NoSuchGroupException;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupIncludeCache;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.group.GroupAuditService;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.ReceiveCommand;

/**
 * A database accessor for write calls related to groups.
 *
 * <p>All calls which write group related details to the database are gathered here. Other classes
 * should always use this class instead of accessing the database directly. There are a few
 * exceptions though: schema classes, wrapper classes, and classes executed during init. The latter
 * ones should use {@link com.google.gerrit.pgm.init.GroupsOnInit} instead.
 *
 * <p>If not explicitly stated, all methods of this class refer to <em>internal</em> groups.
 */
public class GroupsUpdate {
  public interface Factory {
    /**
     * Creates a {@link GroupsUpdate} which uses the identity of the specified user to mark database
     * modifications executed by it. For NoteDb, this identity is used as author and committer for
     * all related commits.
     *
     * <p><strong>Note</strong>: Please use this method with care and consider using the {@link
     * com.google.gerrit.server.UserInitiated} annotation on the provider of a {@link GroupsUpdate}
     * instead.
     *
     * @param currentUser the user to which modifications should be attributed
     */
    GroupsUpdate create(IdentifiedUser currentUser);

    /**
     * Creates a {@link GroupsUpdate} which uses the server identity to mark database modifications
     * executed by it. For NoteDb, this identity is used as author and committer for all related
     * commits.
     *
     * <p><strong>Note</strong>: Please use this method with care and consider using the {@link
     * com.google.gerrit.server.ServerInitiated} annotation on the provider of a {@link
     * GroupsUpdate} instead.
     */
    GroupsUpdate createWithServerIdent();
  }

  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final GitRepositoryManager repoManager;
  private final AllUsersName allUsersName;
  private final GroupCache groupCache;
  private final GroupIncludeCache groupIncludeCache;
  private final Provider<GroupIndexer> indexer;
  private final GroupAuditService groupAuditService;
  private final RenameGroupOp.Factory renameGroupOpFactory;
  private final Optional<IdentifiedUser> currentUser;
  private final AuditLogFormatter auditLogFormatter;
  private final PersonIdent authorIdent;
  private final MetaDataUpdateFactory metaDataUpdateFactory;
  private final GitReferenceUpdated gitRefUpdated;
  private final RetryHelper retryHelper;

  @AssistedInject
  GroupsUpdate(
      GitRepositoryManager repoManager,
      AllUsersName allUsersName,
      GroupBackend groupBackend,
      GroupCache groupCache,
      GroupIncludeCache groupIncludeCache,
      Provider<GroupIndexer> indexer,
      GroupAuditService auditService,
      AccountCache accountCache,
      RenameGroupOp.Factory renameGroupOpFactory,
      @GerritServerId String serverId,
      @GerritPersonIdent PersonIdent serverIdent,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper) {
    this(
        repoManager,
        allUsersName,
        groupBackend,
        groupCache,
        groupIncludeCache,
        indexer,
        auditService,
        accountCache,
        renameGroupOpFactory,
        serverId,
        serverIdent,
        metaDataUpdateInternalFactory,
        gitRefUpdated,
        retryHelper,
        Optional.empty());
  }

  @AssistedInject
  GroupsUpdate(
      GitRepositoryManager repoManager,
      AllUsersName allUsersName,
      GroupBackend groupBackend,
      GroupCache groupCache,
      GroupIncludeCache groupIncludeCache,
      Provider<GroupIndexer> indexer,
      GroupAuditService auditService,
      AccountCache accountCache,
      RenameGroupOp.Factory renameGroupOpFactory,
      @GerritServerId String serverId,
      @GerritPersonIdent PersonIdent serverIdent,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper,
      @Assisted IdentifiedUser currentUser) {
    this(
        repoManager,
        allUsersName,
        groupBackend,
        groupCache,
        groupIncludeCache,
        indexer,
        auditService,
        accountCache,
        renameGroupOpFactory,
        serverId,
        serverIdent,
        metaDataUpdateInternalFactory,
        gitRefUpdated,
        retryHelper,
        Optional.of(currentUser));
  }

  private GroupsUpdate(
      GitRepositoryManager repoManager,
      AllUsersName allUsersName,
      GroupBackend groupBackend,
      GroupCache groupCache,
      GroupIncludeCache groupIncludeCache,
      Provider<GroupIndexer> indexer,
      GroupAuditService auditService,
      AccountCache accountCache,
      RenameGroupOp.Factory renameGroupOpFactory,
      @GerritServerId String serverId,
      @GerritPersonIdent PersonIdent serverIdent,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper,
      Optional<IdentifiedUser> currentUser) {
    this.repoManager = repoManager;
    this.allUsersName = allUsersName;
    this.groupCache = groupCache;
    this.groupIncludeCache = groupIncludeCache;
    this.indexer = indexer;
    this.groupAuditService = auditService;
    this.renameGroupOpFactory = renameGroupOpFactory;
    this.gitRefUpdated = gitRefUpdated;
    this.retryHelper = retryHelper;
    this.currentUser = currentUser;

    auditLogFormatter = AuditLogFormatter.createBackedBy(accountCache, groupBackend, serverId);
    metaDataUpdateFactory =
        getMetaDataUpdateFactory(
            metaDataUpdateInternalFactory, currentUser, serverIdent, auditLogFormatter);
    authorIdent = getAuthorIdent(serverIdent, currentUser);
  }

  private static MetaDataUpdateFactory getMetaDataUpdateFactory(
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      Optional<IdentifiedUser> currentUser,
      PersonIdent serverIdent,
      AuditLogFormatter auditLogFormatter) {
    return (projectName, repository, batchRefUpdate) -> {
      MetaDataUpdate metaDataUpdate =
          metaDataUpdateInternalFactory.create(projectName, repository, batchRefUpdate);
      metaDataUpdate.getCommitBuilder().setCommitter(serverIdent);
      PersonIdent authorIdent;
      if (currentUser.isPresent()) {
        metaDataUpdate.setAuthor(currentUser.get());
        authorIdent =
            auditLogFormatter.getParsableAuthorIdent(currentUser.get().getAccount(), serverIdent);
      } else {
        authorIdent = serverIdent;
      }
      metaDataUpdate.getCommitBuilder().setAuthor(authorIdent);
      return metaDataUpdate;
    };
  }

  private static PersonIdent getAuthorIdent(
      PersonIdent serverIdent, Optional<IdentifiedUser> currentUser) {
    return currentUser.map(user -> createPersonIdent(serverIdent, user)).orElse(serverIdent);
  }

  private static PersonIdent createPersonIdent(PersonIdent ident, IdentifiedUser user) {
    return user.newCommitterIdent(ident);
  }

  /**
   * Creates the specified group for the specified members (accounts).
   *
   * @param groupCreation an {@link InternalGroupCreation} which specifies all mandatory properties
   *     of the group
   * @param groupDelta a {@link GroupDelta} which specifies optional properties of the group. If
   *     this {@link GroupDelta} updates a property which was already specified by the {@link
   *     InternalGroupCreation}, the value of this {@link GroupDelta} wins.
   * @throws DuplicateKeyException if a group with the chosen name already exists
   * @throws IOException if indexing fails, or an error occurs while reading/writing from/to NoteDb
   * @return the created {@link InternalGroup}
   */
  @CanIgnoreReturnValue
  public InternalGroup createGroup(InternalGroupCreation groupCreation, GroupDelta groupDelta)
      throws DuplicateKeyException, IOException, ConfigInvalidException {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Creating group",
            Metadata.builder()
                .groupName(groupDelta.getName().orElseGet(groupCreation::getNameKey).get())
                .build())) {
      InternalGroup createdGroup = createGroupInNoteDbWithRetry(groupCreation, groupDelta);
      evictCachesOnGroupCreation(createdGroup);
      dispatchAuditEventsOnGroupCreation(createdGroup);
      return createdGroup;
    }
  }

  /**
   * Updates the specified group.
   *
   * @param groupUuid the UUID of the group to update
   * @param groupDelta a {@link GroupDelta} which indicates the desired updates on the group
   * @throws DuplicateKeyException if the new name of the group is used by another group
   * @throws IOException if indexing fails, or an error occurs while reading/writing from/to NoteDb
   * @throws NoSuchGroupException if the specified group doesn't exist
   */
  public void updateGroup(AccountGroup.UUID groupUuid, GroupDelta groupDelta)
      throws DuplicateKeyException, IOException, NoSuchGroupException, ConfigInvalidException {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Updating group", Metadata.builder().groupUuid(groupUuid.get()).build())) {
      Optional<Instant> updatedOn = groupDelta.getUpdatedOn();
      if (!updatedOn.isPresent()) {
        updatedOn = Optional.of(TimeUtil.now());
        groupDelta = groupDelta.toBuilder().setUpdatedOn(updatedOn.get()).build();
      }

      UpdateResult result = updateGroupInNoteDbWithRetry(groupUuid, groupDelta);
      updateNameInProjectConfigsIfNecessary(result);
      evictCachesOnGroupUpdate(result);
      dispatchAuditEventsOnGroupUpdate(result, updatedOn.get());
    }
  }

  /**
   * Delete a specific group
   *
   * @param groupUuid the UUID of the group to delete
   * @throws ConfigInvalidException if removing group note failed
   * @throws IOException if indexing fails, or an error occurs while reading/writing from/to NoteDb
   */
  public void deleteGroup(AccountGroup.UUID groupUuid) throws ConfigInvalidException, IOException {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Deleting group", Metadata.builder().groupUuid(groupUuid.get()).build())) {
      DeleteResult result = deleteGroupInNoteDbWithRetry(groupUuid);
      evictCacheOnGroupDeletion(result);
    }
  }

  private InternalGroup createGroupInNoteDbWithRetry(
      InternalGroupCreation groupCreation, GroupDelta groupDelta)
      throws IOException, ConfigInvalidException, DuplicateKeyException {
    try (RefUpdateContext ctx = RefUpdateContext.open(GROUPS_UPDATE)) {
      try {
        return retryHelper
            .groupUpdate("createGroup", () -> createGroupInNoteDb(groupCreation, groupDelta))
            .call();
      } catch (Exception e) {
        Throwables.throwIfUnchecked(e);
        Throwables.throwIfInstanceOf(e, IOException.class);
        Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
        Throwables.throwIfInstanceOf(e, DuplicateKeyException.class);
        throw new IOException(e);
      }
    }
  }

  @VisibleForTesting
  public InternalGroup createGroupInNoteDb(
      InternalGroupCreation groupCreation, GroupDelta groupDelta)
      throws IOException, ConfigInvalidException, DuplicateKeyException {
    try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
      AccountGroup.NameKey groupName = groupDelta.getName().orElseGet(groupCreation::getNameKey);
      GroupNameNotes groupNameNotes =
          GroupNameNotes.forNewGroup(
              allUsersName, allUsersRepo, groupCreation.getGroupUUID(), groupName);

      GroupConfig groupConfig =
          GroupConfig.createForNewGroup(allUsersName, allUsersRepo, groupCreation);
      groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

      commit(allUsersRepo, groupConfig, groupNameNotes);

      return groupConfig
          .getLoadedGroup()
          .orElseThrow(
              () -> new IllegalStateException("Created group wasn't automatically loaded"));
    }
  }

  private UpdateResult updateGroupInNoteDbWithRetry(
      AccountGroup.UUID groupUuid, GroupDelta groupDelta)
      throws IOException, ConfigInvalidException, DuplicateKeyException, NoSuchGroupException {
    try {
      return retryHelper
          .groupUpdate("updateGroup", () -> updateGroupInNoteDb(groupUuid, groupDelta))
          .call();
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, IOException.class);
      Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
      Throwables.throwIfInstanceOf(e, DuplicateKeyException.class);
      Throwables.throwIfInstanceOf(e, NoSuchGroupException.class);
      throw new IOException(e);
    }
  }

  @VisibleForTesting
  @CanIgnoreReturnValue
  public UpdateResult updateGroupInNoteDb(AccountGroup.UUID groupUuid, GroupDelta groupDelta)
      throws IOException, ConfigInvalidException, DuplicateKeyException, NoSuchGroupException {
    try (RefUpdateContext ctx = RefUpdateContext.open(GROUPS_UPDATE)) {
      try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
        GroupConfig groupConfig = GroupConfig.loadForGroup(allUsersName, allUsersRepo, groupUuid);
        groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
        if (!groupConfig.getLoadedGroup().isPresent()) {
          throw new NoSuchGroupException(groupUuid);
        }

        InternalGroup originalGroup = groupConfig.getLoadedGroup().get();
        GroupNameNotes groupNameNotes = null;
        if (groupDelta.getName().isPresent()) {
          AccountGroup.NameKey oldName = originalGroup.getNameKey();
          AccountGroup.NameKey newName = groupDelta.getName().get();
          groupNameNotes =
              GroupNameNotes.forRename(allUsersName, allUsersRepo, groupUuid, oldName, newName);
        }

        commit(allUsersRepo, groupConfig, groupNameNotes);

        InternalGroup updatedGroup =
            groupConfig
                .getLoadedGroup()
                .orElseThrow(
                    () -> new IllegalStateException("Updated group wasn't automatically loaded"));
        return getUpdateResult(originalGroup, updatedGroup);
      }
    }
  }

  private DeleteResult deleteGroupInNoteDbWithRetry(AccountGroup.UUID groupUuid)
      throws IOException, ConfigInvalidException {
    try {
      return retryHelper.groupUpdate("deleteGroup", () -> deleteGroupInNoteDb(groupUuid)).call();
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, IOException.class);
      Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
      Throwables.throwIfInstanceOf(e, DuplicateKeyException.class);
      throw new IOException(e);
    }
  }

  private DeleteResult deleteGroupInNoteDb(AccountGroup.UUID groupUuid)
      throws NoSuchGroupException, ConfigInvalidException, IOException {
    try (RefUpdateContext ctx = RefUpdateContext.open(GROUPS_UPDATE)) {
      try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
        GroupConfig groupConfig = GroupConfig.loadForGroup(allUsersName, allUsersRepo, groupUuid);
        if (groupConfig.getLoadedGroup().isEmpty()) {
          throw new NoSuchGroupException(groupUuid);
        }
        InternalGroup group = groupConfig.getLoadedGroup().get();
        GroupNameNotes groupNameNotes =
            GroupNameNotes.forDeletingGroup(
                allUsersName, allUsersRepo, groupUuid, group.getNameKey());
        commit(allUsersRepo, null, groupNameNotes);
        deleteSingleRefNote(group.getGroupUUID().get());
        return buildDeleteResult(group);
      }
    }
  }

  private void deleteSingleRefNote(String ref) {
    if (!ref.startsWith(R_REFS)) {
      ref = RefNames.REFS_GROUPS + ref.substring(0, 2) + "/" + ref;
    }
    try (Repository repository = repoManager.openRepository(allUsersName)) {
      RefUpdate u = repository.updateRef(ref);
      u.setExpectedOldObjectId(repository.exactRef(ref).getObjectId());
      u.setNewObjectId(ObjectId.zeroId());
      u.setForceUpdate(true);
      RefUpdate.Result result = u.delete();

      switch (result) {
        case NEW:
        case NO_CHANGE:
        case FAST_FORWARD:
        case FORCED:
          gitRefUpdated.fire(
              allUsersName,
              u,
              ReceiveCommand.Type.DELETE,
              currentUser.map(IdentifiedUser::state).orElse(null));
          break;
        case LOCK_FAILURE:
          throw new LockFailureException(String.format("Cannot delete %s", ref), u);
        case IO_FAILURE:
        case NOT_ATTEMPTED:
        case REJECTED:
        case RENAMED:
        case REJECTED_MISSING_OBJECT:
        case REJECTED_OTHER_REASON:
        default:
          throw new StorageException(String.format("Cannot delete %s: %s", ref, result.name()));
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  private static UpdateResult getUpdateResult(
      InternalGroup originalGroup, InternalGroup updatedGroup) {
    Set<Account.Id> addedMembers =
        Sets.difference(updatedGroup.getMembers(), originalGroup.getMembers());
    Set<Account.Id> deletedMembers =
        Sets.difference(originalGroup.getMembers(), updatedGroup.getMembers());
    Set<AccountGroup.UUID> addedSubgroups =
        Sets.difference(updatedGroup.getSubgroups(), originalGroup.getSubgroups());
    Set<AccountGroup.UUID> deletedSubgroups =
        Sets.difference(originalGroup.getSubgroups(), updatedGroup.getSubgroups());

    UpdateResult.Builder resultBuilder =
        UpdateResult.builder()
            .setGroupUuid(updatedGroup.getGroupUUID())
            .setGroupId(updatedGroup.getId())
            .setGroupName(updatedGroup.getNameKey())
            .setAddedMembers(addedMembers)
            .setDeletedMembers(deletedMembers)
            .setAddedSubgroups(addedSubgroups)
            .setDeletedSubgroups(deletedSubgroups);
    if (!Objects.equals(originalGroup.getNameKey(), updatedGroup.getNameKey())) {
      resultBuilder.setPreviousGroupName(originalGroup.getNameKey());
    }
    return resultBuilder.build();
  }

  private static DeleteResult buildDeleteResult(InternalGroup deletedGroup) {
    ImmutableSet<Account.Id> deletedMembers = deletedGroup.getMembers();
    ImmutableSet<AccountGroup.UUID> deletedSubgroups = deletedGroup.getSubgroups();

    DeleteResult.Builder resultBuilder =
        DeleteResult.builder()
            .setDeletedGroupUuid(deletedGroup.getGroupUUID())
            .setDeletedGroupId(deletedGroup.getId())
            .setDeletedGroupName(deletedGroup.getNameKey())
            .setDeletedGroupMembers(deletedMembers)
            .setDeletedGroupSubgroups(deletedSubgroups);
    return resultBuilder.build();
  }

  private void commit(
      Repository allUsersRepo,
      @Nullable GroupConfig groupConfig,
      @Nullable GroupNameNotes groupNameNotes)
      throws IOException {
    BatchRefUpdate batchRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
    if (groupConfig != null) {
      try (MetaDataUpdate metaDataUpdate =
          metaDataUpdateFactory.create(allUsersName, allUsersRepo, batchRefUpdate)) {
        groupConfig.commit(metaDataUpdate);
      }
    }
    if (groupNameNotes != null) {
      // MetaDataUpdates unfortunately can't be reused. -> Create a new one.
      try (MetaDataUpdate metaDataUpdate =
          metaDataUpdateFactory.create(allUsersName, allUsersRepo, batchRefUpdate)) {
        groupNameNotes.commit(metaDataUpdate);
      }
    }

    RefUpdateUtil.executeChecked(batchRefUpdate, allUsersRepo);
    gitRefUpdated.fire(
        allUsersName, batchRefUpdate, currentUser.map(user -> user.state()).orElse(null));
  }

  private void evictCachesOnGroupCreation(InternalGroup createdGroup) {
    logger.atFine().log("evict caches on creation of group %s", createdGroup.getGroupUUID());
    // By UUID is used for the index and hence should be evicted before refreshing the index.
    indexer.get().index(createdGroup.getGroupUUID());
    // These caches use the result from the index and hence must be evicted after refreshing the
    // index.
    groupCache.evict(createdGroup.getId());
    groupCache.evict(createdGroup.getNameKey());
    createdGroup.getMembers().forEach(groupIncludeCache::evictGroupsWithMember);
    createdGroup.getSubgroups().forEach(groupIncludeCache::evictParentGroupsOf);
  }

  private void evictCachesOnGroupUpdate(UpdateResult result) {
    logger.atFine().log("evict caches on update of group %s", result.getGroupUuid());
    indexer.get().index(result.getGroupUuid());
    // These caches use the result from the index and hence must be evicted after refreshing the
    // index.
    groupCache.evict(result.getGroupId());
    groupCache.evict(result.getGroupName());
    result.getPreviousGroupName().ifPresent(groupCache::evict);

    result.getAddedMembers().forEach(groupIncludeCache::evictGroupsWithMember);
    result.getDeletedMembers().forEach(groupIncludeCache::evictGroupsWithMember);
    result.getAddedSubgroups().forEach(groupIncludeCache::evictParentGroupsOf);
    result.getDeletedSubgroups().forEach(groupIncludeCache::evictParentGroupsOf);
  }

  private void evictCacheOnGroupDeletion(DeleteResult result) {
    logger.atFine().log("evict caches on deletion of group %s", result.getDeletedGroupUuid());
    indexer.get().index(result.getDeletedGroupUuid());
    groupCache.evict(result.getDeletedGroupId());
    groupCache.evict(AccountGroup.nameKey(result.getDeletedGroupName().get()));
    result.getDeletedGroupMembers().forEach(groupIncludeCache::evictGroupsWithMember);
    result.getDeletedGroupSubgroups().forEach(groupIncludeCache::evictParentGroupsOf);
  }

  private void updateNameInProjectConfigsIfNecessary(UpdateResult result) {
    if (result.getPreviousGroupName().isPresent()) {
      AccountGroup.NameKey previousName = result.getPreviousGroupName().get();

      @SuppressWarnings("unused")
      Future<?> possiblyIgnoredError =
          renameGroupOpFactory
              .create(
                  authorIdent,
                  result.getGroupUuid(),
                  previousName.get(),
                  result.getGroupName().get())
              .start(0, TimeUnit.MILLISECONDS);
    }
  }

  private void dispatchAuditEventsOnGroupCreation(InternalGroup createdGroup) {
    if (!currentUser.isPresent()) {
      return;
    }

    if (!createdGroup.getMembers().isEmpty()) {
      groupAuditService.dispatchAddMembers(
          currentUser.get().getAccountId(),
          createdGroup.getGroupUUID(),
          createdGroup.getMembers(),
          createdGroup.getCreatedOn());
    }
    if (!createdGroup.getSubgroups().isEmpty()) {
      groupAuditService.dispatchAddSubgroups(
          currentUser.get().getAccountId(),
          createdGroup.getGroupUUID(),
          createdGroup.getSubgroups(),
          createdGroup.getCreatedOn());
    }
  }

  private void dispatchAuditEventsOnGroupUpdate(UpdateResult result, Instant updatedOn) {
    if (!currentUser.isPresent()) {
      return;
    }

    if (!result.getAddedMembers().isEmpty()) {
      groupAuditService.dispatchAddMembers(
          currentUser.get().getAccountId(),
          result.getGroupUuid(),
          result.getAddedMembers(),
          updatedOn);
    }
    if (!result.getDeletedMembers().isEmpty()) {
      groupAuditService.dispatchDeleteMembers(
          currentUser.get().getAccountId(),
          result.getGroupUuid(),
          result.getDeletedMembers(),
          updatedOn);
    }
    if (!result.getAddedSubgroups().isEmpty()) {
      groupAuditService.dispatchAddSubgroups(
          currentUser.get().getAccountId(),
          result.getGroupUuid(),
          result.getAddedSubgroups(),
          updatedOn);
    }
    if (!result.getDeletedSubgroups().isEmpty()) {
      groupAuditService.dispatchDeleteSubgroups(
          currentUser.get().getAccountId(),
          result.getGroupUuid(),
          result.getDeletedSubgroups(),
          updatedOn);
    }
  }

  @FunctionalInterface
  private interface MetaDataUpdateFactory {
    MetaDataUpdate create(
        Project.NameKey projectName, Repository repository, BatchRefUpdate batchRefUpdate)
        throws IOException;
  }

  @AutoValue
  abstract static class UpdateResult {
    abstract AccountGroup.UUID getGroupUuid();

    abstract AccountGroup.Id getGroupId();

    abstract AccountGroup.NameKey getGroupName();

    abstract Optional<AccountGroup.NameKey> getPreviousGroupName();

    abstract ImmutableSet<Account.Id> getAddedMembers();

    abstract ImmutableSet<Account.Id> getDeletedMembers();

    abstract ImmutableSet<AccountGroup.UUID> getAddedSubgroups();

    abstract ImmutableSet<AccountGroup.UUID> getDeletedSubgroups();

    static Builder builder() {
      return new AutoValue_GroupsUpdate_UpdateResult.Builder();
    }

    @AutoValue.Builder
    abstract static class Builder {
      abstract Builder setGroupUuid(AccountGroup.UUID groupUuid);

      abstract Builder setGroupId(AccountGroup.Id groupId);

      abstract Builder setGroupName(AccountGroup.NameKey name);

      abstract Builder setPreviousGroupName(AccountGroup.NameKey previousName);

      abstract Builder setAddedMembers(Set<Account.Id> addedMembers);

      abstract Builder setDeletedMembers(Set<Account.Id> deletedMembers);

      abstract Builder setAddedSubgroups(Set<AccountGroup.UUID> addedSubgroups);

      abstract Builder setDeletedSubgroups(Set<AccountGroup.UUID> deletedSubgroups);

      abstract UpdateResult build();
    }
  }

  @AutoValue
  abstract static class DeleteResult {
    abstract AccountGroup.UUID getDeletedGroupUuid();

    abstract AccountGroup.Id getDeletedGroupId();

    abstract AccountGroup.NameKey getDeletedGroupName();

    abstract ImmutableSet<Account.Id> getDeletedGroupMembers();

    abstract ImmutableSet<AccountGroup.UUID> getDeletedGroupSubgroups();

    static Builder builder() {
      return new AutoValue_GroupsUpdate_DeleteResult.Builder();
    }

    @AutoValue.Builder
    abstract static class Builder {
      abstract Builder setDeletedGroupUuid(AccountGroup.UUID groupUuid);

      abstract Builder setDeletedGroupId(AccountGroup.Id groupId);

      abstract Builder setDeletedGroupName(AccountGroup.NameKey name);

      abstract Builder setDeletedGroupMembers(Set<Account.Id> deletedMembers);

      abstract Builder setDeletedGroupSubgroups(Set<AccountGroup.UUID> deletedSubgroups);

      abstract DeleteResult build();
    }
  }
}
