// Copyright (C) 2023 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.restapi.account;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
import com.google.common.flogger.FluentLogger;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.common.Input;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.gpg.PublicKeyStoreUtil;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.StarredChangesReader;
import com.google.gerrit.server.StarredChangesWriter;
import com.google.gerrit.server.UserInitiated;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.account.AccountSshKey;
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.AuthTokenAccessor;
import com.google.gerrit.server.account.VersionedAuthorizedKeys;
import com.google.gerrit.server.change.AccountPatchReviewStore;
import com.google.gerrit.server.config.AccountConfig;
import com.google.gerrit.server.edit.ChangeEdit;
import com.google.gerrit.server.edit.ChangeEditUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.db.GroupDelta;
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.plugincontext.PluginItemContext;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.ssh.SshKeyCache;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jgit.errors.ConfigInvalidException;
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.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * REST endpoint for deleting an account.
 *
 * <p>This REST endpoint handles {@code DELETE /accounts/<account-identifier>} requests. Currently,
 * only self deletions are allowed.
 */
@Singleton
public class DeleteAccount implements RestModifyView<AccountResource, Input> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final Provider<CurrentUser> self;
  private final Provider<PersonIdent> serverIdent;
  private final Provider<AccountsUpdate> accountsUpdateProvider;
  private final VersionedAuthorizedKeys.Accessor authorizedKeys;
  private final SshKeyCache sshKeyCache;
  private final StarredChangesReader starredChangesReader;
  private final StarredChangesWriter starredChangesWriter;
  private final DeleteDraftCommentsUtil deleteDraftCommentsUtil;
  private final GitRepositoryManager gitManager;
  private final Provider<InternalChangeQuery> queryProvider;
  private final ChangeEditUtil changeEditUtil;
  private final PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore;
  private final PublicKeyStoreUtil publicKeyStoreUtil;
  private final AccountConfig accountConfig;
  private final Provider<GroupsUpdate> groupsUpdateProvider;
  private final AuthTokenAccessor tokenAccessor;

  @Inject
  public DeleteAccount(
      Provider<CurrentUser> self,
      @GerritPersonIdent Provider<PersonIdent> serverIdent,
      @UserInitiated Provider<AccountsUpdate> accountsUpdateProvider,
      @UserInitiated Provider<GroupsUpdate> groupsUpdateProvider,
      VersionedAuthorizedKeys.Accessor authorizedKeys,
      SshKeyCache sshKeyCache,
      StarredChangesReader starredChangesReader,
      StarredChangesWriter starredChangesWriter,
      DeleteDraftCommentsUtil deleteDraftCommentsUtil,
      GitRepositoryManager gitManager,
      Provider<InternalChangeQuery> queryProvider,
      ChangeEditUtil changeEditUtil,
      PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore,
      PublicKeyStoreUtil publicKeyStoreUtil,
      AccountConfig accountConfig,
      AuthTokenAccessor tokenAccessor) {
    this.self = self;
    this.serverIdent = serverIdent;
    this.accountsUpdateProvider = accountsUpdateProvider;
    this.authorizedKeys = authorizedKeys;
    this.sshKeyCache = sshKeyCache;
    this.starredChangesReader = starredChangesReader;
    this.starredChangesWriter = starredChangesWriter;
    this.deleteDraftCommentsUtil = deleteDraftCommentsUtil;
    this.gitManager = gitManager;
    this.queryProvider = queryProvider;
    this.changeEditUtil = changeEditUtil;
    this.accountPatchReviewStore = accountPatchReviewStore;
    this.publicKeyStoreUtil = publicKeyStoreUtil;
    this.accountConfig = accountConfig;
    this.groupsUpdateProvider = groupsUpdateProvider;
    this.tokenAccessor = tokenAccessor;
  }

  @Override
  @CanIgnoreReturnValue
  public Response<?> apply(AccountResource rsrc, Input unusedInput)
      throws AuthException, AccountException, ResourceNotFoundException {
    if (!accountConfig.isDeleteEnabled()) {
      throw new ResourceNotFoundException("Delete account is not enabled");
    }
    IdentifiedUser user = rsrc.getUser();
    if (!self.get().hasSameAccountId(user)) {
      throw new AuthException("Delete account is only permitted for self");
    }

    Account.Id userId = user.getAccountId();
    try {
      deletePgpKeys(user);
      deleteSshKeys(user);
      deleteStarredChanges(userId);
      deleteChangeEdits(userId);
      tokenAccessor.deleteAllTokens(user.getAccountId());
      deleteDraftCommentsUtil.deleteDraftComments(user, null);
      accountPatchReviewStore.run(a -> a.clearReviewedBy(userId));
      removeUserFromGroups(user);
      accountsUpdateProvider
          .get()
          .delete("Deleting user through `DELETE /accounts/{ID}`", user.getAccountId());
    } catch (Exception e) {
      throw new AccountException("Could not delete account", e);
    }
    return Response.none();
  }

  private void removeUserFromGroups(IdentifiedUser user) {
    Account.Id accountId = user.getAccountId();

    GroupDelta groupDelta =
        GroupDelta.builder()
            .setMemberModification(memberIds -> Sets.difference(memberIds, Set.of(accountId)))
            .build();

    Set<AccountGroup.UUID> internalGroups =
        user.getEffectiveGroups().getKnownGroups().stream()
            .filter(g -> g.isInternalGroup())
            .collect(Collectors.toSet());

    internalGroups.forEach(
        groupUuid -> {
          try {
            groupsUpdateProvider.get().updateGroup(groupUuid, groupDelta);
            logger.atInfo().log("User: %s removed from Group: %s", accountId, groupUuid);
          } catch (Exception e) {
            logger.atWarning().withCause(e).log(
                "User: %s could not be removed from Group: %s ", accountId, groupUuid);
          }
        });
  }

  private void deletePgpKeys(IdentifiedUser user) {
    if (!publicKeyStoreUtil.hasInitializedPublicKeyStore()) {
      return;
    }
    try {
      List<RefUpdate.Result> deletedKeyResults =
          publicKeyStoreUtil.deleteAllPgpKeysForUser(
              user.getAccountId(), serverIdent.get(), serverIdent.get());
      for (RefUpdate.Result saveResult : deletedKeyResults) {
        if (saveResult != RefUpdate.Result.NO_CHANGE
            && saveResult != RefUpdate.Result.FAST_FORWARD) {
          throw new StorageException(String.format("Failed to delete PGP key: %s", saveResult));
        }
      }
    } catch (Exception e) {
      throw new StorageException("Failed to delete PGP keys.", e);
    }
  }

  private void deleteSshKeys(IdentifiedUser user) throws ConfigInvalidException, IOException {
    List<AccountSshKey> keys = authorizedKeys.getKeys(user.getAccountId());
    for (AccountSshKey key : keys) {
      authorizedKeys.deleteKey(user.getAccountId(), key.seq());
    }
    user.getUserName().ifPresent(sshKeyCache::evict);
  }

  private void deleteStarredChanges(Account.Id accountId) {
    ImmutableSet<Change.Id> staredChanges = starredChangesReader.byAccountId(accountId, false);
    for (Change.Id change : staredChanges) {
      starredChangesWriter.unstar(self.get().getAccountId(), change);
    }
  }

  private void deleteChangeEdits(Account.Id accountId) throws IOException, QueryParseException {
    // Note: in case of a stale index, the results of this query might be incomplete.
    List<ChangeData> changesWithEdits = queryProvider.get().byOpenEditByUser(accountId);

    for (ChangeData cd : changesWithEdits) {
      for (Table.Cell<Account.Id, PatchSet.Id, Ref> edit : cd.editRefs().cellSet()) {
        if (!accountId.equals(edit.getRowKey())) {
          continue;
        }
        try (Repository repo = gitManager.openRepository(cd.project());
            RevWalk rw = new RevWalk(repo)) {
          RevCommit commit = rw.parseCommit(edit.getValue().getObjectId());
          changeEditUtil.delete(
              new ChangeEdit(
                  cd.change(),
                  edit.getValue().getName(),
                  commit,
                  cd.patchSet(edit.getColumnKey())));
        }
      }
    }
  }
}
