<?php

declare(strict_types=1);

namespace Drupal\native_observability\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\native_observability\Service\NativeObservabilityUiBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * GET-based filters form for the traces listing.
 *
 * Filters are persisted in the URL query string.
 */
final class TraceFiltersForm extends FormBase {

  /**
   * Creates a new trace filters form instance.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The current request stack.
   * @param \Drupal\native_observability\Service\NativeObservabilityUiBuilder $ui
   *   The UI helper service used to build filter options.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   The currently authenticated user.
   */
  public function __construct(
    private readonly RequestStack $request_stack,
    private readonly NativeObservabilityUiBuilder $ui,
    private readonly AccountProxyInterface $current_user,
  ) {
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): self {
    return new self(
      $container->get('request_stack'),
      $container->get('native_observability.ui_builder'),
      $container->get('current_user')
    );
  }

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

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $request = $this->request_stack->getCurrentRequest();
    $form['#method'] = 'get';

    // Inline layout wrapper.
    $form['filters'] = [
      '#type' => 'container',
      '#attributes' => [
        'style' => 'display:flex; flex-wrap:wrap; gap:12px; align-items:flex-end; margin-bottom:12px;',
      ],
    ];

    $httpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];
    $httpMethodOptions = array_combine($httpMethods, $httpMethods) ?: [];

    $statusCodes = [
      '200', '201', '204', '301', '302', '304', '400', '401', '403', '404',
      '409', '422', '429', '500', '502', '503', '504',
    ];
    $statusCodeOptions = array_combine($statusCodes, $statusCodes) ?: [];

    $sortDirections = ['DESC', 'ASC'];
    $sortDirectionOptions = array_combine($sortDirections, $sortDirections) ?: [];

    $form['filters']['search'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Search'),
      '#default_value' => $request?->query->get('search', ''),
      '#size' => 28,
      '#attributes' => [
        'placeholder' => $this->t('Path, route, request ID...'),
      ],
    ];

    $form['filters']['method'] = [
      '#type' => 'select',
      '#title' => $this->t('Method'),
      '#options' => ['' => $this->t('- Any -')] + $httpMethodOptions,
      '#default_value' => $request?->query->get('method', ''),
    ];

    $form['filters']['status_code'] = [
      '#type' => 'select',
      '#title' => $this->t('Status'),
      '#options' => [
        '' => $this->t('- Any -'),
        '2xx' => $this->t('2xx Success'),
        '3xx' => $this->t('3xx Redirect'),
        '4xx' => $this->t('4xx Client error'),
        '5xx' => $this->t('5xx Server error'),
      ] + $statusCodeOptions,
      '#default_value' => $request?->query->get('status_code', ''),
    ];

    $form['filters']['sort'] = [
      '#type' => 'select',
      '#title' => $this->t('Sort'),
      '#options' => [
        'started_at' => $this->t('Started'),
        'status_code' => $this->t('Status'),
        'duration_ms' => $this->t('Duration (ms)'),
      ],
      '#default_value' => $request?->query->get('sort', 'started_at'),
    ];

    $form['filters']['direction'] = [
      '#type' => 'select',
      '#title' => $this->t('Direction'),
      '#options' => $sortDirectionOptions,
      '#default_value' => $request?->query->get('direction', 'DESC'),
    ];

    $form['filters']['actions'] = [
      '#type' => 'actions',
      '#attributes' => [
        'style' => 'display:flex; gap:8px;',
      ],
    ];

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

    // Keep your existing reset button helper.
    $form['filters']['actions']['reset'] = $this->ui->resetFiltersButton();

    if ($this->current_user->hasPermission('delete all native observability traces')) {
      $form['filters']['actions']['delete_all'] = $this->ui->deleteAllTracesButton();
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $values = $form_state->getValues();

    // Keep the query string compact (avoid empty values).
    $query = array_filter([
      'search' => $values['search'] ?? '',
      'method' => $values['method'] ?? '',
      'status_code' => $values['status_code'] ?? '',
      'sort' => $values['sort'] ?? 'started_at',
      'direction' => $values['direction'] ?? 'DESC',
    ], static fn($v) => $v !== '' && $v !== NULL);

    $form_state->setRedirect('native_observability.traces', [], [
      'query' => $query,
    ]);
  }

}
