// 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 com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.backend.config.InvalidPluginConfigurationException;
import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics;
import com.google.gerrit.server.ExceptionHook;
import com.google.inject.Inject;
import java.nio.file.InvalidPathException;
import java.util.Optional;

/**
 * Class to define the HTTP response status code and message for exceptions that can occur for all
 * REST endpoints and which should not result in a 500 Internal Server Error.
 *
 * <p>The following exceptions are handled:
 *
 * <ul>
 *   <li>exception due to invalid plugin configuration ({@link
 *       InvalidPluginConfigurationException}): mapped to {@code 409 Conflict}
 *   <li>exception due to invalid code owner config files ({@link
 *       org.eclipse.jgit.errors.ConfigInvalidException}): mapped to {@code 409 Conflict}
 * </ul>
 */
public class CodeOwnersExceptionHook implements ExceptionHook {
  private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
  private final CodeOwnerMetrics codeOwnerMetrics;

  @Inject
  CodeOwnersExceptionHook(
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      CodeOwnerMetrics codeOwnerMetric) {
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
    this.codeOwnerMetrics = codeOwnerMetric;
  }

  @Override
  public boolean skipRetryWithTrace(String actionType, String actionName, Throwable throwable) {
    return isCausedByConfigurationError(throwable);
  }

  @Override
  public ImmutableList<String> getUserMessages(Throwable throwable, @Nullable String traceId) {
    Optional<InvalidPluginConfigurationException> invalidPluginConfigurationException =
        getInvalidPluginConfigurationCause(throwable);
    if (invalidPluginConfigurationException.isPresent()) {
      return ImmutableList.of(invalidPluginConfigurationException.get().getMessage());
    }

    Optional<InvalidCodeOwnerConfigException> invalidCodeOwnerConfigException =
        CodeOwners.getInvalidCodeOwnerConfigCause(throwable);
    if (invalidCodeOwnerConfigException.isPresent()) {
      codeOwnerMetrics.countInvalidCodeOwnerConfigFiles.increment(
          invalidCodeOwnerConfigException.get().getProjectName().get(),
          invalidCodeOwnerConfigException.get().getRef(),
          invalidCodeOwnerConfigException.get().getCodeOwnerConfigFilePath());

      ImmutableList.Builder<String> messages = ImmutableList.builder();
      messages.add(invalidCodeOwnerConfigException.get().getMessage());
      codeOwnersPluginConfiguration
          .getProjectConfig(invalidCodeOwnerConfigException.get().getProjectName())
          .getInvalidCodeOwnerConfigInfoUrl()
          .ifPresent(
              invalidCodeOwnerConfigInfoUrl ->
                  messages.add(String.format("For help check %s", invalidCodeOwnerConfigInfoUrl)));
      return messages.build();
    }

    Optional<InvalidPathException> invalidPathException = getInvalidPathException(throwable);
    if (invalidPathException.isPresent()) {
      return ImmutableList.of(invalidPathException.get().getMessage());
    }

    // This must be done last since some of the exceptions we handle above may be wrapped in a
    // CodeOwnersInternalServerErrorException.
    Optional<CodeOwnersInternalServerErrorException> codeOwnersInternalServerErrorException =
        getCodeOwnersInternalServerErrorException(throwable);
    if (codeOwnersInternalServerErrorException.isPresent()) {
      return ImmutableList.of(codeOwnersInternalServerErrorException.get().getUserVisibleMessage());
    }

    return ImmutableList.of();
  }

  @Override
  public Optional<Status> getStatus(Throwable throwable) {
    if (isCausedByConfigurationError(throwable)) {
      return Optional.of(Status.create(409, "Conflict"));
    }
    return Optional.empty();
  }

  private static Optional<CodeOwnersInternalServerErrorException>
      getCodeOwnersInternalServerErrorException(Throwable throwable) {
    return getCause(CodeOwnersInternalServerErrorException.class, throwable);
  }

  public static boolean isCausedByConfigurationError(Throwable throwable) {
    return isInvalidPluginConfigurationException(throwable)
        || isInvalidCodeOwnerConfigException(throwable)
        || isInvalidPathException(throwable);
  }

  public static Optional<? extends Exception> getCauseOfConfigurationError(Throwable throwable) {
    Optional<InvalidPathException> invalidPathException =
        CodeOwnersExceptionHook.getInvalidPathException(throwable);
    if (invalidPathException.isPresent()) {
      return invalidPathException;
    }

    Optional<InvalidPluginConfigurationException> invalidPluginConfigurationException =
        CodeOwnersExceptionHook.getInvalidPluginConfigurationCause(throwable);
    if (invalidPluginConfigurationException.isPresent()) {
      return invalidPluginConfigurationException;
    }

    return CodeOwners.getInvalidCodeOwnerConfigCause(throwable);
  }

  private static boolean isInvalidPluginConfigurationException(Throwable throwable) {
    return getInvalidPluginConfigurationCause(throwable).isPresent();
  }

  public static Optional<InvalidPluginConfigurationException> getInvalidPluginConfigurationCause(
      Throwable throwable) {
    return getCause(InvalidPluginConfigurationException.class, throwable);
  }

  private static boolean isInvalidPathException(Throwable throwable) {
    return getInvalidPathException(throwable).isPresent();
  }

  public static Optional<InvalidPathException> getInvalidPathException(Throwable throwable) {
    return getCause(InvalidPathException.class, throwable);
  }

  private static <T extends Throwable> Optional<T> getCause(
      Class<T> exceptionClass, Throwable throwable) {
    return Throwables.getCausalChain(throwable).stream()
        .filter(exceptionClass::isInstance)
        .map(exceptionClass::cast)
        .findFirst();
  }

  private static boolean isInvalidCodeOwnerConfigException(Throwable throwable) {
    return CodeOwners.getInvalidCodeOwnerConfigCause(throwable).isPresent();
  }
}
