<?php

declare(strict_types=1);

namespace Drupal\flowdrop_interrupt\Service;

use Drupal\flowdrop_orchestration\Exception\InterruptExceptionInterface;
use Drupal\flowdrop_job\FlowDropJobInterface;
use Drupal\flowdrop_pipeline\Entity\FlowDropPipelineInterface;
use Drupal\flowdrop_interrupt\DTO\InterruptState;

/**
 * Interface for interrupt state persistence.
 *
 * This interface abstracts the persistence of interrupt state, ensuring that
 * interrupt data is always stored persistently (even when the orchestrator
 * uses in-memory storage) so that execution can be resumed later.
 *
 * Key design decision: Interrupt state is ALWAYS persisted to durable storage
 * regardless of the orchestrator's primary storage backend. This ensures that
 * workflows can be resumed after an interrupt even when using InMemoryStorage.
 *
 * @api
 */
interface InterruptPersistenceInterface {

  /**
   * Persists the interrupt state for later resumption.
   *
   * This method is called when an InterruptException is thrown during
   * workflow execution. It saves all necessary state to allow the workflow
   * to be resumed when the interrupt is resolved.
   *
   * @param \Drupal\flowdrop_pipeline\Entity\FlowDropPipelineInterface $pipeline
   *   The pipeline being executed.
   * @param \Drupal\flowdrop_job\FlowDropJobInterface $job
   *   The job that was interrupted.
   * @param \Drupal\flowdrop_orchestration\Exception\InterruptExceptionInterface $exception
   *   The interrupt exception containing interrupt details.
   * @param string $executionId
   *   The execution ID for the current workflow run.
   * @param array $partialResults
   *   Partial results collected before the interrupt.
   */
  public function persistInterruptState(
    FlowDropPipelineInterface $pipeline,
    FlowDropJobInterface $job,
    InterruptExceptionInterface $exception,
    string $executionId,
    array $partialResults = [],
  ): void;

  /**
   * Loads the interrupt state for resumption.
   *
   * @param string $interruptId
   *   The interrupt ID.
   *
   * @return \Drupal\flowdrop_interrupt\DTO\InterruptState|null
   *   The interrupt state, or NULL if not found.
   */
  public function loadInterruptState(string $interruptId): ?InterruptState;

  /**
   * Marks an interrupt as resolved.
   *
   * Called when the interrupt has been handled and the workflow can continue.
   *
   * @param string $interruptId
   *   The interrupt ID.
   * @param array $userInput
   *   The user input that resolves the interrupt.
   */
  public function resolveInterrupt(string $interruptId, array $userInput): void;

  /**
   * Checks if an interrupt exists and is pending resolution.
   *
   * @param string $interruptId
   *   The interrupt ID.
   *
   * @return bool
   *   TRUE if the interrupt exists and is pending.
   */
  public function isInterruptPending(string $interruptId): bool;

  /**
   * Deletes interrupt state after successful resumption.
   *
   * @param string $interruptId
   *   The interrupt ID.
   */
  public function deleteInterruptState(string $interruptId): void;

}
