// 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.acceptance.api;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
import com.google.gerrit.plugins.codeowners.api.CodeOwnerBranchConfigInfo;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackendId;
import com.google.gerrit.plugins.codeowners.backend.FallbackCodeOwners;
import com.google.gerrit.plugins.codeowners.backend.config.BackendConfig;
import com.google.gerrit.plugins.codeowners.backend.config.GeneralConfig;
import com.google.gerrit.plugins.codeowners.backend.config.OverrideApprovalConfig;
import com.google.gerrit.plugins.codeowners.backend.config.RequiredApprovalConfig;
import com.google.gerrit.plugins.codeowners.backend.config.StatusConfig;
import com.google.gerrit.plugins.codeowners.common.MergeCommitStrategy;
import org.junit.Before;
import org.junit.Test;

/**
 * Acceptance test for the {@link
 * com.google.gerrit.plugins.codeowners.restapi.GetCodeOwnerBranchConfig} REST endpoint.
 *
 * <p>Further tests for the {@link
 * com.google.gerrit.plugins.codeowners.restapi.GetCodeOwnerBranchConfig} REST endpoint that require
 * using the REST API are implemented in {@link
 * com.google.gerrit.plugins.codeowners.acceptance.restapi.GetCodeOwnerBranchConfigRestIT}.
 */
public class GetCodeOwnerBranchConfigIT extends AbstractCodeOwnersIT {
  private BackendConfig backendConfig;

  @Before
  public void setup() throws Exception {
    backendConfig = plugin.getSysInjector().getInstance(BackendConfig.class);
  }

