<?php

namespace App\EventListener;

use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpKernel\Exception\HttpException;

/**
 * Convertit les exceptions de sécurité et redirections en réponses JSON pour l'API
 */
class ApiExceptionListener
{
    /**
     * IMPORTANT: Exécuté TRÈS tôt pour forcer le chargement de la session
     */
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();

        // Seulement pour /api
        if (!str_starts_with($request->getPathInfo(), '/api')) {
            return;
        }

        // S'assurer que la session est chargée et disponible
        // Cela permet au firewall /api d'accéder à la session du context partagé
        try {
            if ($request->hasSession()) {
                $session = $request->getSession();
                // Forcer le chargement/démarrage de la session
                if (!$session->isStarted()) {
                    $session->start();
                }
            }
        } catch (\Exception $e) {
            // Ignorer les erreurs de session
        }
    }

    public function onKernelException(ExceptionEvent $event): void
    {
        $request = $event->getRequest();
        $exception = $event->getThrowable();

        // Vérifier si c'est une route /api
        if (!str_starts_with($request->getPathInfo(), '/api')) {
            return;
        }

        $response = null;

        if ($exception instanceof AuthenticationException) {
            // Non authentifié
            $response = new JsonResponse(
                [
                    'error' => 'Unauthorized',
                    'message' => 'Authentication required',
                ],
                401
            );
        } elseif ($exception instanceof AccessDeniedException) {
            // Authentifié mais pas les droits
            $response = new JsonResponse(
                [
                    'error' => 'Forbidden',
                    'message' => 'You do not have permission to access this resource',
                ],
                403
            );
        }

        if ($response !== null) {
            $event->setResponse($response);
        }
    }

    /**
     * Intercepter les réponses de redirection sur les routes /api
     * et les convertir en 401 JSON
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        $request = $event->getRequest();
        $response = $event->getResponse();

        // Vérifier si c'est une route /api ET une redirection (302, 301, 303, 307, 308)
        if (str_starts_with($request->getPathInfo(), '/api') &&
            in_array($response->getStatusCode(), [301, 302, 303, 307, 308])) {

            // Remplacer la redirection par une réponse 401 JSON
            $jsonResponse = new JsonResponse(
                [
                    'error' => 'Unauthorized',
                    'message' => 'Authentication required. Please provide a valid API token or be logged in.',
                ],
                401
            );
            $event->setResponse($jsonResponse);
        }
    }
}
