<?php

declare(strict_types=1);

namespace Drupal\native_observability_cache_observer\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\native_observability_cache_observer\Service\CacheObserverStorage;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Exports raw cache observer events as JSON.
 */
final class CacheObserverExportController extends ControllerBase {

  /**
   * Creates a new cache observer export controller instance.
   */
  public function __construct(
    private readonly CacheObserverStorage $storage,
    private readonly RequestStack $cacheObserverRequestStack,
  ) {
  }

  /**
   * Exports a single raw event as JSON.
   */
  public function export(int $id): Response {
    $record = $this->storage->load($id);
    if (!$record) {
      throw new NotFoundHttpException('Cache observer event not found.');
    }

    $payload = json_encode($record, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?: '{}';
    $filename = 'cache_observer_event_' . $id . '.json';

    $response = new Response($payload);
    $response->headers->set('Content-Type', 'application/json; charset=UTF-8');
    $response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');

    return $response;
  }

  /**
   * Exports the filtered raw dataset as JSON.
   */
  public function exportFiltered(): Response {
    $request = $this->cacheObserverRequestStack->getCurrentRequest();

    $filters = [
      'search' => (string) $request?->query->get('search', ''),
      'event_type' => (string) $request?->query->get('event_type', ''),
      'cache_layer' => (string) $request?->query->get('cache_layer', ''),
      'status' => (string) $request?->query->get('status', ''),
      'method' => (string) $request?->query->get('method', ''),
      'route_name' => (string) $request?->query->get('route_name', ''),
      'path' => (string) $request?->query->get('path', ''),
      'request_id' => (string) $request?->query->get('request_id', ''),
      'has_request_id' => (string) $request?->query->get('has_request_id', ''),
      'uncacheable_only' => (string) $request?->query->get('uncacheable_only', ''),
      'sort' => (string) $request?->query->get('sort', 'created_at'),
      'direction' => (string) $request?->query->get('direction', 'DESC'),
    ];

    $filters = array_filter($filters, static fn($value): bool => $value !== '' && $value !== NULL);
    $rows = $this->storage->search($filters, 5000, 0);

    $payload = json_encode([
      'meta' => [
        'exported_at' => gmdate('c'),
        'count' => count($rows),
        'filters' => $filters,
      ],
      'rows' => $rows,
    ], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?: '{}';

    $filename = 'cache_observer_filtered_export.json';

    $response = new Response($payload);
    $response->headers->set('Content-Type', 'application/json; charset=UTF-8');
    $response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');

    return $response;
  }

}
