<?php

declare(strict_types=1);

namespace Drupal\flowdrop\Plugin\FlowDropNodeProcessor;

use Drupal\flowdrop\DTO\ParameterBagInterface;
use Drupal\flowdrop_orchestration\DTO\ResolvedInterruptInterface;

/**
 * Opt-in contract for node processors that can resume from an interrupt.
 *
 * A node that throws an InterruptRequiredException pauses execution until
 * the interrupt resolves. When the orchestrator re-executes the job after
 * resolution it invokes {@see self::resume()} instead of `process()` for
 * processors that implement this interface.
 *
 * **Why a separate method:** the boilerplate "check `__interrupt_id__`,
 * load entity, branch on status" pattern that every interrupt-aware node
 * has to repeat in `process()` is collapsed into a single typed hook. The
 * orchestrator does the loading and dispatch; the node receives the
 * resolved interrupt and produces its outputs.
 *
 * **Why opt-in:** the vast majority of node processors never interrupt.
 * Forcing every node to declare a no-op `resume()` would be noise. Only
 * nodes that throw `InterruptRequiredException` need this interface.
 *
 * The runtime calls `resume()` ONLY when:
 *  - The job's metadata.interrupt_id is set (this is a resume invocation), AND
 *  - The pointed-to interrupt is in the resolved state.
 *
 * If the interrupt is still pending (race condition: job re-enqueued before
 * resolution arrived) the runtime keeps the job interrupted without calling
 * the node. Nodes therefore never need to defensively re-throw an interrupt
 * exception inside `resume()`.
 *
 * @api
 */
interface ResumableNodeProcessorInterface {

  /**
   * Resumes execution with the resolved interrupt.
   *
   * @param \Drupal\flowdrop_orchestration\DTO\ResolvedInterruptInterface $interrupt
   *   The resolved interrupt. Implementations should read response data via
   *   `getResponseData()`. Nodes that need richer access (schema, options,
   *   context) can downcast to the concrete entity type — at the cost of
   *   a hard dependency on flowdrop_interrupt.
   * @param \Drupal\flowdrop\DTO\ParameterBagInterface $params
   *   The same parameter bag the node would have received on initial
   *   `process()`. Upstream params are rebuilt from completed jobs by the
   *   orchestrator — they are NOT cached from the pre-interrupt run.
   *
   * @return array<string, mixed>
   *   The node's output, same shape as `process()` returns.
   */
  public function resume(
    ResolvedInterruptInterface $interrupt,
    ParameterBagInterface $params,
  ): array;

}
