// 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.restapi.change;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.Objects.requireNonNull;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.LabelValue;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.DraftCommentsReader;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.ServiceUserClassifier;
import com.google.gerrit.server.approval.ApprovalsUtil;
import com.google.gerrit.server.change.AddToAttentionSetOp;
import com.google.gerrit.server.change.AttentionSetUnchangedOp;
import com.google.gerrit.server.change.AttentionSetUpdateCondition;
import com.google.gerrit.server.change.CommentThread;
import com.google.gerrit.server.change.CommentThreads;
import com.google.gerrit.server.change.RemoveFromAttentionSetOp;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.util.AttentionSetUtil;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;

/**
 * This class is used to update the attention set when performing a review or replying on a change.
 */
public class ReplyAttentionSetUpdates {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final PermissionBackend permissionBackend;
  private final AddToAttentionSetOp.Factory addToAttentionSetOpFactory;
  private final RemoveFromAttentionSetOp.Factory removeFromAttentionSetOpFactory;
  private final ApprovalsUtil approvalsUtil;
  private final AccountResolver accountResolver;
  private final ServiceUserClassifier serviceUserClassifier;
  private final CommentsUtil commentsUtil;
  private final DraftCommentsReader draftCommentsReader;
  private final ProjectCache projectCache;

  @Inject
  ReplyAttentionSetUpdates(
      PermissionBackend permissionBackend,
      AddToAttentionSetOp.Factory addToAttentionSetOpFactory,
      RemoveFromAttentionSetOp.Factory removeFromAttentionSetOpFactory,
      ApprovalsUtil approvalsUtil,
      AccountResolver accountResolver,
      ServiceUserClassifier serviceUserClassifier,
      CommentsUtil commentsUtil,
      DraftCommentsReader draftCommentsReader,
      ProjectCache projectCache) {
    this.permissionBackend = permissionBackend;
    this.addToAttentionSetOpFactory = addToAttentionSetOpFactory;
    this.removeFromAttentionSetOpFactory = removeFromAttentionSetOpFactory;
    this.approvalsUtil = approvalsUtil;
    this.accountResolver = accountResolver;
    this.serviceUserClassifier = serviceUserClassifier;
    this.commentsUtil = commentsUtil;
    this.draftCommentsReader = draftCommentsReader;
    this.projectCache = projectCache;
  }

  /** Adjusts the attention set but only based on the automatic rules. */
  public void processAutomaticAttentionSetRulesOnReply(
      BatchUpdate bu,
      ChangeNotes changeNotes,
      boolean readyForReview,
      CurrentUser currentUser,
      List<HumanComment> commentsToBePublished) {
    if (serviceUserClassifier.isServiceUser(currentUser.getAccountId())) {
      return;
    }
    processRules(
        bu,
        /* postReviewOp= */ null,
        changeNotes,
        readyForReview,
        currentUser,
        commentsToBePublished.stream().collect(toImmutableSet()));
  }

  /**
   * Adjusts the attention set when a review is posted.
   *
   * <p>If the same user should be added and removed or added/removed twice, the user will only be
   * added/removed once, based on first addition/removal.
   *
   * @param postReviewOp the {@link PostReviewOp} that is being executed before the attention set
   *     updates
   */
  public void updateAttentionSetOnPostReview(
      BatchUpdate bu,
      PostReviewOp postReviewOp,
      ChangeNotes changeNotes,
      ReviewInput input,
      CurrentUser currentUser)
      throws BadRequestException,
          IOException,
          PermissionBackendException,
          UnprocessableEntityException,
          ConfigInvalidException {
    requireNonNull(postReviewOp, "postReviewOp must not be null");

    processManualUpdates(bu, changeNotes, input);
    if (input.ignoreAutomaticAttentionSetRules) {

      // If we ignore automatic attention set rules it means we need to pass this information to
      // ChangeUpdate. Also, we should stop all other attention set updates that are part of
      // this method and happen in PostReview.
      bu.addOp(changeNotes.getChangeId(), new AttentionSetUnchangedOp());
      return;
    }
    boolean isReadyForReview = isReadyForReview(changeNotes, input);

    if (isReadyForReview && serviceUserClassifier.isServiceUser(currentUser.getAccountId())) {
      botsWithNegativeLabelsAddOwnerAndUploader(bu, postReviewOp, changeNotes);
      return;
    }

    processRules(
        bu,
        postReviewOp,
        changeNotes,
        isReadyForReview,
        currentUser,
        getAllNewComments(changeNotes, input, currentUser));
  }

