// Copyright 2024 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.actions;

import static com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap;

import com.google.common.base.Functions;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.server.FailureDetails.Analysis;
import com.google.devtools.build.lib.server.FailureDetails.Analysis.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.AbstractSaneAnalysisException;
import com.google.devtools.build.lib.util.DetailedExitCode;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/**
 * This exception is thrown when a conflict between actions is detected. It contains information
 * about the artifact for which the conflict is found, and data about the two conflicting actions
 * and their owners. Non-final only for {@link WithAspectKeyInfo}.
 */
public sealed class ActionConflictException extends AbstractSaneAnalysisException {
  private final Artifact artifact;
  private final ActionAnalysisMetadata attemptedAction;
  private final boolean isPrefixConflict;

  private static final int MAX_DIFF_ARTIFACTS_TO_REPORT = 5;

  public static ActionConflictException create(
      ActionKeyContext actionKeyContext,
      Artifact artifact,
      ActionAnalysisMetadata previousAction,
      ActionAnalysisMetadata attemptedAction) {
    return new ActionConflictException(
        artifact,
        attemptedAction,
        createDetailedMessage(artifact, actionKeyContext, attemptedAction, previousAction),
        /* isPrefixConflict= */ false);
  }

  /**
   * Exception to indicate that one {@link Action} has an output artifact whose path is a prefix of
   * an output of another action. Since the first path cannot be both a directory and a file, this
   * would lead to an error if both actions were executed in the same build.
   */
  public static ActionConflictException createPrefix(
      Artifact firstArtifact,
      Artifact secondArtifact,
      ActionAnalysisMetadata firstAction,
      ActionAnalysisMetadata secondAction) {
    return new ActionConflictException(
        firstArtifact,
        firstAction,
        createPrefixDetailedMessage(
            firstArtifact,
            secondArtifact,
            firstAction.getOwner().getLabel(),
            secondAction.getOwner().getLabel()),
        /* isPrefixConflict= */ true);
  }

  public static ActionConflictException withAspectKeyInfo(
      ActionConflictException e, ActionLookupKey aspectKey) {
    return new WithAspectKeyInfo(e, aspectKey);
  }

  private ActionConflictException(
      Artifact artifact,
      ActionAnalysisMetadata attemptedAction,
      String message,
      boolean isPrefixConflict) {
    super(message);
    this.artifact = artifact;
    this.attemptedAction = attemptedAction;
    this.isPrefixConflict = isPrefixConflict;
  }

  public Artifact getArtifact() {
    return artifact;
  }

  public ActionAnalysisMetadata getAttemptedAction() {
    return attemptedAction;
  }

  private static String createDetailedMessage(
      Artifact artifact,
      ActionKeyContext actionKeyContext,
      ActionAnalysisMetadata a,
      ActionAnalysisMetadata b) {
    return "file '"
        + artifact.prettyPrint()
        + "' is generated by these conflicting actions:\n"
        + debugSuffix(actionKeyContext, a, b);
  }

  private static String createPrefixDetailedMessage(
      Artifact firstArtifact, Artifact secondArtifact, Label firstOwner, Label secondOwner) {
    return String.format(
        "One of the output paths '%s' (belonging to %s) and '%s' (belonging to %s) is a"
            + " prefix of the other. These actions cannot be simultaneously present; please"
            + " rename one of the output files or build just one of them",
        firstArtifact.getExecPath(), firstOwner, secondArtifact.getExecPath(), secondOwner);
  }

  public void reportTo(EventHandler eventListener) {
    eventListener.handle(Event.error(this.getMessage()));
  }

  @Override
  public DetailedExitCode getDetailedExitCode() {
    return DetailedExitCode.of(
        FailureDetail.newBuilder()
            .setMessage(getMessage())
            .setAnalysis(
                Analysis.newBuilder()
                    .setCode(
                        isPrefixConflict ? Code.ARTIFACT_PREFIX_CONFLICT : Code.ACTION_CONFLICT))
            .build());
  }

