<?php

namespace App\Tests\Security;

use App\Security\ErrorListener;
use App\Service\Mailer\Mailer;
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Twig\Environment;

#[AllowMockObjectsWithoutExpectations]
class ErrorListenerTest extends TestCase
{
    private $twig;
    private $mailer;
    private $listener;

    protected function setUp(): void
    {
        $this->twig = $this->createMock(Environment::class);
        $this->mailer = $this->createMock(Mailer::class);
        $this->listener = new ErrorListener($this->mailer, $this->twig);
    }

    public function testOnKernelExceptionInDevModeDoesNothing()
    {
        $_ENV['APP_ENV'] = 'dev';
        $kernel = $this->createMock(HttpKernelInterface::class);
        $request = new Request();
        $event = new ExceptionEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, new \Exception());

        // Le mailer ne doit jamais être appelé en dev
        $this->mailer->expects($this->never())->method('send');

        $this->listener->onKernelException($event);

        $this->assertNull($event->getResponse());

        unset($_ENV['APP_ENV']);
    }

    public function testOnKernelExceptionSendsEmailFor404()
    {
        $_ENV['APP_ENV'] = 'prod';
        $kernel = $this->createMock(HttpKernelInterface::class);
        $request = Request::create('/une-page-existante');

        $exception = new NotFoundHttpException('Not found');
        $event = new ExceptionEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $exception);

        // On vérifie que le mail est bien envoyé pour une 404 standard
        $this->mailer->expects($this->once())
            ->method('send')
            ->with($this->anything(), $this->anything(), $this->stringContains('404 Page introuvable'));

        $this->listener->onKernelException($event);

        unset($_ENV['APP_ENV']);
    }

    public function testOnKernelExceptionDoesNotSendEmailForBotTarget()
    {
        $_ENV['APP_ENV'] = 'prod';
        $kernel = $this->createMock(HttpKernelInterface::class);
        $request = Request::create('/.env'); // URL typique de bot

        $exception = new NotFoundHttpException('Not found');
        $event = new ExceptionEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $exception);

        // Le mailer ne doit PAS être appelé car c'est une cible de bot
        $this->mailer->expects($this->never())->method('send');

        $this->listener->onKernelException($event);

        unset($_ENV['APP_ENV']);
    }

    public function testOnKernelExceptionJsonRequest()
    {
        $_ENV['APP_ENV'] = 'prod';
        $kernel = $this->createMock(HttpKernelInterface::class);
        $request = new Request();
        $request->headers->set('Accept', 'application/json');

        $exception = new NotFoundHttpException('Not found');
        $event = new ExceptionEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $exception);

        $this->listener->onKernelException($event);

        $response = $event->getResponse();
        $this->assertInstanceOf(JsonResponse::class, $response);
        $this->assertEquals(404, $response->getStatusCode());

        unset($_ENV['APP_ENV']);
    }

    public function testOnKernelExceptionHtmlRequest()
    {
        $_ENV['APP_ENV'] = 'prod';
        $kernel = $this->createMock(HttpKernelInterface::class);
        $request = new Request();

        $exception = new \Exception('500 Error');
        $event = new ExceptionEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $exception);

        $this->twig->expects($this->once())
            ->method('render')
            ->with('error/500.twig', $this->anything())
            ->willReturn('<html>Error</html>');

        $this->listener->onKernelException($event);

        $response = $event->getResponse();
        $this->assertEquals(500, $response->getStatusCode());

        unset($_ENV['APP_ENV']);
    }
}
