// 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.RetryHelper;
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 RetryHelper retryHelper;
  private final ChangeNotes.Factory changeNotesFactory;
  private final AccountCache accountCache;
  private final ChangeMessagesUtil changeMessageUtil;

  @Inject
  CodeOwnersOnAddReviewer(
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      CodeOwnerApprovalCheck codeOwnerApprovalCheck,
      Provider<CurrentUser> userProvider,
      RetryHelper retryHelper,
      ChangeNotes.Factory changeNotesFactory,
      AccountCache accountCache,
      ChangeMessagesUtil changeMessageUtil) {
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
    this.codeOwnerApprovalCheck = codeOwnerApprovalCheck;
    this.userProvider = userProvider;
    this.retryHelper = retryHelper;
    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 {
      retryHelper
          .changeUpdate(
              "addCodeOwnersMessageOnAddReviewer",
              updateFactory -> {
                try (BatchUpdate batchUpdate =
                    updateFactory.create(projectName, userProvider.get(), TimeUtil.nowTs())) {
                  batchUpdate.addOp(changeId, new Op(event.getReviewers()));
                  batchUpdate.execute();
                }
                return null;
              })
          .call();
    } catch (Exception 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())));
    }
  }
}
