<?php

declare(strict_types=1);

namespace Drupal\flowdrop_stategraph\Plugin\Orchestrator;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\flowdrop_orchestration\Attribute\Orchestrator;
use Drupal\flowdrop_orchestration\DTO\Orchestrator\OrchestrationRequest;
use Drupal\flowdrop_orchestration\DTO\Orchestrator\OrchestrationResponse;
use Drupal\flowdrop_orchestration\Plugin\Orchestrator\OrchestratorPluginBase;
use Drupal\flowdrop_runtime\Service\Orchestrator\PipelineExecutorAwareInterface;
use Drupal\flowdrop_runtime\Service\Orchestrator\PipelineExecutorInterface;
use Drupal\flowdrop_stategraph\Service\StateGraphOrchestrator;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * StateGraph orchestrator plugin - stateful graph execution with checkpointing.
 *
 * This orchestrator provides:
 * - Typed state with reducer-based updates.
 * - Checkpointing for durable execution.
 * - Conditional edge routing for loops.
 * - Iteration limits for safety.
 * - Thread-based conversation continuity.
 *
 * This plugin delegates to the StateGraphOrchestrator service which is
 * configured with all required dependencies including the WorkflowStateManager
 * for snapshot generation.
 *
 * @internal This class is not part of the public API and may change without notice.
 */
#[Orchestrator(
  id: "stategraph",
  label: new TranslatableMarkup("StateGraph Orchestrator"),
  description: "Stateful graph execution with checkpointing, reducers, and human-in-the-loop support",
  capabilities: [
    "synchronous_execution",
    "retry_support",
    "error_recovery",
    "pipeline_based",
    "job_tracking",
    "stateful",
    "checkpointing",
    "conditional_routing",
    "iterator_support",
    "message_history",
    "interrupt_support",
  ],
)]
class StateGraphOrchestratorPlugin extends OrchestratorPluginBase implements ContainerFactoryPluginInterface, PipelineExecutorAwareInterface {

  /**
   * The underlying orchestrator service.
   *
   * @var \Drupal\flowdrop_stategraph\Service\StateGraphOrchestrator
   */
  protected StateGraphOrchestrator $orchestratorService;

  /**
   * Constructs a new StateGraphOrchestratorPlugin.
   *
   * @param array<string, mixed> $configuration
   *   A configuration array.
   * @param string $plugin_id
   *   The plugin ID.
   * @param mixed $plugin_definition
   *   The plugin definition.
   * @param \Drupal\flowdrop_stategraph\Service\StateGraphOrchestrator $orchestratorService
   *   The StateGraph orchestrator service (fully configured with all deps).
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    StateGraphOrchestrator $orchestratorService,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->orchestratorService = $orchestratorService;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get("flowdrop_stategraph.orchestrator"),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function orchestrate(OrchestrationRequest $request): OrchestrationResponse {
    return $this->orchestratorService->orchestrate($request);
  }

  /**
   * {@inheritdoc}
   */
  public function getPipelineExecutor(): PipelineExecutorInterface {
    return $this->orchestratorService;
  }

  /**
   * {@inheritdoc}
   */
  public function supportsWorkflow(array $workflow): bool {
    return $this->orchestratorService->supportsWorkflow($workflow);
  }

