<?php

declare(strict_types=1);

namespace Drupal\native_observability_execution\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\native_observability_execution\Service\ExecutionTimelineBuilder;

/**
 * Filters form for the Execution page.
 *
 * Uses GET parameters to keep URLs shareable and consistent with Trace filters.
 */
final class ExecutionFiltersForm extends FormBase {

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The execution timeline builder.
   *
   * @var \Drupal\native_observability_execution\Service\ExecutionTimelineBuilder
   */
  protected $timelineBuilder;

  /**
   * The private temp store factory.
   *
   * @var \Drupal\Core\TempStore\PrivateTempStoreFactory
   */
  protected $tempStoreFactory;

  public function __construct(
    RequestStack $requestStack,
    ExecutionTimelineBuilder $timelineBuilder,
    PrivateTempStoreFactory $tempStoreFactory,
  ) {
    $this->requestStack = $requestStack;
    $this->timelineBuilder = $timelineBuilder;
    $this->tempStoreFactory = $tempStoreFactory;
  }

  /**
   * Creates the form instance.
   */
  public static function create(ContainerInterface $container): self {
    return new self(
      $container->get('request_stack'),
      $container->get('native_observability_execution.timeline_builder'),
      $container->get('tempstore.private'),
    );
  }

  /**
   * Gets the form identifier.
   */
  public function getFormId(): string {
    return 'native_observability_execution_filters';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $query = $this->requestStack->getCurrentRequest()->query;

    // IMPORTANT:
    // - Use GET so filters are reflected in the URL.
    // - Disable caching since output depends on query parameters.
    $form['#method'] = 'get';
    $form['#cache'] = ['max-age' => 0];

    $form['filters'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => ['container-inline', 'native-observability-execution-filters'],
      ],
    ];

    $form['filters']['path'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Path'),
      '#size' => 20,
      '#default_value' => (string) $query->get('path', ''),
    ];

    $methods = ['' => $this->t('- Any -')] + $this->timelineBuilder->getAvailableMethods();
    $statuses = ['' => $this->t('- Any -')] + $this->timelineBuilder->getAvailableStatuses();

    $form['filters']['method'] = [
      '#type' => 'select',
      '#title' => $this->t('Method'),
      '#options' => $methods,
      '#default_value' => (string) $query->get('method', ''),
    ];

    $categories = ['' => $this->t('- Any -')] + $this->timelineBuilder->getAvailableCategories();

    $form['filters']['category'] = [
      '#type' => 'select',
      '#title' => $this->t('Category'),
      '#options' => $categories,
      '#default_value' => (string) $query->get('category', ''),
    ];

    // Sorting (builder supports "ts" and "duration").
    $form['filters']['sort'] = [
      '#type' => 'select',
      '#title' => $this->t('Sort'),
      '#options' => [
        'ts' => $this->t('Time'),
        'duration' => $this->t('Duration'),
      ],
      '#default_value' => (string) $query->get('sort', 'ts'),
    ];

    $form['filters']['order'] = [
      '#type' => 'select',
      '#title' => $this->t('Order'),
      '#options' => [
        'desc' => $this->t('Desc'),
        'asc' => $this->t('Asc'),
      ],
      '#default_value' => (string) $query->get('order', 'desc'),
    ];

    $form['filters']['status'] = [
      '#type' => 'select',
      '#title' => $this->t('Status'),
      '#options' => $statuses,
      '#default_value' => (string) $query->get('status', ''),
    ];

    $form['filters']['actions'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['form-actions']],
    ];

    $form['filters']['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Apply'),
      '#button_type' => 'primary',
    ];

    // Reset filters (drops all query params).
    $form['filters']['actions']['reset'] = [
      '#type' => 'link',
      '#title' => $this->t('Reset'),
      '#url' => Url::fromUserInput($this->getRequest()->getPathInfo()),
      '#attributes' => ['class' => ['button']],
    ];

    // Clear stored spans (TempStore history).
    $form['filters']['actions']['clear'] = [
      '#type' => 'submit',
      '#value' => $this->t('Clear history'),
      '#submit' => ['::clearHistorySubmit'],
      '#limit_validation_errors' => [],
      '#attributes' => [
        'class' => ['button', 'button--danger'],
        // Force POST for this action even if the form is GET.
        'formmethod' => 'post',
      ],
    ];

    return $form;
  }

  /**
   * Handles GET form submission.
   *
   * The form relies on query parameters directly, so no additional work is
   * required here.
   *
   * @param array<string, mixed> $form
   *   The form structure.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    // No-op: GET form uses query params directly.
  }

  /**
   * Clears stored spans history from TempStore.
   */
  public function clearHistorySubmit(array &$form, FormStateInterface $form_state): void {
    // Clear only the stored history; current request spans are in-memory.
    $store = $this->tempStoreFactory->get('native_observability_execution');
    $store->delete('recent_request_spans');

    $this->messenger()->addStatus($this->t('Execution history cleared.'));

    // Redirect back to the page without filters.
    $form_state->setRedirectUrl(Url::fromUserInput($this->getRequest()->getPathInfo()));
  }

}
