// 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.plugins.codeowners.backend;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.plugins.codeowners.JgitPath;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersTest;
import com.google.gerrit.plugins.codeowners.acceptance.testsuite.CodeOwnerConfigOperations;
import com.google.inject.Inject;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;

/** Tests for {@link CodeOwnerConfigFileUpdateScanner}. */
public class CodeOwnerConfigFileUpdateScannerTest extends AbstractCodeOwnersTest {
  @Rule public final MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

  @Mock private CodeOwnerConfigFileUpdater updater;

  @Inject private ProjectOperations projectOperations;

  private CodeOwnerConfigOperations codeOwnerConfigOperations;
  private CodeOwnerConfigFileUpdateScanner codeOwnerConfigFileUpdateScanner;

  @Before
  public void setUpCodeOwnersPlugin() throws Exception {
    codeOwnerConfigOperations =
        plugin.getSysInjector().getInstance(CodeOwnerConfigOperations.class);
    codeOwnerConfigFileUpdateScanner =
        plugin.getSysInjector().getInstance(CodeOwnerConfigFileUpdateScanner.class);
  }

  @Test
  public void cannotUpdateCodeOwnerConfigsForNullBranch() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerConfigFileUpdateScanner.update(
                    /** branchNameKey = */
                    null,
                    "Update code owner configs",
                    (codeOwnerConfigFilePath, codeOwnerConfigFileContent) -> Optional.empty()));
    assertThat(npe).hasMessageThat().isEqualTo("branchNameKey");
  }

  @Test
  public void cannotUpdateCodeOwnerConfigsWithNullCommitMessage() throws Exception {
    BranchNameKey branchNameKey = BranchNameKey.create(project, "master");
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerConfigFileUpdateScanner.update(
                    branchNameKey,
                    /** commitMessage = */
                    null,
                    (codeOwnerConfigFilePath, codeOwnerConfigFileContent) -> Optional.empty()));
    assertThat(npe).hasMessageThat().isEqualTo("commitMessage");
  }

  @Test
  public void cannotUpdateCodeOwnerConfigsWithNullUpdater() throws Exception {
    BranchNameKey branchNameKey = BranchNameKey.create(project, "master");
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerConfigFileUpdateScanner.update(
                    branchNameKey,
                    "Update code owner configs",
                    /** codeOwnerConfigFileUpdater = */
                    null));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerConfigFileUpdater");
  }

  @Test
  public void cannotUpdateCodeOwnerConfigsForNonExistingBranch() throws Exception {
    BranchNameKey branchNameKey = BranchNameKey.create(project, "non-existing");
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () ->
                codeOwnerConfigFileUpdateScanner.update(
                    branchNameKey,
                    "Update code owner configs",
                    (codeOwnerConfigFilePath, codeOwnerConfigFileContent) -> Optional.empty()));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "branch %s of project %s not found", branchNameKey.branch(), project.get()));
  }

  @Test
  public void noUpdateIfNoCodeOwnerConfigFilesExists() throws Exception {
    Optional<RevCommit> commit =
        codeOwnerConfigFileUpdateScanner.update(
            BranchNameKey.create(project, "master"), "Update code owner configs", updater);
    assertThat(commit).isEmpty();
    verifyZeroInteractions(updater);
  }

  @Test
  public void noUpdateForNonCodeOwnerConfigFiles() throws Exception {
    // Create some non code owner config files.
    try (TestRepository<Repository> testRepo =
        new TestRepository<>(repoManager.openRepository(project))) {
      Ref ref = testRepo.getRepository().exactRef("refs/heads/master");
      RevCommit head = testRepo.getRevWalk().parseCommit(ref.getObjectId());
      testRepo.update(
          "refs/heads/master",
          testRepo
              .commit()
              .parent(head)
              .message("Add some non code owner config files")
              .add("owners.txt", "some content")
              .add("owners", "some content")
              .add("foo/bar/owners.txt", "some content")
              .add("foo/bar/owners", "some content"));
    }

    Optional<RevCommit> commit =
        codeOwnerConfigFileUpdateScanner.update(
            BranchNameKey.create(project, "master"), "Update code owner configs", updater);
    assertThat(commit).isEmpty();
    verifyZeroInteractions(updater);
  }

  @Test
  public void noUpdateIfCallbackDoesntReturnNewFileContent() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(admin.email())
            .create();
    Path path =
        Paths.get(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath());
    String content = codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getContent();

    RevCommit oldHead = projectOperations.project(project).getHead("master");

    when(updater.update(path, content)).thenReturn(Optional.empty());
    Optional<RevCommit> commit =
        codeOwnerConfigFileUpdateScanner.update(
            BranchNameKey.create(project, "master"), "Update code owner configs", updater);
    assertThat(commit).isEmpty();

    // Verify the code owner config file was not updated.
    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getContent())
        .isEqualTo(content);

    // Check that no commit was created.
    RevCommit newHead = projectOperations.project(project).getHead("master");
    assertThat(newHead).isEqualTo(oldHead);
  }

  @Test
  public void updateCodeOwnerConfigFiles() throws Exception {
    TestAccount user2 = accountCreator.user2();

    CodeOwnerConfig.Key codeOwnerConfigKey1 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(admin.email())
            .create();
    Path path1 =
        Paths.get(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getFilePath());
    String oldContent1 =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getContent();
    String newContent1 = user.email() + "\n";
    when(updater.update(path1, oldContent1)).thenReturn(Optional.of(newContent1));

    CodeOwnerConfig.Key codeOwnerConfigKey2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/foo/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    Path path2 =
        Paths.get(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath());
    String oldContent2 =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getContent();
    String newContent2 = user2.email() + "\n";
    when(updater.update(path2, oldContent2)).thenReturn(Optional.of(newContent2));

    RevCommit oldHead = projectOperations.project(project).getHead("master");

    String commitMessage = "Update code owner configs";
    Optional<RevCommit> commit =
        codeOwnerConfigFileUpdateScanner.update(
            BranchNameKey.create(project, "master"), commitMessage, updater);
    assertThat(commit).isPresent();

    // Verify that we received the expected callbacks for the invalid code onwer config.
    Mockito.verify(updater).update(path1, oldContent1);
    Mockito.verify(updater).update(path2, oldContent2);
    verifyNoMoreInteractions(updater);

    // Verify the code owner config files were updated.
    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getContent())
        .isEqualTo(newContent1);
    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getContent())
        .isEqualTo(newContent2);

    // Check that exactly 1 commit was created.
    RevCommit newHead = projectOperations.project(project).getHead("master");
    assertThat(commit.get()).isEqualTo(newHead);
    assertThat(newHead).isNotEqualTo(oldHead);
    assertThat(newHead.getShortMessage()).isEqualTo(commitMessage);
    assertThat(newHead.getParent(0)).isEqualTo(oldHead);
  }

  @Test
  public void updateInvalidCodeOwnerConfigFile() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = createInvalidCodeOwnerConfig("/OWNERS", "INVALID");

    when(updater.update(any(Path.class), any(String.class)))
        .thenReturn(Optional.of("STILL INVALID"));
    Optional<RevCommit> update =
        codeOwnerConfigFileUpdateScanner.update(
            BranchNameKey.create(project, "master"), "Update code owner configs", updater);
    assertThat(update).isPresent();

    // Verify that we received the expected callbacks for the invalid code onwer config.
    Mockito.verify(updater).update(Paths.get("/OWNERS"), "INVALID");
    verifyNoMoreInteractions(updater);

    // Verify the code owner config file was updated.
    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getContent())
        .isEqualTo("STILL INVALID");
  }

  private CodeOwnerConfig.Key createInvalidCodeOwnerConfig(String filePath, String content)
      throws Exception {
    disableCodeOwnersForProject(project);
    String changeId =
        createChange("Add invalid code owners file", JgitPath.of(filePath).get(), content)
            .getChangeId();
    approve(changeId);
    gApi.changes().id(changeId).current().submit();
    enableCodeOwnersForProject(project);
    Path path = Paths.get(filePath);
    return CodeOwnerConfig.Key.create(
        project, "master", path.getParent().toString(), path.getFileName().toString());
  }
}