  private ImmutableSet<HumanComment> getAllNewComments(
      ChangeNotes changeNotes, ReviewInput input, CurrentUser currentUser) {
    Set<HumanComment> newComments = new HashSet<>();
    if (input.comments != null) {
      for (ReviewInput.CommentInput commentInput :
          input.comments.values().stream().flatMap(x -> x.stream()).collect(Collectors.toList())) {
        newComments.add(
            commentsUtil.newHumanComment(
                changeNotes,
                currentUser,
                TimeUtil.now(),
                commentInput.path,
                commentInput.patchSet == null
                    ? changeNotes.getChange().currentPatchSetId()
                    : PatchSet.id(changeNotes.getChange().getId(), commentInput.patchSet),
                commentInput.side(),
                commentInput.message,
                commentInput.unresolved,
                commentInput.inReplyTo,
                CommentsUtil.createFixSuggestionsFromInput(commentInput.fixSuggestions)));
      }
    }
    List<HumanComment> drafts = new ArrayList<>();
    if (input.drafts == ReviewInput.DraftHandling.PUBLISH) {
      drafts =
          draftCommentsReader.getDraftsByPatchSetAndDraftAuthor(
              changeNotes, changeNotes.getChange().currentPatchSetId(), currentUser.getAccountId());
    }
    if (input.drafts == ReviewInput.DraftHandling.PUBLISH_ALL_REVISIONS) {
      drafts =
          draftCommentsReader.getDraftsByChangeAndDraftAuthor(
              changeNotes, currentUser.getAccountId());
    }
    return Stream.concat(newComments.stream(), drafts.stream()).collect(toImmutableSet());
  }

  /**
   * Process the automatic rules of the attention set.
   *
   * <p>All of the automatic rules except adding/removing reviewers and entering/exiting WIP state
   * are done here, and the rest are done in {@link ChangeUpdate}.
   *
   * @param postReviewOp {@link PostReviewOp} that is being executed before the attention set
   *     updates, may be {@code null}
   */
  private void processRules(
      BatchUpdate bu,
      @Nullable PostReviewOp postReviewOp,
      ChangeNotes changeNotes,
      boolean readyForReview,
      CurrentUser currentUser,
      ImmutableSet<HumanComment> allNewComments) {
    updateAttentionSetForCurrentUser(bu, postReviewOp, changeNotes, currentUser);

    // The rest of the conditions only apply if the change is open.
    if (changeNotes.getChange().getStatus().isClosed()) {
      // We still add the owner if a new comment thread was created, on closed changes.
      if (allNewComments.stream().anyMatch(c -> c.parentUuid == null)) {
        addToAttentionSet(
            bu,
            changeNotes,
            changeNotes.getChange().getOwner(),
            "A new comment thread was created",
            false);
      }
      return;
    }
    // The rest of the conditions only apply if the change is ready for review and reply is not
    // posted by a bot.
    if (!readyForReview || serviceUserClassifier.isServiceUser(currentUser.getAccountId())) {
      return;
    }

    addOwnerAndUploaderToAttentionSetIfSomeoneElseReplied(
        bu, postReviewOp, changeNotes, currentUser, readyForReview, allNewComments);
    addAllAuthorsOfCommentThreads(bu, changeNotes, allNewComments, currentUser);
  }

