// Copyright 2021 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.bazel.bzlmod;

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

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkValue;
import net.starlark.java.syntax.Location;

/** The Starlark object passed to the implementation function of module extension metadata. */
@StarlarkBuiltin(
    name = "extension_metadata",
    category = DocCategory.BUILTIN,
    doc =
        "Return values of this type from a module extension's implementation function to "
            + "provide metadata about the repositories generated by the extension to Bazel.")
public class ModuleExtensionMetadata implements StarlarkValue {
  @Nullable private final ImmutableSet<String> explicitRootModuleDirectDeps;
  @Nullable private final ImmutableSet<String> explicitRootModuleDirectDevDeps;
  private final UseAllRepos useAllRepos;

  private ModuleExtensionMetadata(
      @Nullable Set<String> explicitRootModuleDirectDeps,
      @Nullable Set<String> explicitRootModuleDirectDevDeps,
      UseAllRepos useAllRepos) {
    this.explicitRootModuleDirectDeps =
        explicitRootModuleDirectDeps != null
            ? ImmutableSet.copyOf(explicitRootModuleDirectDeps)
            : null;
    this.explicitRootModuleDirectDevDeps =
        explicitRootModuleDirectDevDeps != null
            ? ImmutableSet.copyOf(explicitRootModuleDirectDevDeps)
            : null;
    this.useAllRepos = useAllRepos;
  }

  static ModuleExtensionMetadata create(
      Object rootModuleDirectDepsUnchecked, Object rootModuleDirectDevDepsUnchecked)
      throws EvalException {
    if (rootModuleDirectDepsUnchecked == Starlark.NONE
        && rootModuleDirectDevDepsUnchecked == Starlark.NONE) {
      return new ModuleExtensionMetadata(null, null, UseAllRepos.NO);
    }

    // When root_module_direct_deps = "all", accept both root_module_direct_dev_deps = None and
    // root_module_direct_dev_deps = [], but not root_module_direct_dev_deps = ["some_repo"].
    if (rootModuleDirectDepsUnchecked.equals("all")
        && rootModuleDirectDevDepsUnchecked.equals(StarlarkList.immutableOf())) {
      return new ModuleExtensionMetadata(null, null, UseAllRepos.REGULAR);
    }

    if (rootModuleDirectDevDepsUnchecked.equals("all")
        && rootModuleDirectDepsUnchecked.equals(StarlarkList.immutableOf())) {
      return new ModuleExtensionMetadata(null, null, UseAllRepos.DEV);
    }

    if (rootModuleDirectDepsUnchecked.equals("all")
        || rootModuleDirectDevDepsUnchecked.equals("all")) {
      throw Starlark.errorf(
          "if one of root_module_direct_deps and root_module_direct_dev_deps is "
              + "\"all\", the other must be an empty list");
    }

    if (rootModuleDirectDepsUnchecked instanceof String
        || rootModuleDirectDevDepsUnchecked instanceof String) {
      throw Starlark.errorf(
          "root_module_direct_deps and root_module_direct_dev_deps must be "
              + "None, \"all\", or a list of strings");
    }
    if ((rootModuleDirectDepsUnchecked == Starlark.NONE)
        != (rootModuleDirectDevDepsUnchecked == Starlark.NONE)) {
      throw Starlark.errorf(
          "root_module_direct_deps and root_module_direct_dev_deps must both be "
              + "specified or both be unspecified");
    }

    Sequence<String> rootModuleDirectDeps =
        Sequence.cast(rootModuleDirectDepsUnchecked, String.class, "root_module_direct_deps");
    Sequence<String> rootModuleDirectDevDeps =
        Sequence.cast(
            rootModuleDirectDevDepsUnchecked, String.class, "root_module_direct_dev_deps");

    Set<String> explicitRootModuleDirectDeps = new LinkedHashSet<>();
    for (String dep : rootModuleDirectDeps) {
      try {
        RepositoryName.validateUserProvidedRepoName(dep);
      } catch (EvalException e) {
        throw Starlark.errorf("in root_module_direct_deps: %s", e.getMessage());
      }
      if (!explicitRootModuleDirectDeps.add(dep)) {
        throw Starlark.errorf("in root_module_direct_deps: duplicate entry '%s'", dep);
      }
    }

    Set<String> explicitRootModuleDirectDevDeps = new LinkedHashSet<>();
    for (String dep : rootModuleDirectDevDeps) {
      try {
        RepositoryName.validateUserProvidedRepoName(dep);
      } catch (EvalException e) {
        throw Starlark.errorf("in root_module_direct_dev_deps: %s", e.getMessage());
      }
      if (explicitRootModuleDirectDeps.contains(dep)) {
        throw Starlark.errorf(
            "in root_module_direct_dev_deps: entry '%s' is also in " + "root_module_direct_deps",
            dep);
      }
      if (!explicitRootModuleDirectDevDeps.add(dep)) {
        throw Starlark.errorf("in root_module_direct_dev_deps: duplicate entry '%s'", dep);
      }
    }

    return new ModuleExtensionMetadata(
        explicitRootModuleDirectDeps, explicitRootModuleDirectDevDeps, UseAllRepos.NO);
  }