  @Test
  public void cannotGetConfigForHiddenProject() throws Exception {
    ConfigInput configInput = new ConfigInput();
    configInput.state = ProjectState.HIDDEN;
    gApi.projects().name(project.get()).config(configInput);

    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> projectCodeOwnersApiFactory.project(project).branch("master").getConfig());
    assertThat(exception).hasMessageThat().isEqualTo("project state HIDDEN does not permit read");
  }

  @Test
  public void getDefaultConfig() throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.general.fileExtension).isNull();
    assertThat(codeOwnerBranchConfigInfo.general.mergeCommitStrategy)
        .isEqualTo(MergeCommitStrategy.ALL_CHANGED_FILES);
    assertThat(codeOwnerBranchConfigInfo.general.fallbackCodeOwners)
        .isEqualTo(FallbackCodeOwners.NONE);
    assertThat(codeOwnerBranchConfigInfo.general.implicitApprovals).isNull();
    assertThat(codeOwnerBranchConfigInfo.general.overrideInfoUrl).isNull();
    assertThat(codeOwnerBranchConfigInfo.disabled).isNull();
    assertThat(codeOwnerBranchConfigInfo.backendId)
        .isEqualTo(CodeOwnerBackendId.getBackendId(backendConfig.getDefaultBackend().getClass()));
    assertThat(codeOwnerBranchConfigInfo.requiredApproval.label)
        .isEqualTo(RequiredApprovalConfig.DEFAULT_LABEL);
    assertThat(codeOwnerBranchConfigInfo.requiredApproval.value)
        .isEqualTo(RequiredApprovalConfig.DEFAULT_VALUE);
    assertThat(codeOwnerBranchConfigInfo.overrideApproval).isNull();
  }

  @Test
  public void getConfigWithConfiguredFileExtension() throws Exception {
    configureFileExtension(project, "foo");
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.general.fileExtension).isEqualTo("foo");
  }

  @Test
  public void getConfigWithConfiguredOverrideInfoUrl() throws Exception {
    configureOverrideInfoUrl(project, "http://foo.example.com");
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.general.overrideInfoUrl)
        .isEqualTo("http://foo.example.com");
  }

  @Test
  public void getConfigWithConfiguredMergeCommitStrategy() throws Exception {
    configureMergeCommitStrategy(project, MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION);
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.general.mergeCommitStrategy)
        .isEqualTo(MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION);
  }

  @Test
  public void getConfigWithConfiguredFallbackCodeOwners() throws Exception {
    configureFallbackCodeOwners(project, FallbackCodeOwners.ALL_USERS);
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.general.fallbackCodeOwners)
        .isEqualTo(FallbackCodeOwners.ALL_USERS);
  }

  @Test
  public void getConfigForBranchOfDisabledProject() throws Exception {
    disableCodeOwnersForProject(project);
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.disabled).isTrue();
    assertThat(codeOwnerBranchConfigInfo.general).isNull();
    assertThat(codeOwnerBranchConfigInfo.backendId).isNull();
    assertThat(codeOwnerBranchConfigInfo.requiredApproval).isNull();
    assertThat(codeOwnerBranchConfigInfo.overrideApproval).isNull();
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabled", value = "true")
  @GerritConfig(name = "plugin.code-owners.requiredApproval", value = "INVALID")
  public void getConfigForBranchOfDisabledProject_invalidPluginConfig() throws Exception {
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.disabled).isTrue();
    assertThat(codeOwnerBranchConfigInfo.general).isNull();
    assertThat(codeOwnerBranchConfigInfo.backendId).isNull();
    assertThat(codeOwnerBranchConfigInfo.requiredApproval).isNull();
    assertThat(codeOwnerBranchConfigInfo.overrideApproval).isNull();
  }

  @Test
  public void getConfigForDisabledBranch() throws Exception {
    configureDisabledBranch(project, "refs/heads/master");
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.disabled).isTrue();
    assertThat(codeOwnerBranchConfigInfo.general).isNull();
    assertThat(codeOwnerBranchConfigInfo.backendId).isNull();
    assertThat(codeOwnerBranchConfigInfo.requiredApproval).isNull();
    assertThat(codeOwnerBranchConfigInfo.overrideApproval).isNull();
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabledBranch", value = "refs/heads/master")
  @GerritConfig(name = "plugin.code-owners.requiredApproval", value = "INVALID")
  public void getConfigForDisabledBranch_invalidPluginConfig() throws Exception {
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.disabled).isTrue();
    assertThat(codeOwnerBranchConfigInfo.general).isNull();
    assertThat(codeOwnerBranchConfigInfo.backendId).isNull();
    assertThat(codeOwnerBranchConfigInfo.requiredApproval).isNull();
    assertThat(codeOwnerBranchConfigInfo.overrideApproval).isNull();
  }

  @Test
  public void getConfigWithConfiguredBackend() throws Exception {
    String otherBackendId = getOtherCodeOwnerBackend(backendConfig.getDefaultBackend());
    configureBackend(project, otherBackendId);
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.backendId).isEqualTo(otherBackendId);
  }

  @Test
  public void getConfigWithConfiguredBackendForBranch() throws Exception {
    String otherBackendId = getOtherCodeOwnerBackend(backendConfig.getDefaultBackend());
    configureBackend(project, "refs/heads/master", otherBackendId);
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.backendId).isEqualTo(otherBackendId);
  }

  @Test
  public void getConfigWithConfiguredRequiredApproval() throws Exception {
    configureRequiredApproval(project, "Code-Review+2");
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.requiredApproval.label).isEqualTo("Code-Review");
    assertThat(codeOwnerBranchConfigInfo.requiredApproval.value).isEqualTo(2);
  }

  @Test
  public void getConfigWithConfiguredOverrideApproval() throws Exception {
    configureOverrideApproval(project, "Code-Review+2");
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.overrideApproval).hasSize(1);
    assertThat(codeOwnerBranchConfigInfo.overrideApproval.get(0).label).isEqualTo("Code-Review");
    assertThat(codeOwnerBranchConfigInfo.overrideApproval.get(0).value).isEqualTo(2);
  }

  @Test
  public void getConfigWithMultipleConfiguredOverrideApproval() throws Exception {
    createOwnersOverrideLabel();
    setCodeOwnersConfig(
        project,
        /* subsection= */ null,
        OverrideApprovalConfig.KEY_OVERRIDE_APPROVAL,
        ImmutableList.of("Owners-Override+1", "Code-Review+2"));
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.overrideApproval).hasSize(2);
    assertThat(codeOwnerBranchConfigInfo.overrideApproval.get(0).label).isEqualTo("Code-Review");
    assertThat(codeOwnerBranchConfigInfo.overrideApproval.get(0).value).isEqualTo(2);
    assertThat(codeOwnerBranchConfigInfo.overrideApproval.get(1).label)
        .isEqualTo("Owners-Override");
    assertThat(codeOwnerBranchConfigInfo.overrideApproval.get(1).value).isEqualTo(1);
  }

  @Test
  public void getConfigWithEnabledImplicitApprovals() throws Exception {
    configureImplicitApprovals(project);
    CodeOwnerBranchConfigInfo codeOwnerBranchConfigInfo =
        projectCodeOwnersApiFactory.project(project).branch("master").getConfig();
    assertThat(codeOwnerBranchConfigInfo.general.implicitApprovals).isTrue();
  }

  private void configureFileExtension(Project.NameKey project, String fileExtension)
      throws Exception {
    setCodeOwnersConfig(
        project, /* subsection= */ null, GeneralConfig.KEY_FILE_EXTENSION, fileExtension);
  }

  private void configureOverrideInfoUrl(Project.NameKey project, String overrideInfoUrl)
      throws Exception {
    setCodeOwnersConfig(
        project, /* subsection= */ null, GeneralConfig.KEY_OVERRIDE_INFO_URL, overrideInfoUrl);
  }

  private void configureMergeCommitStrategy(
      Project.NameKey project, MergeCommitStrategy mergeCommitStrategy) throws Exception {
    setCodeOwnersConfig(
        project,
        /* subsection= */ null,
        GeneralConfig.KEY_MERGE_COMMIT_STRATEGY,
        mergeCommitStrategy.name());
  }

  private void configureFallbackCodeOwners(
      Project.NameKey project, FallbackCodeOwners fallbackCodeOwners) throws Exception {
    setCodeOwnersConfig(
        project,
        /* subsection= */ null,
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        fallbackCodeOwners.name());
  }

  private void configureDisabledBranch(Project.NameKey project, String disabledBranch)
      throws Exception {
    setCodeOwnersConfig(
        project, /* subsection= */ null, StatusConfig.KEY_DISABLED_BRANCH, disabledBranch);
  }

  private void configureBackend(Project.NameKey project, String backendName) throws Exception {
    configureBackend(project, /* branch= */ null, backendName);
  }

  private void configureBackend(
      Project.NameKey project, @Nullable String branch, String backendName) throws Exception {
    setCodeOwnersConfig(project, branch, BackendConfig.KEY_BACKEND, backendName);
  }

  private void configureRequiredApproval(Project.NameKey project, String requiredApproval)
      throws Exception {
    setCodeOwnersConfig(
        project,
        /* subsection= */ null,
        RequiredApprovalConfig.KEY_REQUIRED_APPROVAL,
        requiredApproval);
  }

  private void configureOverrideApproval(Project.NameKey project, String overrideApproval)
      throws Exception {
    setCodeOwnersConfig(
        project,
        /* subsection= */ null,
        OverrideApprovalConfig.KEY_OVERRIDE_APPROVAL,
        overrideApproval);
  }

  private void configureImplicitApprovals(Project.NameKey project) throws Exception {
    setCodeOwnersConfig(
        project, /* subsection= */ null, GeneralConfig.KEY_ENABLE_IMPLICIT_APPROVALS, "true");
  }

  /** Returns the ID of a code owner backend that is not the given backend. */
  private String getOtherCodeOwnerBackend(CodeOwnerBackend codeOwnerBackend) {
    for (CodeOwnerBackendId codeOwnerBackendId : CodeOwnerBackendId.values()) {
      if (!codeOwnerBackendId.getCodeOwnerBackendClass().equals(codeOwnerBackend.getClass())) {
        return codeOwnerBackendId.getBackendId();
      }
    }
    throw new IllegalStateException(
        String.format("couldn't find other backend than %s", codeOwnerBackend.getClass()));
  }
}