  /**
   * Updates the attention set for the current user.
   *
   * <p>Removes the current user from the attention set (since they replied) unless they voted on an
   * outdated patch set and some of the votes were not copied to the current patch set (in this case
   * they should be in the attention set to re-apply their votes).
   *
   * <p>If the current user voted on an outdated patch set and some of the votes were not copied to
   * the current patch set:
   *
   * <ul>
   *   <li>the current user is added to the attention set (if they are not in the attention set yet)
   *       or
   *   <li>the reason for the current user to be in the attention set is updated (if they are
   *       already in the attention set).
   * </ul>
   */
  private void updateAttentionSetForCurrentUser(
      BatchUpdate bu,
      @Nullable PostReviewOp postReviewOp,
      ChangeNotes changeNotes,
      CurrentUser currentUser) {
    if (postReviewOp == null) {
      // Replying removes the current user from the attention set.
      removeFromAttentionSet(
          bu, changeNotes, currentUser.getAccountId(), "removed on reply", false);
    } else {
      // If the current user voted on an outdated patch set and some of the votes were not copied to
      // the current patch set the current user should stay in the attention set, or be added to the
      // attention set. In case the user stays in the attention set, this updates the reason for
      // being in the attention set.
      AttentionSetUpdateCondition addOrKeepCondition =
          () ->
              postReviewOp
                  .getResult()
                  .appliedVotesOnOutdatedPatchSetThatWereNotCopiedToCurrentPatchSet();
      maybeAddToAttentionSet(
          bu,
          addOrKeepCondition,
          changeNotes,
          currentUser.getAccountId(),
          "Some votes were not copied to the current patch set",
          false);

      // Otherwise replying removes the current user from the attention set.
      AttentionSetUpdateCondition removeCondition = () -> !addOrKeepCondition.check();
      maybeRemoveFromAttentionSet(
          bu, removeCondition, changeNotes, currentUser.getAccountId(), "removed on reply", false);
    }
  }

  /**
   * Adds the owner and uploader to the attention set if someone else replied.
   *
   * <p>Replying means they either updated the votes on the current patch set (either directly on
   * the current patch set or the votes were copied to the current patch set), they posted a change
   * message, they marked the change as ready or they posted new comments.
   */
  private void addOwnerAndUploaderToAttentionSetIfSomeoneElseReplied(
      BatchUpdate bu,
      @Nullable PostReviewOp postReviewOp,
      ChangeNotes changeNotes,
      CurrentUser currentUser,
      boolean readyForReview,
      ImmutableSet<HumanComment> allNewComments) {
    AttentionSetUpdateCondition condition =
        postReviewOp != null
            ? () ->
                postReviewOp.getResult().updatedAnyVoteOnCurrentPatchSet()
                    || postReviewOp.getResult().postedChangeMessage()
                    || (changeNotes.getChange().isWorkInProgress() && readyForReview)
                    || !allNewComments.isEmpty()
            : () ->
                (changeNotes.getChange().isWorkInProgress() && readyForReview)
                    || !allNewComments.isEmpty();

    Account.Id owner = changeNotes.getChange().getOwner();
    if (!currentUser.getAccountId().equals(owner)) {
      maybeAddToAttentionSet(
          bu, condition, changeNotes, owner, "Someone else replied on the change", false);
    }

    Account.Id uploader = changeNotes.getCurrentPatchSet().uploader();
    if (!owner.equals(uploader) && !currentUser.getAccountId().equals(uploader)) {
      maybeAddToAttentionSet(
          bu, condition, changeNotes, uploader, "Someone else replied on the change", false);
    }
  }

