<?php

declare(strict_types=1);

namespace Drupal\flowdrop_runtime\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\SynchronousOrchestrator;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Synchronous workflow orchestrator plugin.
 *
 * Executes workflows directly without requiring pipeline entities. Uses the
 * ExecutionGraph for determining execution order and the DependencyGraph for
 * data resolution at runtime.
 *
 * This plugin delegates to the SynchronousOrchestrator 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: "synchronous",
  label: new TranslatableMarkup("Synchronous Orchestrator"),
  description: "Executes workflows synchronously with real-time updates",
  capabilities: [
    "synchronous_execution",
    "retry_support",
    "error_recovery",
    "workflow_compilation",
    "direct_execution",
    "interrupt_support",
  ],
)]
class SynchronousOrchestratorPlugin extends OrchestratorPluginBase implements ContainerFactoryPluginInterface {

  /**
   * The underlying synchronous orchestrator service.
   *
   * @var \Drupal\flowdrop_runtime\Service\Orchestrator\SynchronousOrchestrator
   */
  protected SynchronousOrchestrator $orchestratorService;

  /**
   * Constructs a new SynchronousOrchestratorPlugin.
   *
   * @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_runtime\Service\Orchestrator\SynchronousOrchestrator $orchestratorService
   *   The synchronous orchestrator service (fully configured with all deps).
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    SynchronousOrchestrator $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_runtime.synchronous_orchestrator"),
    );
  }

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

  /**
   * {@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);

    // Synchronous orchestrator has minimal configuration.
    // Just use the common fields (priority, timeout) from parent.
    $form["info"] = [
      "#type" => "markup",
      "#markup" => "<p>" . $this->t("The synchronous orchestrator executes workflows immediately in the current request. It provides real-time updates and is best suited for short-running workflows.") . "</p>",
    ];

    $form["realtime"] = [
      "#type" => "fieldset",
      "#title" => $this->t("Real-Time Settings"),
      "#description" => $this->t("Configure real-time execution behavior."),
    ];

    $form["realtime"]["enable_realtime_updates"] = [
      "#type" => "checkbox",
      "#title" => $this->t("Enable Real-Time Updates"),
      "#description" => $this->t("Send real-time status updates during execution. Requires WebSocket or SSE support."),
      "#default_value" => $settings["enable_realtime_updates"] ?? TRUE,
    ];

    $form["realtime"]["log_level"] = [
      "#type" => "select",
      "#title" => $this->t("Logging Level"),
      "#description" => $this->t("Detail level for execution logging."),
      "#options" => [
        "minimal" => $this->t("Minimal - Only errors"),
        "normal" => $this->t("Normal - Start/end and errors"),
        "verbose" => $this->t("Verbose - All node executions"),
        "debug" => $this->t("Debug - Everything including data"),
      ],
      "#default_value" => $settings["log_level"] ?? "normal",
    ];

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

    return $form;
  }

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

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

    $realtimeSettings = $values["realtime"] ?? [];
    $config["enable_realtime_updates"] = (bool) ($realtimeSettings["enable_realtime_updates"] ?? TRUE);
    $config["log_level"] = $realtimeSettings["log_level"] ?? "normal";

    return $config;
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultConfiguration(): array {
    return [
      "type" => $this->getPluginId(),
      "priority" => "normal",
      "timeout" => 300,
      "enable_realtime_updates" => TRUE,
      "log_level" => "normal",
    ];
  }

}
