// Copyright (C) 2024 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.acceptance;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.DIRECT_PUSH;
import static java.util.Objects.requireNonNull;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.PluginPushOption;
import com.google.gerrit.server.ValidationOptionsListener;
import com.google.gerrit.server.change.EmailReviewComments;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.flow.Flow;
import com.google.gerrit.server.flow.FlowCreation;
import com.google.gerrit.server.flow.FlowExpression;
import com.google.gerrit.server.flow.FlowKey;
import com.google.gerrit.server.flow.FlowPermissionDeniedException;
import com.google.gerrit.server.flow.FlowService;
import com.google.gerrit.server.flow.FlowStage;
import com.google.gerrit.server.flow.FlowStageEvaluationStatus;
import com.google.gerrit.server.flow.InvalidFlowException;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationInfo;
import com.google.gerrit.server.git.validators.CommitValidationInfoListener;
import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.rules.SubmitRule;
import com.google.gerrit.server.update.RetryListener;
import com.google.gerrit.server.update.context.RefUpdateContext;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Class to host common test extension implementations.
 *
 * <p>To test the invocation of an extension point tests usually register a test implementation for
 * the extension that records the parameters with which it has been called.
 *
 * <p>If the same extension point is triggered by different actions, these test extension
 * implementations may be needed in different test classes. To avoid duplicating them in the test
 * classes, they can be added to this class and then be reused from the different tests.
 */
public class TestExtensions {
  public static class TestCommitValidationListener implements CommitValidationListener {
    public CommitReceivedEvent receiveEvent;

    @Override
    public List<CommitValidationMessage> onCommitReceived(CommitReceivedEvent receiveEvent)
        throws CommitValidationException {
      this.receiveEvent = receiveEvent;
      return ImmutableList.of();
    }
  }

  public static class TestValidationOptionsListener implements ValidationOptionsListener {
    public ImmutableListMultimap<String, String> validationOptions;

    @Override
    public void onPatchSetCreation(
        BranchNameKey projectAndBranch,
        PatchSet.Id patchSetId,
        ImmutableListMultimap<String, String> validationOptions) {
      this.validationOptions = validationOptions;
    }
  }

  public static class TestCommitValidationInfoListener implements CommitValidationInfoListener {
    public ImmutableMap<String, CommitValidationInfo> validationInfoByValidator;
    public CommitReceivedEvent receiveEvent;
    @Nullable public PatchSet.Id patchSetId;
    public boolean hasChangeModificationRefContext;
    public boolean hasDirectPushRefContext;

    @Override
    public void commitValidated(
        ImmutableMap<String, CommitValidationInfo> validationInfoByValidator,
        CommitReceivedEvent receiveEvent,
        PatchSet.Id patchSetId) {
      this.validationInfoByValidator = validationInfoByValidator;
      this.receiveEvent = receiveEvent;
      this.patchSetId = patchSetId;
      this.hasChangeModificationRefContext = RefUpdateContext.hasOpen(CHANGE_MODIFICATION);
      this.hasDirectPushRefContext = RefUpdateContext.hasOpen(DIRECT_PUSH);
    }
  }

  public static class TestPluginPushOption implements PluginPushOption {
    private final String name;
    private final String description;
    private final Boolean enabled;

    public TestPluginPushOption(String name, String description, Boolean enabled) {
      this.name = name;
      this.description = description;
      this.enabled = enabled;
    }

    @Override
    public String getName() {
      return name;
    }

    @Override
    public String getDescription() {
      return description;
    }

    @Override
    public boolean isOptionEnabled(ChangeNotes changeNotes) {
      return enabled;
    }

    @Override
    public boolean isOptionEnabled(Project.NameKey project, BranchNameKey branch) {
      return enabled;
    }
  }

  public static class TestRetryListener implements RetryListener {
    private List<Retry> retries = new ArrayList<>();

    @Override
    public void onRetry(String actionType, String actionName, long nextAttempt, Throwable cause) {
      this.retries.add(new Retry(actionType, actionName, nextAttempt, cause));
    }

    public ImmutableList<Retry> getRetries() {
      return ImmutableList.copyOf(retries);
    }

    public Retry getOnlyRetry() {
      return Iterables.getOnlyElement(retries);
    }

    public record Retry(String actionType, String actionName, long nextAttempt, Throwable cause) {
      public Retry {
        requireNonNull(actionType, "actionType");
        requireNonNull(actionName, "actionName");
        requireNonNull(cause, "cause");
      }
    }
  }

  /** Test implementation of a {@link FlowService} to be used by the flow integration tests. */
  public static class TestFlowService implements FlowService {
    public static final String INVALID_CONDITION = "invalid";

    private final Map<FlowKey, Flow> flows = new HashMap<>();

    /**
     * Whether any flow creation should be rejected with a {@link FlowPermissionDeniedException}.
     */
    private boolean rejectFlowCreation;

    /**
     * Whether any flow deletion should be rejected with a {@link FlowPermissionDeniedException}.
     */
    private boolean rejectFlowDeletion;

    /** Makes the flow service reject all flow creations. */
    public void rejectFlowCreation() {
      this.rejectFlowCreation = true;
    }

    /** Makes the flow service reject all flow deletions. */
    public void rejectFlowDeletion() {
      this.rejectFlowDeletion = true;
    }

