<?php

declare(strict_types=1);

namespace Drupal\flowdrop_stategraph\Service;

use Drupal\flowdrop_stategraph\DTO\Checkpoint;
use Drupal\flowdrop_stategraph\DTO\GraphState;
use Drupal\flowdrop_stategraph\DTO\StateUpdate;
use Drupal\flowdrop_stategraph\Reducer\ReducerInterface;

/**
 * Interface for the state lifecycle management service.
 *
 * @api
 */
interface StateManagerInterface {

  /**
   * Creates a new initial state.
   *
   * @param string|null $threadId
   *   Optional thread ID for conversation continuity.
   * @param array<string, mixed> $initialData
   *   Optional initial data to populate the state.
   *
   * @return \Drupal\flowdrop_stategraph\DTO\GraphState
   *   A new GraphState instance.
   */
  public function createInitialState(
    ?string $threadId = NULL,
    array $initialData = [],
  ): GraphState;

  /**
   * Applies a state update to the current state.
   *
   * @param \Drupal\flowdrop_stategraph\DTO\GraphState $currentState
   *   The current state.
   * @param \Drupal\flowdrop_stategraph\DTO\StateUpdate $update
   *   The update to apply.
   * @param int|null $maxIterations
   *   Optional max iterations override (uses config default if NULL).
   *
   * @return \Drupal\flowdrop_stategraph\DTO\GraphState
   *   A new GraphState with the update applied.
   *
   * @throws \Drupal\flowdrop_stategraph\Exception\MaxIterationsException
   *   When iteration limit is exceeded.
   */
  public function applyUpdate(
    GraphState $currentState,
    StateUpdate $update,
    ?int $maxIterations = NULL,
  ): GraphState;

  /**
   * Increments the iteration count on the state.
   *
   * @param \Drupal\flowdrop_stategraph\DTO\GraphState $state
   *   The current state.
   * @param int|null $maxIterations
   *   Optional max iterations override.
   *
   * @return \Drupal\flowdrop_stategraph\DTO\GraphState
   *   A new state with incremented iteration count.
   *
   * @throws \Drupal\flowdrop_stategraph\Exception\MaxIterationsException
   *   When iteration limit is exceeded.
   */
  public function incrementIteration(
    GraphState $state,
    ?int $maxIterations = NULL,
  ): GraphState;

  /**
   * Creates a checkpoint from the current state.
   *
   * @param \Drupal\flowdrop_stategraph\DTO\GraphState $state
   *   The current state.
   * @param string $nodeId
   *   The current node ID.
   * @param string|null $parentCheckpointId
   *   Optional parent checkpoint ID.
   *
   * @return \Drupal\flowdrop_stategraph\DTO\Checkpoint
   *   A new Checkpoint instance.
   */
  public function createCheckpoint(
    GraphState $state,
    string $nodeId,
    ?string $parentCheckpointId = NULL,
  ): Checkpoint;

  /**
   * Restores state from a checkpoint.
   *
   * @param \Drupal\flowdrop_stategraph\DTO\Checkpoint $checkpoint
   *   The checkpoint to restore from.
   *
   * @return \Drupal\flowdrop_stategraph\DTO\GraphState
   *   The restored GraphState.
   */
  public function restoreFromCheckpoint(Checkpoint $checkpoint): GraphState;

  /**
   * Marks the state as complete.
   *
   * @param \Drupal\flowdrop_stategraph\DTO\GraphState $state
   *   The current state.
   *
   * @return \Drupal\flowdrop_stategraph\DTO\GraphState
   *   A new state marked as complete.
   */
  public function markComplete(GraphState $state): GraphState;

  /**
   * Marks the state with an error.
   *
   * @param \Drupal\flowdrop_stategraph\DTO\GraphState $state
   *   The current state.
   * @param string $errorMessage
   *   The error message.
   *
   * @return \Drupal\flowdrop_stategraph\DTO\GraphState
   *   A new state with the error set.
   */
  public function markError(GraphState $state, string $errorMessage): GraphState;

  /**
   * Validates that state contains required fields.
   *
   * @param \Drupal\flowdrop_stategraph\DTO\GraphState $state
   *   The state to validate.
   *
   * @throws \Drupal\flowdrop_stategraph\Exception\StateValidationException
   *   When validation fails.
   */
  public function validateState(GraphState $state): void;

  /**
   * Gets a reducer by ID.
   *
   * @param string $reducerId
   *   The reducer ID.
   *
   * @return \Drupal\flowdrop_stategraph\Reducer\ReducerInterface
   *   The reducer instance.
   *
   * @throws \InvalidArgumentException
   *   When reducer is not found.
   */
  public function getReducer(string $reducerId): ReducerInterface;

  /**
   * Gets all available reducers.
   *
   * @return array<string, \Drupal\flowdrop_stategraph\Reducer\ReducerInterface>
   *   Map of reducer ID to instance.
   */
  public function getReducers(): array;

  /**
   * Gets the configured max iterations limit.
   *
   * @return int
   *   The maximum iterations.
   */
  public function getMaxIterations(): int;

  /**
   * Extracts state field metadata using reflection.
   *
   * @param \Drupal\flowdrop_stategraph\DTO\GraphState $state
   *   The state instance to inspect.
   *
   * @return array<string, array{reducer: string, description: string, required: bool}>
   *   Array of field metadata keyed by property name.
   */
  public function getStateFieldMetadata(GraphState $state): array;

}
