// 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.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.metrics.Timer0;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginProjectConfigSnapshot;
import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics;
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;
  private final CodeOwnerMetrics codeOwnerMetrics;

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

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

    CodeOwnersPluginProjectConfigSnapshot codeOwnersConfig =
        codeOwnersPluginConfiguration.getProjectConfig(projectName);
    int maxPathsInChangeMessages = codeOwnersConfig.getMaxPathsInChangeMessages();
    if (codeOwnersConfig.isDisabled(event.getChange().branch) || maxPathsInChangeMessages <= 0) {
      return;
    }

    try (Timer0.Context ctx = codeOwnerMetrics.addChangeMessageOnAddReviewer.start()) {
      retryHelper
          .changeUpdate(
              "addCodeOwnersMessageOnAddReviewer",
              updateFactory -> {
                try (BatchUpdate batchUpdate =
                    updateFactory.create(projectName, userProvider.get(), TimeUtil.nowTs())) {
                  batchUpdate.addOp(
                      changeId, new Op(event.getReviewers(), maxPathsInChangeMessages));
                  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;
    private final int limit;

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

    @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 {
        // limit + 1, so that we can show an indicator if there are more than <limit> files.
        ownedPaths =
            codeOwnerApprovalCheck.getOwnedPaths(
                changeNotes,
                changeNotes.getCurrentPatchSet(),
                reviewerAccountId,
                /* start= */ 0,
                limit + 1);
      } 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()));

      if (ownedPaths.size() <= limit) {
        appendPaths(message, ownedPaths.stream());
      } else {
        appendPaths(message, ownedPaths.stream().limit(limit));
        message.append("(more files)\n");
      }

      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())));
    }
  }
}
