<?php

namespace App\Tests\Controller;

use App\Controller\WebhookStripeController;
use App\Entity\StripeWebhookSecret;
use App\Repository\StripeWebhookSecretRepository;
use App\Service\FactureService;
use App\Service\MailerService;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Twig\Environment;

class WebhookStripeControllerTest extends TestCase
{
    private function createController(?string $secret = null): WebhookStripeController
    {
        $repo = $this->createStub(StripeWebhookSecretRepository::class);
        $repo->method('getSecret')->willReturn($secret);

        return new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $repo,
            $this->createStub(EntityManagerInterface::class),
            $this->createStub(MailerService::class),
            $this->createStub(Environment::class),
            $this->createStub(FactureService::class),
            $this->createStub(KernelInterface::class),
            $this->createStub(UrlGeneratorInterface::class),
        );
    }

    private function createPostRequest(string $body = '{}', string $signature = ''): Request
    {
        $request = new Request([], [], [], [], [], ['HTTP_STRIPE_SIGNATURE' => $signature], $body);
        $request->setMethod('POST');

        return $request;
    }

    public function testMainLightNoSecret(): void
    {
        $controller = $this->createController(null);
        $response = $controller->mainLight($this->createPostRequest());

        $this->assertSame(503, $response->getStatusCode());
        $this->assertStringContainsString('not configured', $response->getContent());
    }

    public function testMainInstantNoSecret(): void
    {
        $controller = $this->createController(null);
        $response = $controller->mainInstant($this->createPostRequest());

        $this->assertSame(503, $response->getStatusCode());
    }

    public function testConnectLightNoSecret(): void
    {
        $controller = $this->createController(null);
        $response = $controller->connectLight($this->createPostRequest());

        $this->assertSame(503, $response->getStatusCode());
    }

    public function testConnectInstantNoSecret(): void
    {
        $controller = $this->createController(null);
        $response = $controller->connectInstant($this->createPostRequest());

        $this->assertSame(503, $response->getStatusCode());
    }

    public function testMainLightInvalidSignature(): void
    {
        $controller = $this->createController('whsec_test123');
        $response = $controller->mainLight($this->createPostRequest('{"id":"evt_1"}', 't=123,v1=bad'));

        $this->assertSame(400, $response->getStatusCode());
    }

    public function testMainLightInvalidPayload(): void
    {
        $controller = $this->createController('whsec_test123');
        $response = $controller->mainLight($this->createPostRequest('not-json', ''));

        $this->assertSame(400, $response->getStatusCode());
    }

    public function testMainInstantInvalidSignature(): void
    {
        $controller = $this->createController('whsec_test123');
        $response = $controller->mainInstant($this->createPostRequest('{"id":"evt_1"}', 't=123,v1=bad'));

        $this->assertSame(400, $response->getStatusCode());
    }

    public function testConnectLightInvalidSignature(): void
    {
        $controller = $this->createController('whsec_test123');
        $response = $controller->connectLight($this->createPostRequest('{"id":"evt_1"}', 't=123,v1=bad'));

        $this->assertSame(400, $response->getStatusCode());
    }

    public function testConnectInstantInvalidSignature(): void
    {
        $controller = $this->createController('whsec_test123');
        $response = $controller->connectInstant($this->createPostRequest('{"id":"evt_1"}', 't=123,v1=bad'));

        $this->assertSame(400, $response->getStatusCode());
    }

    // ---------------------------------------------------------------
    // Tests des méthodes privées via Reflection
    // ---------------------------------------------------------------

    /**
     * Crée un objet \Stripe\Event synthétique pour les tests.
     * Stripe\StripeObject supporte l'accès dynamique aux propriétés.
     */
    private function buildStripePaymentIntentEvent(string $type, array $paymentIntentData): \Stripe\Event
    {
        $paymentIntent = \Stripe\PaymentIntent::constructFrom($paymentIntentData);

        $event = \Stripe\Event::constructFrom([
            'id' => 'evt_test_'.uniqid(),
            'object' => 'event',
            'type' => $type,
            'data' => ['object' => $paymentIntentData],
            'livemode' => false,
            'created' => time(),
            'api_version' => '2023-10-16',
            'pending_webhooks' => 0,
            'request' => null,
        ]);

        return $event;
    }

    private function buildControllerWithEm(\Doctrine\ORM\EntityManagerInterface $em): WebhookStripeController
    {
        $repo = $this->createStub(StripeWebhookSecretRepository::class);
        $repo->method('getSecret')->willReturn('whsec_test');

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $urlGenerator = $this->createStub(UrlGeneratorInterface::class);
        $urlGenerator->method('generate')->willReturn('http://example.com/verify');

        return new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $repo,
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $this->createStub(FactureService::class),
            $this->createStub(KernelInterface::class),
            $urlGenerator,
        );
    }

    /**
     * Teste handlePaymentSucceeded via Reflection — pas d'advert_id dans metadata.
     */
    public function testHandlePaymentSucceededNoAdvertId(): void
    {
        $em = $this->createStub(\Doctrine\ORM\EntityManagerInterface::class);
        $controller = $this->buildControllerWithEm($em);

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_test_001',
            'object' => 'payment_intent',
            'amount_received' => 12000,
            'metadata' => [],
            'payment_method_types' => ['card'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('no_advert', $response->getContent());
    }

    /**
     * Teste handlePaymentSucceeded via Reflection — advert_id present mais advert introuvable.
     */
    public function testHandlePaymentSucceededAdvertNotFound(): void
    {
        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn(null);

        $em = $this->createStub(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);

        $controller = $this->buildControllerWithEm($em);

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_test_002',
            'object' => 'payment_intent',
            'amount_received' => 12000,
            'metadata' => ['advert_id' => '999'],
            'payment_method_types' => ['card'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('advert_not_found', $response->getContent());
    }

    /**
     * Teste handlePaymentSucceeded via Reflection — advert déjà traité (already_processed).
     */
    public function testHandlePaymentSucceededAlreadyProcessed(): void
    {
        $orderNumber = new \App\Entity\OrderNumber('04/2026-00001');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');
        $advert->setState(\App\Entity\Advert::STATE_ACCEPTED);
        // Define the same PI ID as what the event carries
        $advert->setStripePaymentId('pi_test_003');

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createStub(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);

        $controller = $this->buildControllerWithEm($em);

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_test_003',
            'object' => 'payment_intent',
            'amount_received' => 12000,
            'metadata' => ['advert_id' => '1'],
            'payment_method_types' => ['card'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('already_processed', $response->getContent());
    }

    /**
     * Teste handlePaymentSucceeded via Reflection — paiement accepté avec succès.
     */
    public function testHandlePaymentSucceededAccepted(): void
    {
        $user = new \App\Entity\User();
        $user->setEmail('client@test.com');
        $user->setFirstName('Jean');
        $user->setLastName('Client');
        $user->setPassword('h');
        $customer = new \App\Entity\Customer($user);

        $orderNumber = new \App\Entity\OrderNumber('04/2026-00002');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');
        $advert->setCustomer($customer);

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->expects($this->atLeastOnce())->method('flush');

        $factureService = $this->createStub(FactureService::class);
        $factureService->method('createPaidFactureFromAdvert')->willReturn(null);

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $urlGenerator = $this->createStub(UrlGeneratorInterface::class);
        $urlGenerator->method('generate')->willReturn('http://example.com/verify');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $factureService,
            $this->createStub(KernelInterface::class),
            $urlGenerator,
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_test_004',
            'object' => 'payment_intent',
            'amount_received' => 12000,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'card'],
            'payment_method_types' => ['card'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('payment_accepted', $response->getContent());
    }

    /**
     * Teste handlePaymentSucceeded avec méthode SEPA pour couvrir les branches methodLabel.
     */
    public function testHandlePaymentSucceededSepaMethod(): void
    {
        $orderNumber = new \App\Entity\OrderNumber('04/2026-00003');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->method('flush');

        $factureService = $this->createStub(FactureService::class);
        $factureService->method('createPaidFactureFromAdvert')->willReturn(null);

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $factureService,
            $this->createStub(KernelInterface::class),
            $this->createStub(UrlGeneratorInterface::class),
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_sepa_005',
            'object' => 'payment_intent',
            'amount_received' => 5000,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'sepa_debit', 'revendeur_code' => 'REV001'],
            'payment_method_types' => ['sepa_debit'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'connect_light');

        $this->assertSame(200, $response->getStatusCode());
    }

    /**
     * Teste handlePaymentFailed via Reflection — pas d'advert_id.
     */
    public function testHandlePaymentFailedNoAdvertId(): void
    {
        $em = $this->createStub(\Doctrine\ORM\EntityManagerInterface::class);
        $controller = $this->buildControllerWithEm($em);

        $event = $this->buildStripePaymentIntentEvent('payment_intent.payment_failed', [
            'id' => 'pi_fail_001',
            'object' => 'payment_intent',
            'amount' => 12000,
            'metadata' => [],
            'payment_method_types' => ['card'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentFailed');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('no_advert', $response->getContent());
    }

    /**
     * Teste handlePaymentFailed via Reflection — advert introuvable.
     */
    public function testHandlePaymentFailedAdvertNotFound(): void
    {
        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn(null);

        $em = $this->createStub(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);

        $controller = $this->buildControllerWithEm($em);

        $event = $this->buildStripePaymentIntentEvent('payment_intent.payment_failed', [
            'id' => 'pi_fail_002',
            'object' => 'payment_intent',
            'amount' => 12000,
            'metadata' => ['advert_id' => '999'],
            'payment_method_types' => ['card'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentFailed');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('advert_not_found', $response->getContent());
    }

    /**
     * Teste handlePaymentSucceeded avec customer_balance et autres methodes de paiement.
     */
    public function testHandlePaymentSucceededCustomerBalance(): void
    {
        $orderNumber = new \App\Entity\OrderNumber('04/2026-00005');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->method('flush');

        $factureService = $this->createStub(FactureService::class);
        $factureService->method('createPaidFactureFromAdvert')->willReturn(null);

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $factureService,
            $this->createStub(KernelInterface::class),
            $this->createStub(UrlGeneratorInterface::class),
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_cb_001',
            'object' => 'payment_intent',
            'amount_received' => 10000,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'customer_balance'],
            'payment_method_types' => ['customer_balance'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('payment_accepted', $response->getContent());
    }

    /**
     * Teste handlePaymentSucceeded avec klarna/revolut_pay/amazon_pay/link methods.
     */
    public function testHandlePaymentSucceededKlarnaMethod(): void
    {
        $orderNumber = new \App\Entity\OrderNumber('04/2026-00006');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->method('flush');

        $factureService = $this->createStub(FactureService::class);
        $factureService->method('createPaidFactureFromAdvert')->willReturn(null);

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $factureService,
            $this->createStub(KernelInterface::class),
            $this->createStub(UrlGeneratorInterface::class),
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_klarna_001',
            'object' => 'payment_intent',
            'amount_received' => 8000,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'klarna'],
            'payment_method_types' => ['klarna'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_instant');

        $this->assertSame(200, $response->getStatusCode());
    }

    /**
     * Teste handlePaymentSucceeded — factureService returns a Facture (generateAndSendFacture branch).
     */
    public function testHandlePaymentSucceededWithFactureGeneration(): void
    {
        $user = new \App\Entity\User();
        $user->setEmail('gen@test.com');
        $user->setFirstName('Gen');
        $user->setLastName('Test');
        $user->setPassword('h');
        $customer = new \App\Entity\Customer($user);
        $customer->setEmail('gen@test.com');

        $orderNumber = new \App\Entity\OrderNumber('04/2026-00007');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');
        $advert->setCustomer($customer);

        // Build a real Facture for the createPaidFactureFromAdvert return
        $factureOrderNumber = new \App\Entity\OrderNumber('04/2026-F001');
        $facture = new \App\Entity\Facture($factureOrderNumber, 'hmac_secret');
        $facture->setTotalHt('100.00');
        $facture->setTotalTva('0.00');
        $facture->setTotalTtc('100.00');

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->method('flush');

        $factureService = $this->createStub(FactureService::class);
        $factureService->method('createPaidFactureFromAdvert')->willReturn($facture);

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $tmpDir = sys_get_temp_dir().'/webhook_test_'.uniqid();
        mkdir($tmpDir.'/public/uploads/factures', 0777, true);

        $kernel = $this->createStub(KernelInterface::class);
        $kernel->method('getProjectDir')->willReturn($tmpDir);

        $urlGenerator = $this->createStub(UrlGeneratorInterface::class);
        $urlGenerator->method('generate')->willReturn('http://localhost/facture/verify/1/abc');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $factureService,
            $kernel,
            $urlGenerator,
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_gen_001',
            'object' => 'payment_intent',
            'amount_received' => 10000,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'card'],
            'payment_method_types' => ['card'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('payment_accepted', $response->getContent());

        // Cleanup
        array_map('unlink', glob($tmpDir.'/public/uploads/factures/*') ?: []);
        @rmdir($tmpDir.'/public/uploads/factures');
        @rmdir($tmpDir.'/public/uploads');
        @rmdir($tmpDir.'/public');
        @rmdir($tmpDir);
    }

    /**
     * Teste handlePaymentFailed via Reflection — paiement refusé avec envoi de mails.
     */
    public function testHandlePaymentFailedWithCustomerAndMails(): void
    {
        $user = new \App\Entity\User();
        $user->setEmail('client@test.com');
        $user->setFirstName('Jean');
        $user->setLastName('Client');
        $user->setPassword('h');
        $customer = new \App\Entity\Customer($user);

        $orderNumber = new \App\Entity\OrderNumber('04/2026-00010');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');
        $advert->setCustomer($customer);

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->expects($this->once())->method('flush');

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $this->createStub(FactureService::class),
            $this->createStub(KernelInterface::class),
            $this->createStub(UrlGeneratorInterface::class),
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.payment_failed', [
            'id' => 'pi_fail_003',
            'object' => 'payment_intent',
            'amount' => 12000,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'sepa_debit'],
            'payment_method_types' => ['sepa_debit'],
            'last_payment_error' => null,
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentFailed');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'connect_instant');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('payment_failed', $response->getContent());
    }

    /**
     * Teste handlePaymentFailed avec methode paypal (autre branche du match).
     */
    public function testHandlePaymentFailedPaypalMethod(): void
    {
        $orderNumber = new \App\Entity\OrderNumber('04/2026-00011');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->method('flush');

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $this->createStub(FactureService::class),
            $this->createStub(KernelInterface::class),
            $this->createStub(UrlGeneratorInterface::class),
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.payment_failed', [
            'id' => 'pi_fail_paypal',
            'object' => 'payment_intent',
            'amount' => 5000,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'paypal', 'revendeur_code' => 'REV002'],
            'payment_method_types' => ['paypal'],
            'last_payment_error' => null,
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentFailed');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'connect_light');

        $this->assertSame(200, $response->getStatusCode());
        $this->assertStringContainsString('payment_failed', $response->getContent());
    }

    /**
     * Teste handlePaymentSucceeded avec revolut_pay method.
     */
    public function testHandlePaymentSucceededRevolutPay(): void
    {
        $orderNumber = new \App\Entity\OrderNumber('04/2026-00008');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->method('flush');

        $factureService = $this->createStub(FactureService::class);
        $factureService->method('createPaidFactureFromAdvert')->willReturn(null);

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $factureService,
            $this->createStub(KernelInterface::class),
            $this->createStub(UrlGeneratorInterface::class),
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_revolut_001',
            'object' => 'payment_intent',
            'amount_received' => 7500,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'revolut_pay'],
            'payment_method_types' => ['revolut_pay'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
    }

    /**
     * Teste handlePaymentSucceeded avec amazon_pay et link methods.
     */
    public function testHandlePaymentSucceededLinkMethod(): void
    {
        $orderNumber = new \App\Entity\OrderNumber('04/2026-00009');
        $advert = new \App\Entity\Advert($orderNumber, 'secret');

        $advertRepo = $this->createStub(\Doctrine\ORM\EntityRepository::class);
        $advertRepo->method('find')->willReturn($advert);

        $em = $this->createMock(\Doctrine\ORM\EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($advertRepo);
        $em->method('persist');
        $em->method('flush');

        $factureService = $this->createStub(FactureService::class);
        $factureService->method('createPaidFactureFromAdvert')->willReturn(null);

        $twig = $this->createStub(Environment::class);
        $twig->method('render')->willReturn('<html></html>');

        $controller = new WebhookStripeController(
            $this->createStub(LoggerInterface::class),
            $this->createStub(StripeWebhookSecretRepository::class),
            $em,
            $this->createStub(MailerService::class),
            $twig,
            $factureService,
            $this->createStub(KernelInterface::class),
            $this->createStub(UrlGeneratorInterface::class),
        );

        $event = $this->buildStripePaymentIntentEvent('payment_intent.succeeded', [
            'id' => 'pi_link_001',
            'object' => 'payment_intent',
            'amount_received' => 6000,
            'metadata' => ['advert_id' => '1', 'payment_method' => 'link'],
            'payment_method_types' => ['link'],
        ]);

        $method = new \ReflectionMethod(WebhookStripeController::class, 'handlePaymentSucceeded');
        $method->setAccessible(true);
        $response = $method->invoke($controller, $event, 'main_light');

        $this->assertSame(200, $response->getStatusCode());
    }
}
