<?php

declare(strict_types=1);

namespace Drupal\flowdrop_orchestration\Plugin\Orchestrator;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\flowdrop_orchestration\DTO\Orchestrator\OrchestrationRequest;
use Drupal\flowdrop_orchestration\DTO\Orchestrator\OrchestrationResponse;

/**
 * Base class for Orchestrator plugins.
 *
 * Provides common functionality for orchestrator implementations.
 * Extend this class to create custom orchestrators.
 *
 * This base class provides default implementations for the configuration
 * form methods with common fields (priority, timeout). Subclasses can
 * override these methods to add orchestrator-specific configuration.
 *
 * @see \Drupal\flowdrop_orchestration\Attribute\Orchestrator
 * @see \Drupal\flowdrop_orchestration\Plugin\Orchestrator\OrchestratorPluginInterface
 *
 * @api
 */
abstract class OrchestratorPluginBase extends PluginBase implements OrchestratorPluginInterface {

  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public function getType(): string {
    return $this->getPluginId();
  }

  /**
   * {@inheritdoc}
   */
  abstract public function orchestrate(OrchestrationRequest $request): OrchestrationResponse;

  /**
   * {@inheritdoc}
   */
  public function supportsWorkflow(array $workflow): bool {
    // By default, orchestrators support all workflows.
    // Override in subclasses for specific requirements.
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function getCapabilities(): array {
    $capabilities = $this->pluginDefinition["capabilities"] ?? [];
    return array_fill_keys($capabilities, TRUE);
  }

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

    // Common fields shared by most orchestrators.
    $form["priority"] = [
      "#type" => "select",
      "#title" => $this->t("Priority"),
      "#description" => $this->t("Execution priority for this trigger."),
      "#options" => [
        "low" => $this->t("Low"),
        "normal" => $this->t("Normal"),
        "high" => $this->t("High"),
        "critical" => $this->t("Critical"),
      ],
      "#default_value" => $settings["priority"] ?? "normal",
    ];

    $form["timeout"] = [
      "#type" => "number",
      "#title" => $this->t("Timeout (seconds)"),
      "#description" => $this->t("Maximum execution time in seconds. Set 0 for no timeout."),
      "#default_value" => $settings["timeout"] ?? 300,
      "#min" => 0,
      "#max" => 86400,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array $form, FormStateInterface $form_state): void {
    // Default implementation does no validation.
    // Subclasses can override to add specific validation.
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array $form, FormStateInterface $form_state): array {
    // Extract common values from form state.
    // The form values are nested under 'orchestrator_settings'.
    $values = $form_state->getValue("orchestrator_settings") ?? [];

    return [
      "type" => $this->getPluginId(),
      "priority" => $values["priority"] ?? "normal",
      "timeout" => (int) ($values["timeout"] ?? 300),
    ];
  }

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

  /**
   * Generates a unique execution ID.
   *
   * @return string
   *   The execution ID.
   */
  protected function generateExecutionId(): string {
    return sprintf(
      "%s_exec_%d_%s",
      $this->getType(),
      time(),
      bin2hex(random_bytes(6))
    );
  }

}
