// Copyright (C) 2021 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.plugins.codeowners.backend;

import static java.util.stream.Collectors.joining;

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.events.ReviewerAddedListener;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.util.JgitPath;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * Callback that is invoked when a user is added as a reviewer.
 *
 * <p>If a code owner was added as reviewer add a change message that lists the files that are owned
 * by the reviewer.
 */
@Singleton
public class CodeOwnersOnAddReviewer implements ReviewerAddedListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String TAG_ADD_REVIEWER =
      ChangeMessagesUtil.AUTOGENERATED_BY_GERRIT_TAG_PREFIX + "code-owners:addReviewer";

  private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
  private final CodeOwnerApprovalCheck codeOwnerApprovalCheck;
  private final Provider<CurrentUser> userProvider;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final ChangeNotes.Factory changeNotesFactory;
  private final AccountCache accountCache;
  private final ChangeMessagesUtil changeMessageUtil;

  @Inject
  CodeOwnersOnAddReviewer(
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      CodeOwnerApprovalCheck codeOwnerApprovalCheck,
      Provider<CurrentUser> userProvider,
      BatchUpdate.Factory batchUpdateFactory,
      ChangeNotes.Factory changeNotesFactory,
      AccountCache accountCache,
      ChangeMessagesUtil changeMessageUtil) {
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
    this.codeOwnerApprovalCheck = codeOwnerApprovalCheck;
    this.userProvider = userProvider;
    this.batchUpdateFactory = batchUpdateFactory;
    this.changeNotesFactory = changeNotesFactory;
    this.accountCache = accountCache;
    this.changeMessageUtil = changeMessageUtil;
  }

  @Override
  public void onReviewersAdded(Event event) {
    Change.Id changeId = Change.id(event.getChange()._number);
    Project.NameKey projectName = Project.nameKey(event.getChange().project);
    BranchNameKey branchNameKey = BranchNameKey.create(projectName, event.getChange().branch);

    if (codeOwnersPluginConfiguration.isDisabled(branchNameKey)
        || codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(projectName) <= 0) {
      return;
    }

    try (BatchUpdate batchUpdate =
        batchUpdateFactory.create(projectName, userProvider.get(), TimeUtil.nowTs())) {
      batchUpdate.addOp(changeId, new Op(event.getReviewers()));
      batchUpdate.execute();
    } catch (RestApiException | UpdateException e) {
      logger.atSevere().withCause(e).log(
          String.format(
              "Failed to post code-owners change message for reviewer on change %s in project %s.",
              changeId, projectName));
    }
  }

  private class Op implements BatchUpdateOp {
    private final List<AccountInfo> reviewers;

    Op(List<AccountInfo> reviewers) {
      this.reviewers = reviewers;
    }

    @Override
    public boolean updateChange(ChangeContext ctx) throws Exception {
      String message =
          reviewers.stream()
              .map(accountInfo -> Account.id(accountInfo._accountId))
              .map(
                  reviewerAccountId ->
                      buildMessageForReviewer(
                          ctx.getProject(), ctx.getChange().getId(), reviewerAccountId))
              .filter(Optional::isPresent)
              .map(Optional::get)
              .collect(joining("\n"));

      if (message.isEmpty()) {
        return false;
      }

      ChangeMessage changeMessage = ChangeMessagesUtil.newMessage(ctx, message, TAG_ADD_REVIEWER);
      changeMessageUtil.addChangeMessage(
          ctx.getUpdate(ctx.getChange().currentPatchSetId()), changeMessage);
      return true;
    }

    private Optional<String> buildMessageForReviewer(
        Project.NameKey projectName, Change.Id changeId, Account.Id reviewerAccountId) {
      ChangeNotes changeNotes = changeNotesFactory.create(projectName, changeId);

      ImmutableList<Path> ownedPaths;
      try {
        ownedPaths =
            codeOwnerApprovalCheck.getOwnedPaths(
                changeNotes, changeNotes.getCurrentPatchSet(), reviewerAccountId);
      } catch (RestApiException e) {
        logger.atFine().withCause(e).log(
            "Couldn't compute owned paths of change %s for account %s",
            changeNotes.getChangeId(), reviewerAccountId.get());
        return Optional.empty();
      }

      if (ownedPaths.isEmpty()) {
        // this reviewer doesn't own any of the modified paths
        return Optional.empty();
      }

      Account reviewerAccount = accountCache.getEvenIfMissing(reviewerAccountId).account();

      StringBuilder message = new StringBuilder();
      message.append(
          String.format(
              "%s who was added as reviewer owns the following files:\n",
              reviewerAccount.getName()));

      int maxPathsInChangeMessage =
          codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(projectName);
      if (ownedPaths.size() <= maxPathsInChangeMessage) {
        appendPaths(message, ownedPaths.stream());
      } else {
        // -1 so that we never show "(1 more files)"
        int limit = maxPathsInChangeMessage - 1;
        appendPaths(message, ownedPaths.stream().limit(limit));
        message.append(String.format("(%s more files)\n", ownedPaths.size() - limit));
      }

      return Optional.of(message.toString());
    }

    private void appendPaths(StringBuilder message, Stream<Path> pathsToAppend) {
      pathsToAppend.forEach(
          path -> message.append(String.format("* %s\n", JgitPath.of(path).get())));
    }
  }
}