  /** Adds all authors of all comment threads that received a reply during this update */
  private void addAllAuthorsOfCommentThreads(
      BatchUpdate bu,
      ChangeNotes changeNotes,
      ImmutableSet<HumanComment> allNewComments,
      CurrentUser currentUser) {
    boolean isOwnerOrUploader =
        currentUser.getAccountId().equals(changeNotes.getChange().getOwner())
            || currentUser.getAccountId().equals(changeNotes.getCurrentPatchSet().uploader());

    boolean noCRLabel = false;
    Optional<LabelValue> maxCRValue =
        projectCache
            .get(changeNotes.getChange().getProject())
            .orElseThrow(
                () ->
                    new IllegalStateException(
                        String.format(
                            "Couldn't find project \"%s\" for a change \"%s\"",
                            changeNotes.getChange().getProject(), changeNotes.getChangeId())))
            .getLabelTypes(changeNotes)
            .byLabel(LabelId.CODE_REVIEW)
            .map(l -> l.getMax());

    ImmutableSet<Account.Id> maxCrApprovers;
    if (maxCRValue.isPresent()) {
      maxCrApprovers =
          changeNotes.getApprovals().all().get(changeNotes.getCurrentPatchSet().id()).stream()
              .filter(
                  a ->
                      a.label().equals(LabelId.CODE_REVIEW)
                          && a.value() == maxCRValue.get().getValue())
              .map(a -> a.accountId())
              .collect(toImmutableSet());
    } else {
      noCRLabel = true;
      maxCrApprovers = ImmutableSet.of();
    }

    // Include newly published comments, when building threads.
    ImmutableList<HumanComment> relevantComments =
        Stream.concat(
                commentsUtil.publishedHumanCommentsByChange(changeNotes).stream(),
                allNewComments.stream())
            .collect(toImmutableList());
    ImmutableSet<CommentThread<HumanComment>> repliedToCommentThreads =
        CommentThreads.forComments(relevantComments).getThreadsForChildren(allNewComments);

    LinkedHashSet<Account.Id> repliedToUsers = new LinkedHashSet<>();
    for (CommentThread<HumanComment> thread : repliedToCommentThreads) {
      // If thread is resolved, we only bring back the commenters who have not yet left max
      // Code-Review vote.
      // If Owner replied but didn't resolve, we assume clarification was asked add everyone on the
      // thread to attention set.
      boolean ignoreVoteCheck = noCRLabel || (thread.unresolved() && isOwnerOrUploader);
      if (thread.unresolved() && !isOwnerOrUploader) {
        // Reviewer replied. Owner is still the one to act. No need to add commenters.
        continue;
      }
      thread.comments().stream()
          .map(comment -> comment.author.getId())
          .filter(
              a ->
                  !a.equals(currentUser.getAccountId())
                      && (ignoreVoteCheck || !maxCrApprovers.contains(a)))
          .forEach(repliedToUsers::add);
    }
    ImmutableSet<Account.Id> possibleUsersToAdd = approvalsUtil.getReviewers(changeNotes).all();
    SetView<Account.Id> usersToAdd = Sets.intersection(possibleUsersToAdd, repliedToUsers);

    for (Account.Id user : usersToAdd) {
      addToAttentionSet(
          bu, changeNotes, user, "Someone else replied on a comment you posted", false);
    }
  }

  /** Process the manual updates of the attention set. */
  private void processManualUpdates(BatchUpdate bu, ChangeNotes changeNotes, ReviewInput input)
      throws BadRequestException,
          IOException,
          PermissionBackendException,
          UnprocessableEntityException,
          ConfigInvalidException {
    Set<Account.Id> accountsChangedInCommit = new HashSet<>();
    // If we specify a user to remove, and the user is in the attention set, we remove it.
    if (input.removeFromAttentionSet != null) {
      for (AttentionSetInput remove : input.removeFromAttentionSet) {
        removeFromAttentionSet(bu, changeNotes, remove, accountsChangedInCommit);
      }
    }

    // If we don't specify a user to remove, but we specify addition for that user, the user will be
    // added if they are not in the attention set yet.
    if (input.addToAttentionSet != null) {
      for (AttentionSetInput add : input.addToAttentionSet) {
        addToAttentionSet(bu, changeNotes, add, accountsChangedInCommit);
      }
    }
  }

