<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Applies security headers to FFmpeg API, AJAX, and SSE responses.
 */
final class ApiResponseSecurityHeadersSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   *
   * @phpstan-return array<string, array{string, int}>
   */
  #[\Override]
  public static function getSubscribedEvents(): array {
    return [
      KernelEvents::RESPONSE => ['onKernelResponse', -100],
    ];
  }

  /**
   * Adds hardening headers for FFmpeg machine-consumable endpoints.
   */
  public function onKernelResponse(ResponseEvent $event): void {
    if (!$event->isMainRequest()) {
      return;
    }

    $request = $event->getRequest();
    $routeName = (string) ($request->attributes->get('_route') ?? '');
    $path = $request->getPathInfo();

    if (!$this->isHardenedEndpoint($routeName, $path)) {
      return;
    }

    $response = $event->getResponse();
    $headers = $response->headers;

    // Security hardening headers for API-like endpoints.
    $headers->set('X-Content-Type-Options', 'nosniff');
    $headers->set('X-Frame-Options', 'DENY');
    $headers->set('Referrer-Policy', 'no-referrer');
    $headers->set('Content-Security-Policy', "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'");
    $headers->set('Permissions-Policy', 'interest-cohort=()');
    $headers->set('Cross-Origin-Resource-Policy', 'same-origin');

    $headers->set('Cache-Control', 'no-cache, no-store, must-revalidate');
    $headers->set('Pragma', 'no-cache');
    $headers->set('Expires', '0');
  }

  /**
   * Returns TRUE for FFmpeg API/AJAX/SSE routes that should be hardened.
   */
  private function isHardenedEndpoint(string $routeName, string $path): bool {
    if (
      str_starts_with($routeName, 'ffmpeg_media.health') ||
      str_starts_with($routeName, 'ffmpeg_media.metrics') ||
      $routeName === 'ffmpeg_media.progress' ||
      str_starts_with($routeName, 'ffmpeg_media_ui.ajax.') ||
      str_starts_with($routeName, 'ffmpeg_media_ui.sse.')
    ) {
      return TRUE;
    }

    return str_starts_with($path, '/api/ffmpeg-media/') ||
      str_starts_with($path, '/ffmpeg-media/ajax/') ||
      str_starts_with($path, '/ffmpeg-media/sse/');
  }

}
