<?php

namespace App\Tests\Controller;

use App\Service\RgpdService;
use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class LegalControllerTest extends WebTestCase
{
    #[DataProvider('provideLegalRoutes')]
    public function testLegalPages(string $url): void
    {
        $client = static::createClient();
        $client->request('GET', $url);

        $this->assertResponseIsSuccessful();
    }

    public static function provideLegalRoutes(): iterable
    {
        yield ['/legal/mention-legal'];
        yield ['/legal/conditions-general-utilisation'];
        yield ['/legal/conditions-general-de-vente'];
        yield ['/legal/cookie'];
        yield ['/legal/hebergement'];
        yield ['/legal/conformite'];
        yield ['/legal/tarif'];
        yield ['/legal/rgpd'];
    }

    public function testRgpdAccessValidation(): void
    {
        $client = static::createClient();
        $client->request('POST', '/legal/rgpd/acces', [
            'ip' => '',
            'email' => '',
        ]);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');
        
        $client->followRedirect();
        $this->assertSelectorTextContains('.border-red-300', 'Veuillez remplir tous les champs.');
    }

    public function testRgpdAccessSuccess(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->expects($this->once())
            ->method('sendVerificationCode')
            ->with('test@example.com', '127.0.0.1', 'access');

        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/acces', [
            'ip' => '127.0.0.1',
            'email' => 'test@example.com',
        ]);

        $this->assertResponseRedirects('/legal/rgpd/verify?type=access&email=test@example.com&ip=127.0.0.1');
    }

    public function testRgpdAccessNotFound(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->expects($this->once())
            ->method('sendVerificationCode')
            ->with('test@example.com', '127.0.0.1', 'access');

        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/acces', [
            'ip' => '127.0.0.1',
            'email' => 'test@example.com',
        ]);

        $this->assertResponseRedirects('/legal/rgpd/verify?type=access&email=test@example.com&ip=127.0.0.1');
    }

    public function testRgpdAccessError(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->expects($this->once())
            ->method('sendVerificationCode')
            ->with('test@example.com', '127.0.0.1', 'access');

        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/acces', [
            'ip' => '127.0.0.1',
            'email' => 'test@example.com',
        ]);

        $this->assertResponseRedirects('/legal/rgpd/verify?type=access&email=test@example.com&ip=127.0.0.1');
    }

    public function testRgpdDeletionValidation(): void
    {
        $client = static::createClient();
        $client->request('POST', '/legal/rgpd/suppression', [
            'ip' => '',
            'email' => '',
        ]);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');

        $client->followRedirect();
        $this->assertSelectorTextContains('.border-red-300', 'Veuillez remplir tous les champs.');
    }

    public function testRgpdDeletionSuccess(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->expects($this->once())
            ->method('sendVerificationCode')
            ->with('test@example.com', '127.0.0.1', 'deletion');

        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/suppression', [
            'ip' => '127.0.0.1',
            'email' => 'test@example.com',
        ]);

        $this->assertResponseRedirects('/legal/rgpd/verify?type=deletion&email=test@example.com&ip=127.0.0.1');
    }

    public function testRgpdDeletionNotFound(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->expects($this->once())
            ->method('sendVerificationCode')
            ->with('test@example.com', '127.0.0.1', 'deletion');

        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/suppression', [
            'ip' => '127.0.0.1',
            'email' => 'test@example.com',
        ]);

        $this->assertResponseRedirects('/legal/rgpd/verify?type=deletion&email=test@example.com&ip=127.0.0.1');
    }

    public function testRgpdDeletionError(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->expects($this->once())
            ->method('sendVerificationCode')
            ->with('test@example.com', '127.0.0.1', 'deletion');

        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/suppression', [
            'ip' => '127.0.0.1',
            'email' => 'test@example.com',
        ]);

        $this->assertResponseRedirects('/legal/rgpd/verify?type=deletion&email=test@example.com&ip=127.0.0.1');
    }

    public function testRgpdVerifyGetShowsForm(): void
    {
        $client = static::createClient();
        $client->request('GET', '/legal/rgpd/verify', [
            'type' => 'access',
            'email' => 'test@example.com',
            'ip' => '127.0.0.1',
        ]);

        $this->assertResponseIsSuccessful();
    }

    public function testRgpdVerifyGetMissingParams(): void
    {
        $client = static::createClient();
        $client->request('GET', '/legal/rgpd/verify', []);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');
    }

    public function testRgpdVerifyPostInvalidCode(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->method('verifyCode')->willReturn(false);
        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/verify', [
            'type' => 'access',
            'email' => 'test@example.com',
            'ip' => '127.0.0.1',
            'code' => 'BADCODE',
        ]);

        $this->assertResponseIsSuccessful();
    }

    public function testRgpdVerifyPostValidAccessCode(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->method('verifyCode')->willReturn(true);
        $rgpdService->method('handleAccessRequest')->willReturn(['found' => true]);
        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/verify', [
            'type' => 'access',
            'email' => 'test@example.com',
            'ip' => '127.0.0.1',
            'code' => 'VALIDCODE',
        ]);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');
    }

    public function testRgpdVerifyPostValidDeletionCode(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->method('verifyCode')->willReturn(true);
        $rgpdService->method('handleDeletionRequest')->willReturn(['found' => false]);
        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/verify', [
            'type' => 'deletion',
            'email' => 'test@example.com',
            'ip' => '127.0.0.1',
            'code' => 'VALIDCODE',
        ]);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');
    }

    public function testRgpdVerifyPostHandlerThrows(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->method('verifyCode')->willReturn(true);
        $rgpdService->method('handleAccessRequest')->willThrowException(new \RuntimeException('Service down'));
        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/verify', [
            'type' => 'access',
            'email' => 'test@example.com',
            'ip' => '127.0.0.1',
            'code' => 'CODE',
        ]);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');
    }

    public function testRgpdVerifyPostValidAccessCodeNotFound(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->method('verifyCode')->willReturn(true);
        $rgpdService->method('handleAccessRequest')->willReturn(['found' => false]);
        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/verify', [
            'type' => 'access',
            'email' => 'test@example.com',
            'ip' => '127.0.0.1',
            'code' => 'VALIDCODE',
        ]);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');
    }

    public function testRgpdVerifyPostValidDeletionCodeFound(): void
    {
        $client = static::createClient();
        $rgpdService = $this->createMock(RgpdService::class);
        $rgpdService->method('verifyCode')->willReturn(true);
        $rgpdService->method('handleDeletionRequest')->willReturn(['found' => true]);
        static::getContainer()->set(RgpdService::class, $rgpdService);

        $client->request('POST', '/legal/rgpd/verify', [
            'type' => 'deletion',
            'email' => 'test@example.com',
            'ip' => '127.0.0.1',
            'code' => 'VALIDCODE',
        ]);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');
    }

    public function testRgpdVerifyPostMissingParams(): void
    {
        $client = static::createClient();
        $client->request('POST', '/legal/rgpd/verify', [
            'type' => '',
            'email' => '',
            'ip' => '',
            'code' => 'CODE',
        ]);

        $this->assertResponseRedirects('/legal/rgpd#exercer-droits');
    }
}