  public void evaluate(
      Collection<ModuleExtensionUsage> usages, Set<String> allRepos, EventHandler handler)
      throws EvalException {
    generateFixupMessage(usages, allRepos).ifPresent(handler::handle);
  }

  Optional<Event> generateFixupMessage(
      Collection<ModuleExtensionUsage> usages, Set<String> allRepos) throws EvalException {
    var rootUsages =
        usages.stream()
            .filter(usage -> usage.getUsingModule().equals(ModuleKey.ROOT))
            .collect(toImmutableList());
    if (rootUsages.isEmpty()) {
      // The root module doesn't use the current extension. Do not suggest fixes as the user isn't
      // expected to modify any other module's MODULE.bazel file.
      return Optional.empty();
    }

    var rootModuleDirectDevDeps = getRootModuleDirectDevDeps(allRepos);
    var rootModuleDirectDeps = getRootModuleDirectDeps(allRepos);
    if (rootModuleDirectDevDeps.isEmpty() && rootModuleDirectDeps.isEmpty()) {
      return Optional.empty();
    }

    Preconditions.checkState(
        rootModuleDirectDevDeps.isPresent() && rootModuleDirectDeps.isPresent());
    return generateFixupMessage(
        rootUsages, allRepos, rootModuleDirectDeps.get(), rootModuleDirectDevDeps.get());
  }

  private static Optional<Event> generateFixupMessage(
      List<ModuleExtensionUsage> rootUsages,
      Set<String> allRepos,
      Set<String> expectedImports,
      Set<String> expectedDevImports) {
    var actualDevImports =
        rootUsages.stream()
            .flatMap(usage -> usage.getDevImports().stream())
            .collect(toImmutableSet());
    var actualImports =
        rootUsages.stream()
            .flatMap(usage -> usage.getImports().values().stream())
            .filter(repo -> !actualDevImports.contains(repo))
            .collect(toImmutableSet());

    // All label strings that map to the same Label are equivalent for buildozer as it implements
    // the same normalization of label strings with no or empty repo name.
    ModuleExtensionUsage firstUsage = rootUsages.get(0);
    String extensionBzlFile = firstUsage.getExtensionBzlFile();
    String extensionName = firstUsage.getExtensionName();
    Location location = firstUsage.getLocation();

    var importsToAdd = ImmutableSortedSet.copyOf(Sets.difference(expectedImports, actualImports));
    var importsToRemove =
        ImmutableSortedSet.copyOf(Sets.difference(actualImports, expectedImports));
    var devImportsToAdd =
        ImmutableSortedSet.copyOf(Sets.difference(expectedDevImports, actualDevImports));
    var devImportsToRemove =
        ImmutableSortedSet.copyOf(Sets.difference(actualDevImports, expectedDevImports));

    if (importsToAdd.isEmpty()
        && importsToRemove.isEmpty()
        && devImportsToAdd.isEmpty()
        && devImportsToRemove.isEmpty()) {
      return Optional.empty();
    }

    var message =
        String.format(
            "The module extension %s defined in %s reported incorrect imports "
                + "of repositories via use_repo():\n\n",
            extensionName, extensionBzlFile);

    var allActualImports = ImmutableSortedSet.copyOf(Sets.union(actualImports, actualDevImports));
    var allExpectedImports =
        ImmutableSortedSet.copyOf(Sets.union(expectedImports, expectedDevImports));

    var invalidImports = ImmutableSortedSet.copyOf(Sets.difference(allActualImports, allRepos));
    if (!invalidImports.isEmpty()) {
      message +=
          String.format(
              "Imported, but not created by the extension (will cause the build to fail):\n"
                  + "    %s\n\n",
              String.join(", ", invalidImports));
    }

    var missingImports =
        ImmutableSortedSet.copyOf(Sets.difference(allExpectedImports, allActualImports));
    if (!missingImports.isEmpty()) {
      message +=
          String.format(
              "Not imported, but reported as direct dependencies by the extension (may cause the"
                  + " build to fail):\n"
                  + "    %s\n\n",
              String.join(", ", missingImports));
    }

    var indirectDepImports =
        ImmutableSortedSet.copyOf(
            Sets.difference(Sets.intersection(allActualImports, allRepos), allExpectedImports));
    if (!indirectDepImports.isEmpty()) {
      message +=
          String.format(
              "Imported, but reported as indirect dependencies by the extension:\n    %s\n\n",
              String.join(", ", indirectDepImports));
    }

    var fixupCommands =
        Stream.of(
                makeUseRepoCommand(
                    "use_repo_add", false, importsToAdd, extensionBzlFile, extensionName),
                makeUseRepoCommand(
                    "use_repo_remove", false, importsToRemove, extensionBzlFile, extensionName),
                makeUseRepoCommand(
                    "use_repo_add", true, devImportsToAdd, extensionBzlFile, extensionName),
                makeUseRepoCommand(
                    "use_repo_remove", true, devImportsToRemove, extensionBzlFile, extensionName))
            .flatMap(Optional::stream);

    return Optional.of(
        Event.warn(
            location,
            message
                + String.format(
                    "%s ** You can use the following buildozer command(s) to fix these"
                        + " issues:%s\n\n"
                        + "%s",
                    "\033[35m\033[1m",
                    "\033[0m",
                    fixupCommands.collect(Collectors.joining("\n")))));
  }

