// Copyright (C) 2025 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.server.restapi.flow;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Objects.requireNonNull;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.FlowActionInfo;
import com.google.gerrit.extensions.common.FlowExpressionInfo;
import com.google.gerrit.extensions.common.FlowInfo;
import com.google.gerrit.extensions.common.FlowInput;
import com.google.gerrit.extensions.common.FlowStageInfo;
import com.google.gerrit.extensions.common.FlowStageState;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.server.flow.Flow;
import com.google.gerrit.server.flow.FlowAction;
import com.google.gerrit.server.flow.FlowCreation;
import com.google.gerrit.server.flow.FlowExpression;
import com.google.gerrit.server.flow.FlowStage;
import com.google.gerrit.server.flow.FlowStageEvaluationStatus;

/**
 * Produces flow-related entities, like {@link FlowInfo}s, which are serialized to JSON afterwards.
 */
public class FlowJson {
  /** Formats the given {@link Flow} instance as a {@link FlowInfo}. */
  public static FlowInfo format(Flow flow) {
    requireNonNull(flow, "flow");

    FlowInfo flowInfo = new FlowInfo();
    flowInfo.uuid = flow.key().uuid();
    flowInfo.owner = new AccountInfo(flow.ownerId().get());
    flowInfo.setCreated(flow.createdOn());
    flowInfo.stages = flow.stages().stream().map(FlowJson::format).collect(toImmutableList());

    if (flow.lastEvaluatedOn().isPresent()) {
      flowInfo.setLastEvaluated(flow.lastEvaluatedOn().get());
    }

    return flowInfo;
  }

  /** Formats the given {@link FlowStage} instance as a {@link FlowStageInfo}. */
  private static FlowStageInfo format(FlowStage flowStage) {
    requireNonNull(flowStage, "flowStage");

    FlowStageInfo flowStageInfo = new FlowStageInfo();
    flowStageInfo.expression = format(flowStage.expression());
    flowStageInfo.state = mapState(flowStage.status().state());
    flowStageInfo.message = flowStage.status().message().orElse(null);
    return flowStageInfo;
  }

  /** Formats the given {@link FlowExpression} instance as a {@link FlowExpressionInfo}. */
  private static FlowExpressionInfo format(FlowExpression flowExpression) {
    requireNonNull(flowExpression, "flowExpression");

    FlowExpressionInfo flowExpressionInfo = new FlowExpressionInfo();
    flowExpressionInfo.condition = flowExpression.condition();
    if (flowExpression.action().isPresent()) {
      flowExpressionInfo.action = format(flowExpression.action().get());
    }
    return flowExpressionInfo;
  }

  /** Formats the given {@link FlowAction} instance as a {@link FlowActionInfo}. */
  private static FlowActionInfo format(FlowAction flowAction) {
    requireNonNull(flowAction, "flowAction");

    FlowActionInfo flowActionInfo = new FlowActionInfo();
    flowActionInfo.name = flowAction.name();
    flowActionInfo.parameters = flowAction.parameters();
    return flowActionInfo;
  }

  /**
   * Maps the given {@link com.google.gerrit.server.flow.FlowStageEvaluationStatus.State} to a
   * {@link FlowStageState}.
   */
  @VisibleForTesting
  public static FlowStageState mapState(FlowStageEvaluationStatus.State flowStageState) {
    requireNonNull(flowStageState, "flowStageState");

    return switch (flowStageState) {
      case UNKNOWN ->
          throw new IllegalStateException("The flow stage state has not been initialized");
      case DONE -> FlowStageState.DONE;
      case PENDING -> FlowStageState.PENDING;
      case FAILED -> FlowStageState.FAILED;
      case TERMINATED -> FlowStageState.TERMINATED;
    };
  }

  /**
   * Create a {@link FlowCreation} from the given {@link FlowInput}.
   *
   * @throws BadRequestException thrown if mandatory properties are missing
   */
  public static FlowCreation createFlowCreation(
      Project.NameKey projectName, Change.Id changeId, Account.Id ownerId, FlowInput flowInput)
      throws BadRequestException {
    requireNonNull(projectName, "projectName");
    requireNonNull(changeId, "changeId");
    requireNonNull(ownerId, "ownerId");
    requireNonNull(flowInput, "flowInput");

    if (flowInput.stageExpressions == null || flowInput.stageExpressions.isEmpty()) {
      throw new BadRequestException("at least one stage expression is required");
    }

    if (Iterables.getLast(flowInput.stageExpressions).action == null) {
      throw new BadRequestException("the last stage expression is required to have an action");
    }

    FlowCreation.Builder flowCreationBuilder =
        FlowCreation.builder().projectName(projectName).changeId(changeId).ownerId(ownerId);

    for (FlowExpressionInfo flowExpressionInfo : flowInput.stageExpressions) {
      flowCreationBuilder.addStageExpression(createFlowExpression(flowExpressionInfo));
    }

    return flowCreationBuilder.build();
  }

  /**
   * Create a {@link FlowExpression} from the given {@link FlowExpressionInfo}.
   *
   * @throws BadRequestException thrown if mandatory properties are missing
   */
  public static FlowExpression createFlowExpression(FlowExpressionInfo flowExpressionInfo)
      throws BadRequestException {
    requireNonNull(flowExpressionInfo, "flowExpressionInfo");

    if (Strings.isNullOrEmpty(flowExpressionInfo.condition)) {
      throw new BadRequestException("condition in stage expression is required");
    }
    var builder = FlowExpression.builder().condition(flowExpressionInfo.condition);
    if (flowExpressionInfo.action != null) {
      builder.action(createFlowAction(flowExpressionInfo.action));
    }

    return builder.build();
  }

  /**
   * Create a {@link FlowAction} from the given {@link FlowActionInfo}.
   *
   * @throws BadRequestException thrown if mandatory properties are missing
   */
  public static FlowAction createFlowAction(FlowActionInfo flowActionInfo)
      throws BadRequestException {
    requireNonNull(flowActionInfo, "flowActionInfo");

    if (Strings.isNullOrEmpty(flowActionInfo.name)) {
      throw new BadRequestException("name in action is required");
    }

    FlowAction.Builder flowActionBuilder = FlowAction.builder().name(flowActionInfo.name);

    if (flowActionInfo.parameters != null) {
      flowActionBuilder.parameters(ImmutableList.copyOf(flowActionInfo.parameters));
    }

    return flowActionBuilder.build();
  }

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