  /**
   * Bots don't process automatic rules, the only attention set change they do is this rule: Add
   * owner and uploader when a bot votes negatively on the current patch set, but only if the change
   * is open.
   */
  private void botsWithNegativeLabelsAddOwnerAndUploader(
      BatchUpdate bu, PostReviewOp postReviewOp, ChangeNotes changeNotes) {
    if (changeNotes.getChange().isClosed()) {
      return;
    }

    AttentionSetUpdateCondition condition =
        () -> postReviewOp.getResult().updatedAnyNegativeVoteOnCurrentPatchSet();

    Account.Id owner = changeNotes.getChange().getOwner();
    maybeAddToAttentionSet(
        bu, condition, changeNotes, owner, "A robot voted negatively on a label", false);

    Account.Id uploader = changeNotes.getCurrentPatchSet().uploader();
    if (!owner.equals(uploader)) {
      maybeAddToAttentionSet(
          bu, condition, changeNotes, uploader, "A robot voted negatively on a label", false);
    }
  }

  /**
   * Adds the user to the attention set
   *
   * @param bu BatchUpdate to perform the updates to the attention set
   * @param changeNotes current change
   * @param user user to add to the attention set
   * @param reason reason for adding
   * @param notify whether or not to notify about this addition
   */
  private void addToAttentionSet(
      BatchUpdate bu, ChangeNotes changeNotes, Account.Id user, String reason, boolean notify) {
    AddToAttentionSetOp addToAttentionSet = addToAttentionSetOpFactory.create(user, reason, notify);
    bu.addOp(changeNotes.getChangeId(), addToAttentionSet);
  }

  /**
   * Adds the user to the attention set if the given condition is true.
   *
   * @param bu BatchUpdate to perform the updates to the attention set
   * @param condition condition that decides whether the attention set update should be performed
   * @param changeNotes current change
   * @param user user to add to the attention set
   * @param reason reason for adding
   * @param notify whether or not to notify about this addition
   */
  private void maybeAddToAttentionSet(
      BatchUpdate bu,
      AttentionSetUpdateCondition condition,
      ChangeNotes changeNotes,
      Account.Id user,
      String reason,
      boolean notify) {
    AddToAttentionSetOp addToAttentionSet =
        addToAttentionSetOpFactory.create(user, reason, notify).setCondition(condition);
    bu.addOp(changeNotes.getChangeId(), addToAttentionSet);
  }

  /**
   * Removes the user from the attention set
   *
   * @param bu BatchUpdate to perform the updates to the attention set.
   * @param changeNotes current change.
   * @param user user to add remove from the attention set.
   * @param reason reason for removing.
   * @param notify whether or not to notify about this removal.
   */
  private void removeFromAttentionSet(
      BatchUpdate bu, ChangeNotes changeNotes, Account.Id user, String reason, boolean notify) {
    RemoveFromAttentionSetOp removeFromAttentionSetOp =
        removeFromAttentionSetOpFactory.create(user, reason, notify);
    bu.addOp(changeNotes.getChangeId(), removeFromAttentionSetOp);
  }

  /**
   * Removes the user from the attention set if the given condition is true.
   *
   * @param bu BatchUpdate to perform the updates to the attention set.
   * @param condition condition that decides whether the attention set update should be performed
   * @param changeNotes current change.
   * @param user user to add remove from the attention set.
   * @param reason reason for removing.
   * @param notify whether or not to notify about this removal.
   */
  private void maybeRemoveFromAttentionSet(
      BatchUpdate bu,
      AttentionSetUpdateCondition condition,
      ChangeNotes changeNotes,
      Account.Id user,
      String reason,
      boolean notify) {
    RemoveFromAttentionSetOp removeFromAttentionSetOp =
        removeFromAttentionSetOpFactory.create(user, reason, notify).setCondition(condition);
    bu.addOp(changeNotes.getChangeId(), removeFromAttentionSetOp);
  }

  private static boolean isReadyForReview(ChangeNotes changeNotes, ReviewInput input) {
    return (!changeNotes.getChange().isWorkInProgress() && !input.workInProgress) || input.ready;
  }

