// Copyright (C) 2019 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.checks.acceptance.api;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.NotifyInfo;
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.extensions.client.ProjectWatchInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.PluginDefinedInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.plugins.checks.CheckKey;
import com.google.gerrit.plugins.checks.CheckerUuid;
import com.google.gerrit.plugins.checks.acceptance.AbstractCheckersTest;
import com.google.gerrit.plugins.checks.api.ChangeCheckInfo;
import com.google.gerrit.plugins.checks.api.CheckInput;
import com.google.gerrit.plugins.checks.api.CheckState;
import com.google.gerrit.plugins.checks.api.CombinedCheckState;
import com.google.gerrit.plugins.checks.api.RerunInput;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.testing.FakeEmailSender.Message;
import com.google.inject.Inject;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;

public class ChecksEmailIT extends AbstractCheckersTest {
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private GroupOperations groupOperations;
  @Inject private ProjectOperations projectOperations;

  private TestAccount bot;
  private TestAccount owner;
  private TestAccount reviewer;
  private TestAccount starrer;
  private TestAccount watcher;
  private PatchSet.Id patchSetId;

  @Before
  public void setup() throws Exception {
    // Create a bot account, create a bots group and add the bot as member and allow the bots group
    // to post checks.
    bot = accountCreator.create("bot", "bot@test.com", "Bot");
    AccountGroup.UUID botsAccountGroupUuid =
        groupOperations.newGroup().name("bots").addMember(bot.id()).create();
    projectOperations
        .project(allProjects)
        .forUpdate()
        .add(allowCapability("checks-administrateCheckers").group(botsAccountGroupUuid))
        .update();

    // Create a change.
    owner = admin;
    patchSetId = createChange().getPatchSetId();

    // Add a reviewer.
    reviewer = accountCreator.create("reviewer", "reviewer@test.com", "Reviewer");
    gApi.changes().id(patchSetId.changeId().get()).addReviewer(reviewer.username());

    // Star the change from some user.
    starrer = accountCreator.create("starred", "starrer@test.com", "Starrer");
    requestScopeOperations.setApiUser(starrer.id());
    gApi.accounts().self().starChange(patchSetId.changeId().toString());

    // Watch all comments of change from some user.
    watcher = accountCreator.create("watcher", "watcher@test.com", "Watcher");
    requestScopeOperations.setApiUser(watcher.id());
    ProjectWatchInfo projectWatchInfo = new ProjectWatchInfo();
    projectWatchInfo.project = project.get();
    projectWatchInfo.filter = "*";
    projectWatchInfo.notifyAllComments = true;
    gApi.accounts().self().setWatchedProjects(ImmutableList.of(projectWatchInfo));

    // Watch only change creations from some user --> user doesn't get notified by checks plugin.
    TestAccount changeCreationWatcher =
        accountCreator.create(
            "changeCreationWatcher", "changeCreationWatcher@test.com", "Change Creation Watcher");
    requestScopeOperations.setApiUser(changeCreationWatcher.id());
    projectWatchInfo = new ProjectWatchInfo();
    projectWatchInfo.project = project.get();
    projectWatchInfo.filter = "*";
    projectWatchInfo.notifyNewChanges = true;
    gApi.accounts().self().setWatchedProjects(ImmutableList.of(projectWatchInfo));

    // Add a reviewer that ignores the change --> user doesn't get notified by checks plugin.
    TestAccount ignorer = accountCreator.create("ignorer", "ignorer@test.com", "Ignorer");
    requestScopeOperations.setApiUser(admin.id());
    gApi.changes().id(patchSetId.changeId().get()).addReviewer(ignorer.username());
    requestScopeOperations.setApiUser(ignorer.id());
    gApi.changes().id(patchSetId.changeId().get()).ignore(true);

    // Reset request scope to admin.
    requestScopeOperations.setApiUser(admin.id());
  }

