<?php

declare(strict_types=1);

namespace Drupal\native_observability\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Link;
use Drupal\Core\Pager\PagerManagerInterface;
use Drupal\Core\Url;
use Drupal\native_observability\Form\TraceFiltersForm;
use Drupal\native_observability\Service\TraceStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Traces listing page (stable baseline).
 *
 * This controller intentionally provides a stable baseline:
 * - Renders a paginated table of traces.
 * - The ID column is a clickable link to the trace view page.
 *
 * Filters and sorting will be reintroduced step-by-step AFTER the baseline
 * is confirmed working.
 */
final class TraceListController extends ControllerBase {

  /**
   * Creates a new trace list controller instance.
   *
   * @param \Drupal\native_observability\Service\TraceStorageInterface $storage
   *   The trace storage service.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   * @param \Drupal\Core\Pager\PagerManagerInterface $pager_manager
   *   The pager manager service.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The current request stack.
   */
  public function __construct(
    private readonly TraceStorageInterface $storage,
    private readonly DateFormatterInterface $date_formatter,
    private readonly PagerManagerInterface $pager_manager,
    private readonly RequestStack $request_stack,
  ) {
  }

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

  /**
   * Listing callback.
   *
   * @return array
   *   Render array.
   */
  public function list(): array {

    $request = $this->request_stack->getCurrentRequest();

    // Build filters from query string.
    $filters = [
      // Global search string (storage decides which columns to search into).
      'search' => (string) $request?->query->get('search', ''),
      // Exact status code filter.
      'status_code' => $request?->query->get('status_code', ''),
      // Optional duration filters (already present in your form).
      'min_duration_ms' => $request?->query->get('min_duration_ms', ''),
      'max_duration_ms' => $request?->query->get('max_duration_ms', ''),
      // Sorting (status_code requested).
      'sort' => (string) $request?->query->get('sort', 'started_at'),
      'direction' => (string) $request?->query->get('direction', 'DESC'),
    ];

    // Keep empty values out of the filters array.
    $filters = array_filter($filters, static fn($v) => $v !== '' && $v !== NULL);

    $limit = 50;

    $total = $this->storage->count($filters);
    $pager = $this->pager_manager->createPager($total, $limit);
    $offset = $pager->getCurrentPage() * $limit;

    $rows = $this->storage->search($filters, $limit, $offset);

    // Canonical Drupal table rows structure: array of rows.
    // Each row is an array of cells with a 'data' key.
    $table_rows = [];
    foreach ($rows as $row) {
      // Rows may come as associative arrays or stdClass objects,
      // depending on the active fetch mode.
      $get = static function ($r, string $key, $default = '') {
        if (is_array($r)) {
          return $r[$key] ?? $default;
        }
        if (is_object($r)) {
          return $r->$key ?? $default;
        }
        return $default;
      };

      $id = (int) $get($row, 'id', 0);

      $table_rows[] = [
        [
          'data' => Link::fromTextAndUrl(
            (string) $id,
            Url::fromRoute('native_observability.trace_view', ['id' => $id])
          ),
        ],
        ['data' => (string) $get($row, 'request_id', '')],
        ['data' => (string) $get($row, 'method', '')],
        ['data' => (string) $get($row, 'status_code', '')],
        ['data' => (string) $get($row, 'duration_ms', '')],
        ['data' => (string) $get($row, 'path', '')],
        ['data' => (string) $get($row, 'route_name', '')],
        [
          'data' => $this->date_formatter->format(
            (int) $get($row, 'started_at', time()),
            'short'
          ),
        ],
      ];
    }

    return [
      '#type' => 'container',
      'filters' => $this->formBuilder()->getForm(TraceFiltersForm::class),
      'table' => [
        '#type' => 'table',
        '#header' => [
          $this->t('ID'),
          $this->t('Request ID'),
          $this->t('Method'),
          $this->t('Status'),
          $this->t('Duration (ms)'),
          $this->t('Path'),
          $this->t('Route'),
          $this->t('Started'),
        ],
        '#rows' => $table_rows,
        '#empty' => $this->t('No traces found yet.'),
      ],
      'pager' => [
        '#type' => 'pager',
      ],
    ];
  }

}