  private static Optional<String> makeUseRepoCommand(
      String cmd,
      boolean devDependency,
      Collection<String> repos,
      String extensionBzlFile,
      String extensionName) {
    if (repos.isEmpty()) {
      return Optional.empty();
    }
    return Optional.of(
        String.format(
            "buildozer '%s%s %s %s %s' //MODULE.bazel:all",
            cmd,
            devDependency ? " dev" : "",
            extensionBzlFile,
            extensionName,
            String.join(" ", repos)));
  }

  private Optional<ImmutableSet<String>> getRootModuleDirectDeps(Set<String> allRepos)
      throws EvalException {
    switch (useAllRepos) {
      case NO:
        if (explicitRootModuleDirectDeps != null) {
          Set<String> invalidRepos = Sets.difference(explicitRootModuleDirectDeps, allRepos);
          if (!invalidRepos.isEmpty()) {
            throw Starlark.errorf(
                "root_module_direct_deps contained the following repositories "
                    + "not generated by the extension: %s",
                String.join(", ", invalidRepos));
          }
        }
        return Optional.ofNullable(explicitRootModuleDirectDeps);
      case REGULAR:
        return Optional.of(ImmutableSet.copyOf(allRepos));
      case DEV:
        return Optional.of(ImmutableSet.of());
    }
    throw new IllegalStateException("not reached");
  }

  private Optional<ImmutableSet<String>> getRootModuleDirectDevDeps(Set<String> allRepos)
      throws EvalException {
    switch (useAllRepos) {
      case NO:
        if (explicitRootModuleDirectDevDeps != null) {
          Set<String> invalidRepos = Sets.difference(explicitRootModuleDirectDevDeps, allRepos);
          if (!invalidRepos.isEmpty()) {
            throw Starlark.errorf(
                "root_module_direct_dev_deps contained the following "
                    + "repositories not generated by the extension: %s",
                String.join(", ", invalidRepos));
          }
        }
        return Optional.ofNullable(explicitRootModuleDirectDevDeps);
      case REGULAR:
        return Optional.of(ImmutableSet.of());
      case DEV:
        return Optional.of(ImmutableSet.copyOf(allRepos));
    }
    throw new IllegalStateException("not reached");
  }

  private enum UseAllRepos {
    NO,
    REGULAR,
    DEV,
  }
}
