<?php

declare(strict_types=1);

namespace Drupal\flowdrop_interrupt\Exception;

use Drupal\flowdrop_interrupt\Entity\FlowDropInterruptInterface;
use Drupal\flowdrop_orchestration\Exception\FlowDropInterruptException;

/**
 * Exception thrown when a workflow node requires user input.
 *
 * This exception is thrown by interrupt node processors to pause workflow
 * execution and wait for user input. The orchestrator catches this exception
 * and returns an "interrupted" status with the interrupt details.
 *
 * Example usage:
 * @code
 * $interrupt = $interruptManager->createInterrupt(
 *   InterruptType::Confirmation,
 *   $workflowId,
 *   $nodeId,
 *   "Do you want to continue?",
 * );
 * throw new InterruptRequiredException($interrupt);
 * @endcode
 *
 * @internal This class is not part of the public API and may change without notice.
 */
class InterruptRequiredException extends FlowDropInterruptException {

  /**
   * Constructs a new InterruptRequiredException.
   *
   * @param \Drupal\flowdrop_interrupt\Entity\FlowDropInterruptInterface $interrupt
   *   The interrupt entity that was created.
   * @param array<string, mixed> $executionContext
   *   Additional execution context for resuming the workflow.
   * @param string $message
   *   The exception message.
   */
  public function __construct(
    public readonly FlowDropInterruptInterface $interrupt,
    public readonly array $executionContext = [],
    string $message = "Workflow interrupted for user input",
  ) {
    parent::__construct($message);
  }

  /**
   * Gets the interrupt entity.
   *
   * @return \Drupal\flowdrop_interrupt\Entity\FlowDropInterruptInterface
   *   The interrupt entity.
   */
  public function getInterrupt(): FlowDropInterruptInterface {
    return $this->interrupt;
  }

  /**
   * Gets the interrupt UUID.
   *
   * @return string
   *   The interrupt UUID.
   */
  public function getInterruptId(): string {
    return $this->interrupt->uuid() ?? "";
  }

  /**
   * Gets the interrupt type.
   *
   * @return string
   *   The interrupt type value.
   */
  public function getInterruptType(): string {
    return $this->interrupt->getType()->value;
  }

  /**
   * Gets the execution context.
   *
   * @return array<string, mixed>
   *   The execution context.
   */
  public function getExecutionContext(): array {
    return $this->executionContext;
  }

  /**
   * Converts the exception to an array for API responses.
   *
   * @return array<string, mixed>
   *   The exception data as an array.
   */
  public function toArray(): array {
    return [
      "interrupt" => $this->interrupt->toApiArray(),
      "context" => $this->executionContext,
    ];
  }

}