  @Test
  public void combinedCheckUpdatedEmailAfterCheckCreation() throws Exception {
    // Create a required checker.
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).required().create();

    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS);

    sender.clear();

    // Post a new check that changes the combined check state to FAILED.
    requestScopeOperations.setApiUser(bot.id());
    CheckInput input = new CheckInput();
    input.checkerUuid = checkerUuid.get();
    input.state = CheckState.FAILED;
    checksApiFactory.revision(patchSetId).create(input).get();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    // Except one email because the combined check state was updated.
    List<Message> messages = sender.getMessages();
    assertThat(messages).hasSize(1);

    Message message = messages.get(0);
    assertThat(message.from().getName()).isEqualTo(bot.fullName() + " (Code Review)");
    assertThat(message.body())
        .contains("The combined check state has been updated to " + CombinedCheckState.FAILED);
    assertThat(message.rcpt())
        .containsExactly(
            owner.getEmailAddress(),
            reviewer.getEmailAddress(),
            starrer.getEmailAddress(),
            watcher.getEmailAddress());
  }

  @Test
  public void noCombinedCheckUpdatedEmailOnCheckCreationIfCombinedCheckStateIsNotChanged()
      throws Exception {
    // Create two required checkers.
    CheckerUuid checkerUuid1 =
        checkerOperations.newChecker().repository(project).required().create();
    CheckerUuid checkerUuid2 =
        checkerOperations.newChecker().repository(project).required().create();

    // Create a check that sets the combined check state to FAILED.
    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid1);
    checkOperations.newCheck(checkKey).state(CheckState.FAILED).upsert();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    sender.clear();

    // Post a new check that doesn't change the combined check state..
    requestScopeOperations.setApiUser(bot.id());
    CheckInput input = new CheckInput();
    input.checkerUuid = checkerUuid2.get();
    input.state = CheckState.SCHEDULED;
    checksApiFactory.revision(patchSetId).create(input).get();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    // Except that no email was sent because the combined check state was not updated.
    assertThat(sender.getMessages()).isEmpty();
  }

  @Test
  public void combinedCheckUpdatedEmailAfterCheckUpdate() throws Exception {
    // Create a required checker.
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).required().create();

    // Create a check that sets the combined check state to FAILED.
    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).state(CheckState.FAILED).upsert();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    sender.clear();

    // Update the new check so that the combined check state is changed to IN_PROGRESS.
    requestScopeOperations.setApiUser(bot.id());
    CheckInput input = new CheckInput();
    input.checkerUuid = checkerUuid.get();
    input.state = CheckState.RUNNING;
    checksApiFactory.revision(patchSetId).create(input).get();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS);

    // Except one email because the combined check state was updated.
    List<Message> messages = sender.getMessages();
    assertThat(messages).hasSize(1);

    Message message = messages.get(0);
    assertThat(message.from().getName()).isEqualTo(bot.fullName() + " (Code Review)");
    assertThat(message.body())
        .contains("The combined check state has been updated to " + CombinedCheckState.IN_PROGRESS);
    assertThat(message.rcpt())
        .containsExactly(
            owner.getEmailAddress(),
            reviewer.getEmailAddress(),
            starrer.getEmailAddress(),
            watcher.getEmailAddress());
  }

  @Test
  public void noCombinedCheckUpdatedEmailOnCheckUpdateIfCombinedCheckStateIsNotChanged()
      throws Exception {
    // Create two required checkers.
    CheckerUuid checkerUuid1 =
        checkerOperations.newChecker().repository(project).required().create();
    CheckerUuid checkerUuid2 =
        checkerOperations.newChecker().repository(project).required().create();

    // Create 2 checks that set the combined check state to FAILED.
    CheckKey checkKey1 = CheckKey.create(project, patchSetId, checkerUuid1);
    checkOperations.newCheck(checkKey1).state(CheckState.FAILED).upsert();
    CheckKey checkKey2 = CheckKey.create(project, patchSetId, checkerUuid2);
    checkOperations.newCheck(checkKey2).state(CheckState.FAILED).upsert();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    sender.clear();

    // Update one of the checks in a way so that doesn't change the combined check state.
    requestScopeOperations.setApiUser(bot.id());
    CheckInput input = new CheckInput();
    input.checkerUuid = checkerUuid2.get();
    input.state = CheckState.SCHEDULED;
    checksApiFactory.revision(patchSetId).create(input).get();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    // Except that no email was sent because the combined check state was not updated.
    assertThat(sender.getMessages()).isEmpty();
  }

  @Test
  public void combinedCheckUpdatedEmailAfterCheckRerun() throws Exception {
    // Create a required checker.
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).required().create();

    // Create a check that sets the combined check state to FAILED.
    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.newCheck(checkKey).state(CheckState.FAILED).upsert();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    sender.clear();

    // Rerun the check so that the combined check state is changed to IN_PROGRESS.
    requestScopeOperations.setApiUser(bot.id());
    checksApiFactory.revision(patchSetId).id(checkKey.checkerUuid()).rerun();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS);

    // Expect one email because the combined check state was updated.
    List<Message> messages = sender.getMessages();
    assertThat(messages).hasSize(1);

    Message message = messages.get(0);
    assertThat(message.from().getName()).isEqualTo(bot.fullName() + " (Code Review)");
    assertThat(message.body())
        .contains("The combined check state has been updated to " + CombinedCheckState.IN_PROGRESS);
    assertThat(message.rcpt())
        .containsExactly(
            owner.getEmailAddress(),
            reviewer.getEmailAddress(),
            starrer.getEmailAddress(),
            watcher.getEmailAddress());
  }

  @Test
  public void noCombinedCheckUpdatedEmailOnCheckRerunIfCombinedCheckStateIsNotChanged()
      throws Exception {
    // Create two required checkers.
    CheckerUuid checkerUuid1 =
        checkerOperations.newChecker().repository(project).required().create();
    CheckerUuid checkerUuid2 =
        checkerOperations.newChecker().repository(project).required().create();

    // Create 2 checks that set the combined check state to FAILED.
    CheckKey checkKey1 = CheckKey.create(project, patchSetId, checkerUuid1);
    checkOperations.newCheck(checkKey1).state(CheckState.FAILED).upsert();
    CheckKey checkKey2 = CheckKey.create(project, patchSetId, checkerUuid2);
    checkOperations.newCheck(checkKey2).state(CheckState.FAILED).upsert();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    sender.clear();

    // Rerun only one check so that the combined check state stays FAILED.
    requestScopeOperations.setApiUser(bot.id());
    checksApiFactory.revision(patchSetId).id(checkKey1.checkerUuid()).rerun();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    // Expect that no email was sent because the combined check state was not updated.
    assertThat(sender.getMessages()).isEmpty();
  }

  @Test
  public void postCheckRespectsNotifySettings() throws Exception {
    // Create a required checker.
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).required().create();

    testNotifySettingsForPostCheck(
        checkerUuid, NotifyHandling.ALL, owner, reviewer, starrer, watcher);
    testNotifySettingsForPostCheck(checkerUuid, NotifyHandling.OWNER, owner);
    testNotifySettingsForPostCheck(checkerUuid, NotifyHandling.OWNER_REVIEWERS, owner, reviewer);
    testNotifySettingsForPostCheck(checkerUuid, NotifyHandling.NONE);

    testNotifySettingsForPostCheck(
        checkerUuid,
        ImmutableSet.of(user),
        NotifyHandling.ALL,
        user,
        owner,
        reviewer,
        starrer,
        watcher);
    testNotifySettingsForPostCheck(
        checkerUuid, ImmutableSet.of(user), NotifyHandling.OWNER, user, owner);
    testNotifySettingsForPostCheck(
        checkerUuid, ImmutableSet.of(user), NotifyHandling.OWNER_REVIEWERS, user, owner, reviewer);
    testNotifySettingsForPostCheck(checkerUuid, ImmutableSet.of(user), NotifyHandling.NONE, user);
  }

  private void testNotifySettingsForPostCheck(
      CheckerUuid checkerUuid, NotifyHandling notify, TestAccount... expectedRecipients)
      throws RestApiException {
    testNotifySettingsForPostCheck(checkerUuid, ImmutableSet.of(), notify, expectedRecipients);
  }

  private void testNotifySettingsForPostCheck(
      CheckerUuid checkerUuid,
      Set<TestAccount> accountsToNotify,
      NotifyHandling notify,
      TestAccount... expectedRecipients)
      throws RestApiException {
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS);

    sender.clear();

    // Post a new check that changes the combined check state to FAILED.
    requestScopeOperations.setApiUser(bot.id());
    CheckInput input = new CheckInput();
    if (!accountsToNotify.isEmpty()) {
      input.notifyDetails =
          ImmutableMap.of(
              RecipientType.TO,
              new NotifyInfo(
                  accountsToNotify.stream().map(TestAccount::username).collect(toImmutableList())));
    }
    input.notify = notify;
    input.checkerUuid = checkerUuid.get();
    input.state = CheckState.FAILED;
    checksApiFactory.revision(patchSetId).create(input).get();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    List<Message> messages = sender.getMessages();
    if (expectedRecipients.length == 0) {
      assertThat(messages).isEmpty();
    } else {
      assertThat(messages).hasSize(1);

      Message message = messages.get(0);
      assertThat(message.from().getName()).isEqualTo(bot.fullName() + " (Code Review)");
      assertThat(message.body())
          .contains("The combined check state has been updated to " + CombinedCheckState.FAILED);
      assertThat(message.rcpt())
          .containsExactlyElementsIn(
              Arrays.stream(expectedRecipients)
                  .map(TestAccount::getEmailAddress)
                  .collect(toImmutableList()));
    }

    // reset combined check state
    input.state = CheckState.SCHEDULED;
    checksApiFactory.revision(patchSetId).create(input).get();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS);
  }

  @Test
  public void rerunCheckRespectsNotifySettings() throws Exception {
    // Create a required checker.
    CheckerUuid checkerUuid =
        checkerOperations.newChecker().repository(project).required().create();

    testNotifySettingsForRerunCheck(
        checkerUuid, NotifyHandling.ALL, owner, reviewer, starrer, watcher);
    testNotifySettingsForRerunCheck(checkerUuid, NotifyHandling.OWNER, owner);
    testNotifySettingsForRerunCheck(checkerUuid, NotifyHandling.OWNER_REVIEWERS, owner, reviewer);
    testNotifySettingsForRerunCheck(checkerUuid, NotifyHandling.NONE);

    testNotifySettingsForRerunCheck(
        checkerUuid,
        ImmutableSet.of(user),
        NotifyHandling.ALL,
        user,
        owner,
        reviewer,
        starrer,
        watcher);
    testNotifySettingsForRerunCheck(
        checkerUuid, ImmutableSet.of(user), NotifyHandling.OWNER, user, owner);
    testNotifySettingsForRerunCheck(
        checkerUuid, ImmutableSet.of(user), NotifyHandling.OWNER_REVIEWERS, user, owner, reviewer);
    testNotifySettingsForRerunCheck(checkerUuid, ImmutableSet.of(user), NotifyHandling.NONE, user);
  }

  private void testNotifySettingsForRerunCheck(
      CheckerUuid checkerUuid, NotifyHandling notify, TestAccount... expectedRecipients)
      throws RestApiException {
    testNotifySettingsForPostCheck(checkerUuid, ImmutableSet.of(), notify, expectedRecipients);
  }

  private void testNotifySettingsForRerunCheck(
      CheckerUuid checkerUuid,
      Set<TestAccount> accountsToNotify,
      NotifyHandling notify,
      TestAccount... expectedRecipients)
      throws RestApiException {
    // Create a check that sets the combined check state to FAILED.
    CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid);
    checkOperations.check(checkKey).forUpdate().state(CheckState.FAILED).upsert();
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);

    sender.clear();

    // Post a new check that changes the combined check state to FAILED.
    requestScopeOperations.setApiUser(bot.id());
    RerunInput rerunInput = new RerunInput();
    if (!accountsToNotify.isEmpty()) {
      rerunInput.notifyDetails =
          ImmutableMap.of(
              RecipientType.TO,
              new NotifyInfo(
                  accountsToNotify.stream().map(TestAccount::username).collect(toImmutableList())));
    }
    rerunInput.notify = notify;
    checksApiFactory.revision(patchSetId).id(checkKey.checkerUuid()).rerun(rerunInput);
    assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS);

    List<Message> messages = sender.getMessages();
    if (expectedRecipients.length == 0) {
      assertThat(messages).isEmpty();
    } else {
      assertThat(messages).hasSize(1);

      Message message = messages.get(0);
      assertThat(message.from().getName()).isEqualTo(bot.fullName() + " (Code Review)");
      assertThat(message.body())
          .contains(
              "The combined check state has been updated to " + CombinedCheckState.IN_PROGRESS);
      assertThat(message.rcpt())
          .containsExactlyElementsIn(
              Arrays.stream(expectedRecipients)
                  .map(TestAccount::getEmailAddress)
                  .collect(toImmutableList()));
    }
  }

  private CombinedCheckState getCombinedCheckState() throws RestApiException {
    ChangeInfo changeInfo =
        gApi.changes()
            .id(patchSetId.changeId().get())
            .get(ImmutableListMultimap.of("checks--combined", "true"));
    ImmutableList<PluginDefinedInfo> infos =
        changeInfo.plugins.stream().filter(i -> i.name.equals("checks")).collect(toImmutableList());
    assertThat(infos).hasSize(1);
    assertThat(infos.get(0)).isInstanceOf(ChangeCheckInfo.class);
    return ((ChangeCheckInfo) infos.get(0)).combinedState;
  }
}