  private static void addStringDetail(StringBuilder sb, String key, String valueA, String valueB) {
    valueA = valueA != null ? valueA : "(null)";
    valueB = valueB != null ? valueB : "(null)";

    sb.append(key).append(": ").append(valueA);
    if (!valueA.equals(valueB)) {
      sb.append(", ").append(valueB);
    }
    sb.append("\n");
  }

  private static void addListDetail(
      StringBuilder sb, String key, Iterable<Artifact> valueA, Iterable<Artifact> valueB) {
    Set<Artifact> diffA = differenceWithoutOwner(valueA, valueB);
    Set<Artifact> diffB = differenceWithoutOwner(valueB, valueA);

    sb.append(key).append(": ");
    if (diffA.isEmpty() && diffB.isEmpty()) {
      sb.append("are equal\n");
    } else {
      if (!diffA.isEmpty()) {
        sb.append(
            "Attempted action contains artifacts not in previous action (first "
                + MAX_DIFF_ARTIFACTS_TO_REPORT
                + "): \n");
        prettyPrintArtifactDiffs(sb, diffA);
      }

      if (!diffB.isEmpty()) {
        sb.append(
            "Previous action contains artifacts not in attempted action (first "
                + MAX_DIFF_ARTIFACTS_TO_REPORT
                + "): \n");
        prettyPrintArtifactDiffs(sb, diffB);
      }
    }
  }

  /** Returns items in {@code valueA} that are not in {@code valueB}, ignoring the owner. */
  private static Set<Artifact> differenceWithoutOwner(
      Iterable<Artifact> valueA, Iterable<Artifact> valueB) {
    ImmutableSet.Builder<Artifact> diff = new ImmutableSet.Builder<>();

    // Group valueB by exec path for easier checks.
    ImmutableListMultimap<String, Artifact> mapB =
        Streams.stream(valueB)
            .collect(toImmutableListMultimap(Artifact::getExecPathString, Functions.identity()));
    for (Artifact a : valueA) {
      boolean found = false;
      for (Artifact b : mapB.get(a.getExecPathString())) {
        if (a.equalsWithoutOwner(b)) {
          found = true;
          break;
        }
      }
      if (!found) {
        diff.add(a);
      }
    }

    return diff.build();
  }

  /** Pretty print action diffs (at most {@code MAX_DIFF_ARTIFACTS_TO_REPORT} lines). */
  private static void prettyPrintArtifactDiffs(StringBuilder sb, Set<Artifact> diff) {
    for (Artifact artifact : Iterables.limit(diff, MAX_DIFF_ARTIFACTS_TO_REPORT)) {
      sb.append('\t').append(artifact.prettyPrint()).append('\n');
    }
  }