  /**
   * {@inheritdoc}
   */
  public function getCapabilities(): array {
    return $this->orchestratorService->getCapabilities();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state, array $settings): array {
    // Merge with defaults to ensure all settings have values.
    $settings = array_merge($this->getDefaultConfiguration(), $settings);

    // StateGraph-specific: Checkpointer configuration.
    $form["stategraph"] = [
      "#type" => "fieldset",
      "#title" => $this->t("StateGraph Settings"),
      "#description" => $this->t("Configure stateful graph execution with checkpointing and iteration control."),
    ];

    $form["stategraph"]["checkpointer_type"] = [
      "#type" => "select",
      "#title" => $this->t("Checkpointer Type"),
      "#description" => $this->t("Select how state checkpoints are stored. Use 'Memory' for development/testing and 'Entity' for production with persistence."),
      "#options" => [
        "memory" => $this->t("Memory (temporary, faster)"),
        "entity" => $this->t("Entity (persistent, durable)"),
      ],
      "#default_value" => $settings["stategraph"]["checkpointer_type"] ?? "memory",
    ];

    $form["stategraph"]["max_iterations"] = [
      "#type" => "number",
      "#title" => $this->t("Maximum Iterations"),
      "#description" => $this->t("Maximum number of loop iterations before execution stops. Prevents infinite loops."),
      "#default_value" => $settings["stategraph"]["max_iterations"] ?? 100,
      "#min" => 1,
      "#max" => 10000,
    ];

    $form["stategraph"]["create_checkpoints"] = [
      "#type" => "checkbox",
      "#title" => $this->t("Create Checkpoints"),
      "#description" => $this->t("Create checkpoints during execution for recovery and debugging. Recommended for production."),
      "#default_value" => $settings["stategraph"]["create_checkpoints"] ?? TRUE,
    ];

    $form["stategraph"]["debug_mode"] = [
      "#type" => "checkbox",
      "#title" => $this->t("Debug Mode"),
      "#description" => $this->t("Enable verbose logging for debugging. Not recommended for production."),
      "#default_value" => $settings["stategraph"]["debug_mode"] ?? FALSE,
    ];

    // Thread configuration (advanced).
    $form["thread"] = [
      "#type" => "details",
      "#title" => $this->t("Thread Configuration (Advanced)"),
      "#description" => $this->t("Configure thread-based conversation continuity. Leave empty for new threads."),
      "#open" => FALSE,
    ];

    $form["thread"]["thread_id"] = [
      "#type" => "textfield",
      "#title" => $this->t("Thread ID"),
      "#description" => $this->t("Optional thread ID to resume an existing conversation. Leave empty for a new thread."),
      "#default_value" => $settings["stategraph"]["thread_id"] ?? "",
      "#maxlength" => 255,
    ];

    $form["thread"]["resume_from_checkpoint"] = [
      "#type" => "textfield",
      "#title" => $this->t("Resume from Checkpoint"),
      "#description" => $this->t("Optional checkpoint ID to resume execution from. Leave empty to start fresh."),
      "#default_value" => $settings["stategraph"]["resume_from_checkpoint"] ?? "",
      "#maxlength" => 255,
    ];

    // Add common fields from parent (priority, timeout).
    $form = parent::buildConfigurationForm($form, $form_state, $settings);

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array $form, FormStateInterface $form_state): void {
    parent::validateConfigurationForm($form, $form_state);

    // Validate max_iterations is positive.
    $values = $form_state->getValue("orchestrator_settings") ?? [];
    $maxIterations = $values["stategraph"]["max_iterations"] ?? 100;

    if ($maxIterations < 1) {
      $form_state->setErrorByName(
        "orchestrator_settings][stategraph][max_iterations",
        $this->t("Maximum iterations must be at least 1.")
      );
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array $form, FormStateInterface $form_state): array {
    // Get base configuration from parent.
    $config = parent::submitConfigurationForm($form, $form_state);

    // Extract StateGraph-specific values.
    $values = $form_state->getValue("orchestrator_settings") ?? [];

    // Build stategraph configuration nested structure.
    $stategraphSettings = $values["stategraph"] ?? [];
    $threadSettings = $values["thread"] ?? [];

    $config["stategraph"] = [
      "checkpointer_type" => $stategraphSettings["checkpointer_type"] ?? "memory",
      "max_iterations" => (int) ($stategraphSettings["max_iterations"] ?? 100),
      "create_checkpoints" => (bool) ($stategraphSettings["create_checkpoints"] ?? TRUE),
      "debug_mode" => (bool) ($stategraphSettings["debug_mode"] ?? FALSE),
      "thread_id" => !empty($threadSettings["thread_id"]) ? $threadSettings["thread_id"] : NULL,
      "resume_from_checkpoint" => !empty($threadSettings["resume_from_checkpoint"]) ? $threadSettings["resume_from_checkpoint"] : NULL,
    ];

    return $config;
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultConfiguration(): array {
    return [
      "type" => $this->getPluginId(),
      "priority" => "normal",
      "timeout" => 300,
      "stategraph" => [
        "checkpointer_type" => "memory",
        "max_iterations" => 100,
        "create_checkpoints" => TRUE,
        "debug_mode" => FALSE,
        "thread_id" => NULL,
        "resume_from_checkpoint" => NULL,
      ],
    ];
  }

}