    @Override
    public Flow createFlow(FlowCreation flowCreation)
        throws FlowPermissionDeniedException, InvalidFlowException, StorageException {
      if (rejectFlowCreation) {
        throw new FlowPermissionDeniedException("not allowed to create flow");
      }

      if (flowCreation.stageExpressions().stream()
          .map(FlowExpression::condition)
          .anyMatch(condition -> condition.endsWith(INVALID_CONDITION))) {
        throw new InvalidFlowException(String.format("invalid condition: %s", INVALID_CONDITION));
      }

      FlowKey flowKey =
          FlowKey.builder()
              .projectName(flowCreation.projectName())
              .changeId(flowCreation.changeId())
              .uuid(ChangeUtil.messageUuid())
              .build();
      Flow flow =
          Flow.builder(flowKey)
              .createdOn(Instant.now())
              .ownerId(flowCreation.ownerId())
              .stages(
                  flowCreation.stageExpressions().stream()
                      .map(
                          stageExpression ->
                              FlowStage.builder().expression(stageExpression).build())
                      .collect(toImmutableList()))
              .build();
      flows.put(flowKey, flow);
      return flow;
    }

    @Override
    public Boolean isFlowsEnabled(Project.NameKey projectName, Change.Id changeId)
        throws RestApiException {
      // Always return true for testing purposes.
      return true;
    }

    @Override
    public Optional<Flow> getFlow(FlowKey flowKey) throws StorageException {
      return Optional.ofNullable(flows.get(flowKey));
    }

    @Override
    public Optional<Flow> deleteFlow(FlowKey flowKey)
        throws FlowPermissionDeniedException, StorageException {
      if (rejectFlowDeletion) {
        throw new FlowPermissionDeniedException("not allowed to delete flow");
      }

      return Optional.ofNullable(flows.remove(flowKey));
    }

    @Override
    public ImmutableList<Flow> listFlows(Project.NameKey projectName, Change.Id changeId)
        throws StorageException {
      return flows.entrySet().stream()
          .filter(
              e ->
                  e.getKey().projectName().equals(projectName)
                      && e.getKey().changeId().equals(changeId))
          .map(Map.Entry::getValue)
          .collect(toImmutableList());
    }

    /**
     * Updates the specified flow.
     *
     * <p>Sets the {@code lastEvaluatedOn} timestamp in the flow and updates the statuses of the
     * stages.
     *
     * @param flowKey the key of the flow that should be updated
     * @param stageStates states to be set for the stages
     * @param stageMessages messages to be set for the stages
     * @throws IllegalStateException thrown if the specified flow is not found, or if the number of
     *     given states/messages doesn't match with the number of stages in the flow
     * @return the updated flow
     */
    public Flow evaluate(
        FlowKey flowKey,
        ImmutableList<FlowStageEvaluationStatus.State> stageStates,
        ImmutableList<Optional<String>> stageMessages)
        throws IllegalStateException {
      Optional<Flow> flow = getFlow(flowKey);
      if (flow.isEmpty()) {
        throw new IllegalStateException(String.format("Flow %s not found.", flowKey));
      }
      if (stageStates.size() != flow.get().stages().size()) {
        throw new IllegalStateException(
            String.format(
                "Invalid number of stage states: got %s, expected %s",
                stageStates.size(), flow.get().stages().size()));
      }
      if (stageMessages.size() != flow.get().stages().size()) {
        throw new IllegalStateException(
            String.format(
                "Invalid number of stage messages: got %s, expected %s",
                stageMessages.size(), flow.get().stages().size()));
      }

      List<FlowStage> stages = new ArrayList<>(flow.get().stages());
      for (int i = 0; i < flow.get().stages().size(); i++) {
        FlowStageEvaluationStatus.Builder updatedStatus =
            stages.get(i).status().toBuilder().state(stageStates.get(i));
        if (stageMessages.get(i).isPresent()) {
          updatedStatus.message(stageMessages.get(i).get());
        }
        FlowStage updatedStage = stages.get(i).toBuilder().status(updatedStatus.build()).build();
        stages.set(i, updatedStage);
      }

      Flow updatedFlow =
          flow.get().toBuilder()
              .lastEvaluatedOn(Instant.now())
              .stages(ImmutableList.copyOf(stages))
              .build();
      flows.put(flowKey, updatedFlow);
      return updatedFlow;
    }
  }

  /**
   * Test submit rule that counts how often it is invoked.
   *
   * <p>Using this submit rule tests can verify that submit rules are not unexpectedly invoked.
   * Checking this is important since executing submit rules is rather expensive.
   */
  public static class TestSubmitRule implements SubmitRule {
    private int count;

    public int count() {
      return count;
    }

    @Override
    public Optional<SubmitRecord> evaluate(ChangeData changeData) {
      if (!isAsyncCallForSendingReviewCommentsEmail()) {
        count++;
      }
      return Optional.empty();
    }

    private boolean isAsyncCallForSendingReviewCommentsEmail() {
      return Arrays.stream(Thread.currentThread().getStackTrace())
          .map(StackTraceElement::getClassName)
          .anyMatch(className -> EmailReviewComments.class.getName().equals(className));
    }
  }

  /**
   * Private constructor to prevent instantiation of this class.
   *
   * <p>This class contains only static classes and hence never needs to be instantiated.
   */
  private TestExtensions() {}
}