  // See also Actions.canBeShared()
  private static String debugSuffix(
      ActionKeyContext actionKeyContext, ActionAnalysisMetadata a, ActionAnalysisMetadata b) {
    // Note: the error message reveals to users the names of intermediate files that are not
    // documented in the BUILD language.  This error-reporting logic is rather elaborate but it
    // does help to diagnose some tricky situations.
    StringBuilder sb = new StringBuilder();
    ActionOwner aOwner = a.getOwner();
    ActionOwner bOwner = b.getOwner();
    boolean aNull = aOwner == null;
    boolean bNull = bOwner == null;

    addStringDetail(
        sb,
        "Label",
        aNull ? null : Label.print(aOwner.getLabel()),
        bNull ? null : Label.print(bOwner.getLabel()));
    if ((!aNull && !aOwner.getAspectDescriptors().isEmpty())
        || (!bNull && !bOwner.getAspectDescriptors().isEmpty())) {
      addStringDetail(sb, "Aspects", aspectDescriptor(aOwner), aspectDescriptor(bOwner));
    }
    addStringDetail(
        sb,
        "RuleClass",
        aNull ? null : aOwner.getTargetKind(),
        bNull ? null : bOwner.getTargetKind());
    addStringDetail(
        sb,
        "JavaActionClass",
        aNull ? null : a.getClass().toString(),
        bNull ? null : b.getClass().toString());
    addStringDetail(
        sb,
        "Configuration",
        aNull ? null : aOwner.getConfigurationChecksum(),
        bNull ? null : bOwner.getConfigurationChecksum());
    addStringDetail(sb, "Mnemonic", a.getMnemonic(), b.getMnemonic());
    try {
      addStringDetail(
          sb,
          "Action key",
          a.getKey(actionKeyContext, /* artifactExpander= */ null),
          b.getKey(actionKeyContext, /* artifactExpander= */ null));
    } catch (InterruptedException e) {
      // Only for debugging - skip the key and carry on.
      addStringDetail(sb, "Action key", "<elided due to interrupt>", "<elided due to interrupt>");
      Thread.currentThread().interrupt();
    }

    if ((a instanceof ActionExecutionMetadata) && (b instanceof ActionExecutionMetadata)) {
      addStringDetail(
          sb,
          "Progress message",
          ((ActionExecutionMetadata) a).getProgressMessage(),
          ((ActionExecutionMetadata) b).getProgressMessage());
      addStringDetail(
          sb,
          "Action describeKey",
          ((ActionExecutionMetadata) a).describeKey(),
          ((ActionExecutionMetadata) b).describeKey());
    }

    Artifact aPrimaryInput = a.getPrimaryInput();
    Artifact bPrimaryInput = b.getPrimaryInput();
    addStringDetail(
        sb,
        "PrimaryInput",
        aPrimaryInput == null ? null : aPrimaryInput.toString(),
        bPrimaryInput == null ? null : bPrimaryInput.toString());
    addStringDetail(
        sb, "PrimaryOutput", a.getPrimaryOutput().toString(), b.getPrimaryOutput().toString());

    // Only add list details if the primary input of A matches the input of B. Otherwise
    // the above information is enough and list diff detail is not needed.
    if ((aPrimaryInput == null && bPrimaryInput == null)
        || (aPrimaryInput != null
            && bPrimaryInput != null
            && aPrimaryInput.toString().equals(bPrimaryInput.toString()))) {
      Artifact aPrimaryOutput = a.getPrimaryOutput();
      Artifact bPrimaryOutput = b.getPrimaryOutput();
      if (!aPrimaryOutput.equalsWithoutOwner(bPrimaryOutput)) {
        sb.append("Primary outputs are different: ")
            .append(System.identityHashCode(aPrimaryOutput))
            .append(", ")
            .append(System.identityHashCode(bPrimaryOutput))
            .append('\n');
      }
      ArtifactOwner aArtifactOwner = aPrimaryOutput.getArtifactOwner();
      ArtifactOwner bArtifactOwner = bPrimaryOutput.getArtifactOwner();
      addStringDetail(
          sb, "Owner information", aArtifactOwner.toString(), bArtifactOwner.toString());
      addListDetail(
          sb, "MandatoryInputs", a.getMandatoryInputs().toList(), b.getMandatoryInputs().toList());
      addListDetail(sb, "Outputs", a.getOutputs(), b.getOutputs());
    }

    return sb.toString();
  }

  @Nullable
  private static String aspectDescriptor(ActionOwner owner) {
    return owner == null
        ? null
        : owner.getAspectDescriptors().stream()
            .map(AspectDescriptor::getDescription)
            .collect(Collectors.joining(",", "[", "]"));
  }

  @Nullable
  public ActionLookupKey getAspectKey() {
    return null;
  }

  /**
   * For skymeld.
   *
   * <p>We need to forward the AspectKey along so that it's available for the final conflict report.
   */
  private static final class WithAspectKeyInfo extends ActionConflictException {
    private final ActionLookupKey aspectKey;

    private WithAspectKeyInfo(ActionConflictException e, ActionLookupKey aspectKey) {
      super(e.artifact, e.attemptedAction, e.getMessage(), e.isPrefixConflict);
      this.aspectKey = aspectKey;
    }

    @Override
    public ActionLookupKey getAspectKey() {
      return aspectKey;
    }
  }
}
