<?php

namespace App\Security;

use App\Service\DiscordWebhookService;
use App\Service\Mailer\Mailer;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;

#[AsEventListener(event: KernelEvents::EXCEPTION)]
class ErrorListener
{
    public function __construct(
        private readonly Mailer $mailer,
        private readonly Environment $twig,
        private readonly DiscordWebhookService $discordWebhookService
    ) {}

    public function onKernelException(ExceptionEvent $event): void
    {
        if ($_ENV['APP_ENV'] === "dev") {
            return;
        }

        $exception = $event->getThrowable();
        $request = $event->getRequest();
        $path = $request->getPathInfo();

        $statusCode = $exception instanceof HttpExceptionInterface
            ? $exception->getStatusCode()
            : Response::HTTP_INTERNAL_SERVER_ERROR;

        // On envoie le mail pour les 500 ET les 404
        // Filtre optionnel : on évite les mails pour les fichiers techniques (.env, .php, etc) cherchés par les bots
        $isBotTarget = preg_match('/\.(php|env|yaml|xml|map)$/i', $path);

        if (!$isBotTarget && $statusCode == 500) {
            $this->mailer->send(
                'notification@siteconseil.fr',
                "Notification siteconseil",
                "[Intranet Ludikevent] - Alerte 500 Erreur serveur",
                "mails/tech/noaccess.twig",
                [
                    'message' => [
                        'service' => 'Application Core',
                        'status' => "Code $statusCode sur l'URL : $path",
                        'trace' => $exception->getMessage()
                    ]
                ]
            );

            $this->discordWebhookService->send(null, [[
                'title' => '🚨 Alerte 500 Erreur Serveur',
                'description' => substr($exception->getMessage(), 0, 2000), // Discord limit
                'color' => 15548997, // Red
                'fields' => [
                    [
                        'name' => 'URL',
                        'value' => $path,
                        'inline' => false
                    ],
                    [
                        'name' => 'Environnement',
                        'value' => $_ENV['APP_ENV'] ?? 'prod',
                        'inline' => true
                    ]
                ],
                'timestamp' => date('c')
            ]]);
        }

        // --- Gestion de la Réponse (JSON vs HTML) ---
        $acceptHeader = $request->headers->get('Accept', '');
        $isJsonRequest = str_contains($acceptHeader, 'application/json') || $request->getContentTypeFormat() === 'json';

        if ($isJsonRequest) {
            $response = new JsonResponse([
                'status' => 'error',
                'code' => $statusCode,
                'message' => $statusCode === 404 ? 'Resource not found' : 'Internal server error'
            ], $statusCode);
        } else {
            $template = ($statusCode === 404) ? 'error/404.twig' : 'error/500.twig';

            try {
                $html = $this->twig->render($template, [
                    'status_code' => $statusCode,
                    'exception' => $exception
                ]);
            } catch (\Exception $e) {
                $html = "<h1>Erreur critique ($statusCode)</h1><p>Une erreur inattendue est survenue.</p>";
            }

            $response = new Response($html, $statusCode);
        }

        $event->setResponse($response);
    }
}
