<?php

declare(strict_types=1);

namespace Drupal\flowdrop\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Central settings form for FlowDrop configuration.
 *
 * This form provides a single location for managing FlowDrop-wide settings
 * that affect the entire ecosystem, including logging, performance, and
 * behavior options.
 *
 * The orchestrator plugin manager is accessed dynamically to avoid a circular
 * dependency: flowdrop → flowdrop_orchestration → flowdrop.
 *
 * @internal This class is not part of the public API and may change without notice.
 */
final class FlowDropSettingsForm extends ConfigFormBase {

  /**
   * The orchestrator plugin manager.
   *
   * Untyped to avoid importing from flowdrop_orchestration (circular dep).
   *
   * @var mixed
   */
  protected mixed $orchestratorManager = NULL;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): static {
    $instance = parent::create($container);
    if ($container->has("flowdrop_orchestration.plugin_manager")) {
      $instance->orchestratorManager = $container->get("flowdrop_orchestration.plugin_manager");
    }
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames(): array {
    return ['flowdrop.settings'];
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'flowdrop_settings_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $config = $this->config('flowdrop.settings');

    // Logging Settings.
    $form['logging'] = [
      '#type' => 'details',
      '#title' => $this->t('Logging'),
      '#open' => TRUE,
      '#tree' => TRUE,
    ];

    $form['logging']['log_verbosity'] = [
      '#type' => 'select',
      '#title' => $this->t('Logging Verbosity'),
      '#description' => $this->t('Controls the amount of detail logged during workflow and node execution.'),
      '#options' => [
        'silent' => $this->t('Silent - No execution logging'),
        'minimal' => $this->t('Minimal - Errors only'),
        'standard' => $this->t('Standard - Workflow/node start and completion (default)'),
        'verbose' => $this->t('Verbose - Include parameter summaries and warnings'),
        'debug' => $this->t('Debug - Full parameter dumps and stack traces'),
      ],
      '#default_value' => $config->get('logging.verbosity') ?? 'standard',
    ];

    $form['logging']['log_to_watchdog'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Log to Drupal watchdog'),
      '#description' => $this->t('When enabled, execution logs are written to Drupal"s database log (dblog).'),
      '#default_value' => $config->get('logging.log_to_watchdog') ?? TRUE,
    ];

    // Execution Settings.
    $form['execution'] = [
      '#type' => 'details',
      '#title' => $this->t('Execution'),
      '#open' => FALSE,
      '#tree' => TRUE,
    ];

    $form['execution']['default_orchestrator'] = [
      '#type' => 'select',
      '#title' => $this->t('Default Orchestrator'),
      '#description' => $this->t('The default orchestrator to use for workflow execution.'),
      '#options' => $this->getOrchestratorOptions(),
      '#default_value' => $config->get('execution.default_orchestrator') ?? 'flowdrop_runtime:synchronous',
    ];

    $form['execution']['max_execution_time'] = [
      '#type' => 'number',
      '#title' => $this->t('Maximum Execution Time'),
      '#description' => $this->t('Maximum time (in seconds) a single node can execute before timeout. Set to 0 for no limit.'),
      '#min' => 0,
      '#max' => 3600,
      '#default_value' => $config->get('execution.max_execution_time') ?? 300,
      '#field_suffix' => $this->t('seconds'),
    ];

    // Real-time Updates Settings.
    $form['realtime'] = [
      '#type' => 'details',
      '#title' => $this->t('Real-time Updates'),
      '#open' => FALSE,
      '#access' => FALSE,
      '#tree' => TRUE,
    ];

    $form['realtime']['enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable real-time status updates'),
      '#description' => $this->t('When enabled, workflow execution status is broadcast in real-time to connected clients.'),
      '#default_value' => $config->get('realtime.enabled') ?? TRUE,
    ];

    $form['realtime']['polling_interval'] = [
      '#type' => 'number',
      '#title' => $this->t('Polling Interval'),
      '#description' => $this->t('How often (in milliseconds) clients should poll for status updates when SSE is unavailable.'),
      '#min' => 0,
      '#max' => 30000,
      '#default_value' => $config->get('realtime.polling_interval') ?? 2000,
      '#field_suffix' => $this->t('ms'),
      '#states' => [
        'visible' => [
          ':input[name="realtime[enabled]"]' => ['checked' => TRUE],
        ],
      ],
    ];

    // UI Settings.
    $form['ui'] = [
      '#type' => 'details',
      '#title' => $this->t('User Interface'),
      '#open' => FALSE,
      '#tree' => TRUE,
    ];

    $form['ui']['icon_picker_enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable icon picker'),
      '#description' => $this->t('When enabled, icon fields in node category and node type forms will display an interactive icon picker powered by <a href="@url" target="_blank">Iconify Picker</a>. This provides access to over 7,000 Material Design Icons for selecting node icons.', [
        '@url' => 'https://metaory.github.io/iconify-picker/',
      ]),
      '#default_value' => $config->get('ui.icon_picker_enabled') ?? TRUE,
    ];

    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $this->config('flowdrop.settings')
      ->set('logging.verbosity', $form_state->getValue(['logging', 'log_verbosity']))
      ->set('logging.log_to_watchdog', (bool) $form_state->getValue(['logging', 'log_to_watchdog']))
      ->set('execution.default_orchestrator', $form_state->getValue(['execution', 'default_orchestrator']))
      ->set('execution.max_execution_time', (int) $form_state->getValue(['execution', 'max_execution_time']))
      ->set('realtime.enabled', (bool) $form_state->getValue(['realtime', 'enabled']))
      ->set('realtime.polling_interval', (int) $form_state->getValue(['realtime', 'polling_interval']))
      ->set('ui.icon_picker_enabled', (bool) $form_state->getValue(['ui', 'icon_picker_enabled']))
      ->save();

    parent::submitForm($form, $form_state);
  }

  /**
   * Get orchestrator options dynamically from registered orchestrators.
   *
   * Retrieves all orchestrator plugins from the plugin manager and builds
   * a select options array with descriptions.
   *
   * @return array<string, string>
   *   Options array with orchestrator IDs as keys and labels as values.
   */
  protected function getOrchestratorOptions(): array {
    $options = [];

    if ($this->orchestratorManager === NULL) {
      return $options;
    }

    // Get all registered orchestrators from the plugin manager.
    $definitions = $this->orchestratorManager->getDefinitions();

    foreach ($definitions as $id => $definition) {
      $label = $definition["label"] ?? ucfirst(str_replace("_", " ", $id));
      $description = $definition["description"] ?? "";

      // Convert TranslatableMarkup to string if needed.
      $labelStr = $label instanceof \Stringable ? (string) $label : $label;

      // Add description to label for clarity if available.
      if (!empty($description)) {
        $options[$id] = sprintf("%s - %s", $labelStr, $description);
      }
      else {
        $options[$id] = $labelStr;
      }
    }

    return $options;
  }

}
