<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\EventSubscriber;

use Drupal\ffmpeg_media\Service\HealthProbeAccessManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Returns machine-readable 403 payloads for denied public health probes.
 *
 * @internal
 */
final class HealthProbeAccessDeniedSubscriber implements EventSubscriberInterface {

  /**
   * Probe routes that should return JSON on access denial.
   *
   * @var list<string>
   */
  private const array PROBE_ROUTES = [
    'ffmpeg_media.health.liveness',
    'ffmpeg_media.health.readiness',
  ];

  /**
   * Constructs a HealthProbeAccessDeniedSubscriber object.
   *
   * @param \Drupal\ffmpeg_media\Service\HealthProbeAccessManagerInterface $accessManager
   *   The shared probe access manager.
   */
  public function __construct(
    protected readonly HealthProbeAccessManagerInterface $accessManager,
  ) {}

  /**
   * Replaces generic access denied pages with JSON for probe routes.
   *
   * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $event
   *   The exception event.
   */
  public function onKernelException(ExceptionEvent $event): void {
    if (!$event->getThrowable() instanceof AccessDeniedHttpException) {
      return;
    }

    $routeName = (string) $event->getRequest()->attributes->get('_route');
    if (!in_array($routeName, self::PROBE_ROUTES, TRUE)) {
      return;
    }

    $event->setResponse($this->accessManager->buildAccessDeniedResponse($event->getRequest()));
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      KernelEvents::EXCEPTION => ['onKernelException', 100],
    ];
  }

}
