// 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.restapi;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.plugins.codeowners.api.CheckCodeOwnerConfigFilesInput;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigScanner;
import com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.validation.CodeOwnerConfigValidator;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.restapi.project.ListBranches;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * REST endpoint that checks/validates the code owner config files in a project.
 *
 * <p>This REST endpoint handles {@code POST
 * /projects/<project-name>/branches/<branch-name>/code_owners.check_config} requests.
 *
 * <p>The implementation of this REST endpoint iterates over all code owner config files in the
 * project. This means the expected performance of this REST endpoint is rather low and it should
 * not be used in any critical path where performance matters.
 */
@Singleton
public class CheckCodeOwnerConfigFiles
    implements RestModifyView<ProjectResource, CheckCodeOwnerConfigFilesInput> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final Provider<CurrentUser> currentUser;
  private final PermissionBackend permissionBackend;
  private final Provider<ListBranches> listBranches;
  private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
  private final CodeOwnerConfigScanner.Factory codeOwnerConfigScannerFactory;
  private final CodeOwnerConfigValidator codeOwnerConfigValidator;

  @Inject
  public CheckCodeOwnerConfigFiles(
      Provider<CurrentUser> currentUser,
      PermissionBackend permissionBackend,
      Provider<ListBranches> listBranches,
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      CodeOwnerConfigScanner.Factory codeOwnerConfigScannerFactory,
      CodeOwnerConfigValidator codeOwnerConfigValidator) {
    this.currentUser = currentUser;
    this.permissionBackend = permissionBackend;
    this.listBranches = listBranches;
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
    this.codeOwnerConfigScannerFactory = codeOwnerConfigScannerFactory;
    this.codeOwnerConfigValidator = codeOwnerConfigValidator;
  }

  @Override
  public Response<Map<String, Map<String, List<ConsistencyProblemInfo>>>> apply(
      ProjectResource projectResource, CheckCodeOwnerConfigFilesInput input)
      throws RestApiException, PermissionBackendException, IOException {
    if (!currentUser.get().isIdentifiedUser()) {
      throw new AuthException("Authentication required");
    }

    // This REST endpoint requires the caller to be a project owner.
    permissionBackend
        .currentUser()
        .project(projectResource.getNameKey())
        .check(ProjectPermission.WRITE_CONFIG);

    logger.atFine().log(
        "checking code owner config files for project %s"
            + " (validateDisabledBranches = %s, branches = %s, path = %s, verbosity = %s)",
        projectResource.getNameKey(),
        input.validateDisabledBranches,
        input.branches,
        input.path,
        input.verbosity);

    ImmutableSet<BranchNameKey> branches = branches(projectResource);

    validateInput(projectResource.getNameKey(), branches, input);

    ImmutableMap.Builder<String, Map<String, List<ConsistencyProblemInfo>>> resultsByBranchBuilder =
        ImmutableMap.builder();
    branches.stream()
        .filter(branchNameKey -> shouldValidateBranch(input, branchNameKey))
        .filter(
            branchNameKey ->
                validateDisabledBranches(input)
                    || !codeOwnersPluginConfiguration.isDisabled(branchNameKey))
        .forEach(
            branchNameKey ->
                resultsByBranchBuilder.put(
                    branchNameKey.branch(),
                    checkBranch(input.path, branchNameKey, input.verbosity)));
    return Response.ok(resultsByBranchBuilder.build());
  }

  private ImmutableSet<BranchNameKey> branches(ProjectResource projectResource)
      throws RestApiException, IOException, PermissionBackendException {
    return listBranches.get().apply(projectResource).value().stream()
        .filter(branchInfo -> !"HEAD".equals(branchInfo.ref))
        .map(branchInfo -> BranchNameKey.create(projectResource.getNameKey(), branchInfo.ref))
        .collect(toImmutableSet());
  }

  private Map<String, List<ConsistencyProblemInfo>> checkBranch(
      String pathGlob,
      BranchNameKey branchNameKey,
      @Nullable ConsistencyProblemInfo.Status verbosity) {
    ListMultimap<String, ConsistencyProblemInfo> problemsByPath = LinkedListMultimap.create();
    CodeOwnerBackend codeOwnerBackend = codeOwnersPluginConfiguration.getBackend(branchNameKey);
    codeOwnerConfigScannerFactory
        .create()
        // Do not check the default code owner config file in refs/meta/config, as this config is
        // stored in another branch. If it should be checked users must check the code owner config
        // files in refs/meta/config explicitly.
        .includeDefaultCodeOwnerConfig(false)
        .visit(
            branchNameKey,
            codeOwnerConfig -> {
              problemsByPath.putAll(
                  codeOwnerBackend.getFilePath(codeOwnerConfig.key()).toString(),
                  checkCodeOwnerConfig(codeOwnerBackend, codeOwnerConfig, verbosity));
              return true;
            },
            (codeOwnerConfigFilePath, configInvalidException) -> {
              problemsByPath.put(
                  codeOwnerConfigFilePath.toString(),
                  new ConsistencyProblemInfo(
                      ConsistencyProblemInfo.Status.FATAL, configInvalidException.getMessage()));
            },
            pathGlob);

    return Multimaps.asMap(problemsByPath);
  }

  private ImmutableList<ConsistencyProblemInfo> checkCodeOwnerConfig(
      CodeOwnerBackend codeOwnerBackend,
      CodeOwnerConfig codeOwnerConfig,
      @Nullable ConsistencyProblemInfo.Status verbosity) {
    return codeOwnerConfigValidator
        .validateCodeOwnerConfig(
            currentUser.get().asIdentifiedUser(), codeOwnerBackend, codeOwnerConfig)
        .map(
            commitValidationMessage ->
                createConsistencyProblemInfo(commitValidationMessage, verbosity))
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(toImmutableList());
  }

  public static Optional<ConsistencyProblemInfo> createConsistencyProblemInfo(
      CommitValidationMessage commitValidationMessage,
      @Nullable ConsistencyProblemInfo.Status verbosity) {
    switch (commitValidationMessage.getType()) {
      case FATAL:
        return Optional.of(
            new ConsistencyProblemInfo(
                ConsistencyProblemInfo.Status.FATAL, commitValidationMessage.getMessage()));
      case ERROR:
        if (ConsistencyProblemInfo.Status.FATAL.equals(verbosity)) {
          // errors should not be reported
          return Optional.empty();
        }
        return Optional.of(
            new ConsistencyProblemInfo(
                ConsistencyProblemInfo.Status.ERROR, commitValidationMessage.getMessage()));
      case WARNING:
        if (ConsistencyProblemInfo.Status.FATAL.equals(verbosity)
            || ConsistencyProblemInfo.Status.ERROR.equals(verbosity)) {
          // warnings should not be reported
          return Optional.empty();
        }
        return Optional.of(
            new ConsistencyProblemInfo(
                ConsistencyProblemInfo.Status.WARNING, commitValidationMessage.getMessage()));
      case HINT:
      case OTHER:
        return Optional.empty();
    }

    throw new IllegalStateException(
        String.format(
            "unknown message type %s for message %s",
            commitValidationMessage.getType(), commitValidationMessage.getMessage()));
  }

  private void validateInput(
      Project.NameKey projectName,
      ImmutableSet<BranchNameKey> branches,
      CheckCodeOwnerConfigFilesInput input)
      throws RestApiException {
    if (input.branches != null) {
      for (String branchName : input.branches) {
        BranchNameKey branchNameKey = BranchNameKey.create(projectName, branchName);
        if (!branches.contains(branchNameKey)) {
          throw new UnprocessableEntityException(String.format("branch %s not found", branchName));
        }

        if ((input.validateDisabledBranches == null || !input.validateDisabledBranches)
            && codeOwnersPluginConfiguration.isDisabled(branchNameKey)) {
          throw new BadRequestException(
              String.format(
                  "code owners functionality for branch %s is disabled,"
                      + " set 'validate_disabled_braches' in the input to 'true' if code owner"
                      + " config files in this branch should be validated",
                  branchName));
        }
      }
    }
  }

  private static boolean shouldValidateBranch(
      CheckCodeOwnerConfigFilesInput input, BranchNameKey branchNameKey) {
    boolean shouldValidateBranch =
        input.branches == null
            || input.branches.contains(branchNameKey.branch())
            || input.branches.contains(branchNameKey.shortName());
    if (!shouldValidateBranch) {
      logger.atFine().log("skip validation for branch %s", branchNameKey.branch());
    }
    return shouldValidateBranch;
  }

  private static boolean validateDisabledBranches(CheckCodeOwnerConfigFilesInput input) {
    return input.validateDisabledBranches != null && input.validateDisabledBranches;
  }
}