  private void addToAttentionSet(
      BatchUpdate bu,
      ChangeNotes changeNotes,
      AttentionSetInput add,
      Set<Account.Id> accountsChangedInCommit)
      throws BadRequestException,
          IOException,
          PermissionBackendException,
          UnprocessableEntityException,
          ConfigInvalidException {
    AttentionSetUtil.validateInput(add);
    try {
      Account.Id attentionUserId =
          getAccountIdAndValidateUser(
              changeNotes, add.user, accountsChangedInCommit, AttentionSetUpdate.Operation.ADD);
      addToAttentionSet(bu, changeNotes, attentionUserId, add.reason, false);
    } catch (AccountResolver.UnresolvableAccountException ex) {
      // This happens only when the account doesn't exist. Silently ignore it. If we threw an error
      // message here, then it would be possible to probe whether an account exists.
    } catch (AuthException ex) {
      // adding users without permission to the attention set should fail silently.
      logger.atFine().log("%s", ex.getMessage());
    }
  }

  private void removeFromAttentionSet(
      BatchUpdate bu,
      ChangeNotes changeNotes,
      AttentionSetInput remove,
      Set<Account.Id> accountsChangedInCommit)
      throws BadRequestException,
          IOException,
          PermissionBackendException,
          UnprocessableEntityException,
          ConfigInvalidException {
    AttentionSetUtil.validateInput(remove);
    try {
      Account.Id attentionUserId =
          getAccountIdAndValidateUser(
              changeNotes,
              remove.user,
              accountsChangedInCommit,
              AttentionSetUpdate.Operation.REMOVE);
      removeFromAttentionSet(bu, changeNotes, attentionUserId, remove.reason, false);
    } catch (AccountResolver.UnresolvableAccountException ex) {
      // This happens only when the account doesn't exist. Silently ignore it. If we threw an error
      // message here, then it would be possible to probe whether an account exists.
    } catch (AuthException ex) {
      // this should never happen since removing users with permissions should work.
      logger.atSevere().log("%s", ex.getMessage());
    }
  }

  private Account.Id getAccountId(
      ChangeNotes changeNotes, String user, AttentionSetUpdate.Operation operation)
      throws ConfigInvalidException,
          IOException,
          UnprocessableEntityException,
          PermissionBackendException,
          AuthException {
    Account.Id attentionUserId = accountResolver.resolve(user).asUnique().account().id();
    try {
      permissionBackend
          .absentUser(attentionUserId)
          .change(changeNotes)
          .check(ChangePermission.READ);
    } catch (AuthException e) {
      // If the change is private, it is okay to add the user to the attention set since that
      // person will be granted visibility when a reviewer.
      if (!changeNotes.getChange().isPrivate()) {

        // Removing users without access is allowed, adding is not allowed
        if (operation == AttentionSetUpdate.Operation.ADD) {
          throw new AuthException(
              "Can't modify attention set: Read not permitted for " + attentionUserId, e);
        }
      }
    }
    return attentionUserId;
  }

  private Account.Id getAccountIdAndValidateUser(
      ChangeNotes changeNotes,
      String user,
      Set<Account.Id> accountsChangedInCommit,
      AttentionSetUpdate.Operation operation)
      throws ConfigInvalidException,
          IOException,
          PermissionBackendException,
          UnprocessableEntityException,
          BadRequestException,
          AuthException {
    try {
      Account.Id attentionUserId = getAccountId(changeNotes, user, operation);
      if (accountsChangedInCommit.contains(attentionUserId)) {
        throw new BadRequestException(
            String.format(
                "%s can not be added/removed twice, and can not be added and "
                    + "removed at the same time",
                user));
      }
      accountsChangedInCommit.add(attentionUserId);
      return attentionUserId;
    } catch (AccountResolver.UnresolvableAccountException ex) {
      // This can only happen if this user can't see the account or the account doesn't exist.
      // Silently modify the account's attention set anyway, if the account exists.
      return accountResolver.resolveIgnoreVisibility(user).asUnique().account().id();
    }
  }
}
