<?php

declare(strict_types=1);

namespace Drupal\native_observability_cache_observer\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_cache_observer\Form\CacheObserverFiltersForm;
use Drupal\native_observability_cache_observer\Service\CacheObserverEnvironmentInspector;
use Drupal\native_observability_cache_observer\Service\CacheObserverStorage;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

/**
 * Raw listing controller for cache observer events.
 */
final class CacheObserverListController extends ControllerBase {

  /**
   * Creates a new cache observer list controller instance.
   */
  public function __construct(
    private readonly CacheObserverStorage $cacheObserverStorage,
    private readonly PagerManagerInterface $cacheObserverPagerManager,
    private readonly RequestStack $cacheObserverRequestStack,
    private readonly CacheObserverEnvironmentInspector $cacheObserverEnvironmentInspector,
    #[Autowire(service: 'date.formatter')]
    private readonly DateFormatterInterface $dateFormatter,
  ) {
  }

  /**
   * Builds the raw listing page.
   */
  public function list(): array {
    $request = $this->cacheObserverRequestStack->getCurrentRequest();

    $filters = [
      'search' => (string) $request?->query->get('search', ''),
      'event_type' => (string) $request?->query->get('event_type', ''),
      'status' => (string) $request?->query->get('status', ''),
      'method' => (string) $request?->query->get('method', ''),
    ];

    $filters = array_filter(
      $filters,
      static fn($value): bool => $value !== '' && $value !== NULL
    );

    $limit = 50;
    $total = $this->cacheObserverStorage->count($filters);
    $pager = $this->cacheObserverPagerManager->createPager($total, $limit);
    $offset = $pager->getCurrentPage() * $limit;

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

    $tableRows = [];
    foreach ($rows as $row) {
      $id = (int) $row['id'];

      $eventLayerMarkup = [
        '#type' => 'container',
        'event_type' => [
          '#markup' => '<div><strong>' . $this->t('@value', [
            '@value' => (string) ($row['event_type'] ?? ''),
          ]) . '</strong></div>',
        ],
        'layer' => [
          '#markup' => '<div style="font-size:12px; color:#6b7280;">' . $this->t('@value', [
            '@value' => (string) ($row['cache_layer'] ?? ''),
          ]) . '</div>',
        ],
      ];

      $routePathMarkup = [
        '#type' => 'container',
        'path' => [
          '#markup' => '<div><strong>' . $this->t('@value', [
            '@value' => (string) ($row['path'] ?? ''),
          ]) . '</strong></div>',
        ],
        'separator' => [
          '#markup' => '<hr style="margin:6px 0;">',
        ],
        'route' => [
          '#markup' => '<div style="font-size:12px; color:#6b7280;">' . $this->t('@value', [
            '@value' => (string) ($row['route_name'] ?? ''),
          ]) . '</div>',
        ],
      ];

      $cacheabilityMarkup = [
        '#type' => 'container',
        'tags' => [
          '#markup' => '<div>' . $this->t('Tags: @value', [
            '@value' => (string) ($row['tag_count'] ?? 0),
          ]) . '</div>',
        ],
        'contexts' => [
          '#markup' => '<div>' . $this->t('Contexts: @value', [
            '@value' => (string) ($row['context_count'] ?? 0),
          ]) . '</div>',
        ],
        'max_age' => [
          '#markup' => '<div>' . $this->t('Max-age: @value', [
            '@value' => (string) ($row['max_age'] ?? ''),
          ]) . '</div>',
        ],
      ];

      $createdAtFormatted = !empty($row['created_at'])
        ? $this->dateFormatter->format((int) $row['created_at'], 'short')
        : '';
      $tableRows[] = [
        [
          'data' => Link::fromTextAndUrl(
            (string) $id,
            Url::fromRoute('native_observability_cache_observer.view', ['id' => $id])
          )->toString(),
        ],
        ['data' => $eventLayerMarkup],
        ['data' => (string) ($row['status'] ?? '')],
        ['data' => (string) ($row['method'] ?? '')],
        ['data' => $routePathMarkup],
        ['data' => (string) ($row['request_id'] ?? '')],
        ['data' => $cacheabilityMarkup],
        ['data' => $createdAtFormatted],
      ];
    }

    $build = [
      '#type' => 'container',
      'filters' => $this->formBuilder()->getForm(CacheObserverFiltersForm::class),
    ];

    $environment = $this->cacheObserverEnvironmentInspector->inspect();
    if (!empty($environment['has_warnings'])) {
      $warningItems = [];
      foreach ($environment['warnings'] as $warning) {
        $warningItems[] = (string) $warning;
      }

      $build['environment_warning'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['messages', 'messages--warning'],
          'style' => 'margin-bottom:16px; padding:12px; border-left:4px solid #d39e00;',
        ],
        'title' => [
          '#markup' => '<strong>' . $this->t('Development/debug environment detected') . '</strong>',
        ],
        'summary' => [
          '#markup' => '<div style="margin-top:6px;">'
          . $this->t('@summary', ['@summary' => (string) $environment['summary']])
          . '</div>',
        ],
        'list' => [
          '#theme' => 'item_list',
          '#items' => $warningItems,
        ],
        'note' => [
          '#markup' => '<div style="margin-top:8px;">'
          . $this->t('In this condition, cache headers, page cache hits, dynamic cache hits, and other cache observer signals may be partial, reduced, or completely missing.')
          . '</div>',
        ],
      ];
    }

    $build['table'] = [
      '#type' => 'table',
      '#header' => [
        $this->t('ID'),
        $this->t('Event / Layer'),
        $this->t('Status'),
        $this->t('Method'),
        $this->t('Route / Path'),
        $this->t('Request ID'),
        $this->t('Cacheability'),
        $this->t('Created'),
      ],
      '#rows' => $tableRows,
      '#empty' => $this->t('No cache observer events found yet.'),
    ];

    $build['pager'] = [
      '#type' => 'pager',
    ];

    return $build;
  }

}
