<?php

namespace App\Tests\Controller;

use App\Entity\User;
use App\Service\MailerService;
use App\Service\MeilisearchService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class RegistrationControllerTest extends WebTestCase
{
    public function testRegistrationRedirectsWhenAuthenticated(): void
    {
        $client = static::createClient();
        $em = static::getContainer()->get(EntityManagerInterface::class);

        $user = new User();
        $user->setEmail('test-reg-auth-'.uniqid().'@example.com');
        $user->setFirstName('Test');
        $user->setLastName('User');
        $user->setPassword('$2y$13$hashed');
        $em->persist($user);
        $em->flush();

        $client->loginUser($user);
        $client->request('GET', '/inscription');

        self::assertResponseRedirects();
    }

    public function testRegistrationPageReturnsSuccess(): void
    {
        $client = static::createClient();
        $client->request('GET', '/inscription');

        self::assertResponseIsSuccessful();
    }

    public function testRegistrationWithValidDataSendsVerificationEmail(): void
    {
        $client = static::createClient();

        $mailer = $this->createMock(MailerService::class);
        $mailer->expects(self::once())->method('sendEmail');
        static::getContainer()->set(MailerService::class, $mailer);

        $client->request('POST', '/inscription', [
            'first_name' => 'Jean',
            'last_name' => 'Dupont',
            'email' => 'test-register-'.uniqid().'@example.com',
            'password' => 'Password123!',
        ]);

        self::assertResponseIsSuccessful();
        self::assertSelectorTextContains('h1', 'Compte cree');
    }

    public function testRegistrationAsOrganizer(): void
    {
        $client = static::createClient();

        $mailer = $this->createMock(MailerService::class);
        $mailer->expects(self::once())->method('sendEmail');
        static::getContainer()->set(MailerService::class, $mailer);

        $client->request('POST', '/inscription', [
            'type' => 'organizer',
            'first_name' => 'Marie',
            'last_name' => 'Martin',
            'email' => 'test-orga-'.uniqid().'@example.com',
            'password' => 'Password123!',
            'company_name' => 'Mon Association',
            'siret' => '12345678901234',
            'address' => '12 rue de la Paix',
            'postal_code' => '75001',
            'city' => 'Paris',
            'phone' => '0612345678',
        ]);

        self::assertResponseIsSuccessful();
        self::assertSelectorTextContains('h1', 'Compte cree');
        self::assertSelectorTextContains('body', '48h');
    }

    public function testRegistrationWithDuplicateEmail(): void
    {
        $email = 'duplicate-'.uniqid().'@example.com';

        $client = static::createClient();

        $mailer = $this->createMock(MailerService::class);
        static::getContainer()->set(MailerService::class, $mailer);

        $client->request('POST', '/inscription', [
            'first_name' => 'Jean',
            'last_name' => 'Dupont',
            'email' => $email,
            'password' => 'Password123!',
        ]);

        $client->request('POST', '/inscription', [
            'first_name' => 'Marie',
            'last_name' => 'Martin',
            'email' => $email,
            'password' => 'Password456!',
        ]);

        self::assertResponseIsSuccessful();
    }

    public function testVerifyEmailWithValidToken(): void
    {
        $client = static::createClient();
        $em = static::getContainer()->get(EntityManagerInterface::class);

        $meilisearch = $this->createMock(MeilisearchService::class);
        static::getContainer()->set(MeilisearchService::class, $meilisearch);

        $user = new User();
        $user->setEmail('test-verify-'.uniqid().'@example.com');
        $user->setFirstName('Test');
        $user->setLastName('User');
        $user->setPassword('$2y$13$hashed');
        $user->setEmailVerificationToken('valid-token-'.uniqid());
        $em->persist($user);
        $em->flush();

        $token = $user->getEmailVerificationToken();
        $client->request('GET', '/verification-email/'.$token);

        self::assertResponseIsSuccessful();
        self::assertSelectorTextContains('h1', 'Email verifie');

        $em->refresh($user);
        self::assertTrue($user->isVerified());
        self::assertNotNull($user->getEmailVerifiedAt());
        self::assertNull($user->getEmailVerificationToken());
    }

    public function testVerifyEmailOrganizerSendsNotificationEmails(): void
    {
        $client = static::createClient();
        $em = static::getContainer()->get(EntityManagerInterface::class);

        $mailer = $this->createMock(MailerService::class);
        $mailer->expects(self::exactly(2))->method('sendEmail');
        static::getContainer()->set(MailerService::class, $mailer);

        $meilisearch = $this->createMock(MeilisearchService::class);
        static::getContainer()->set(MeilisearchService::class, $meilisearch);

        $user = new User();
        $user->setEmail('test-orga-verify-'.uniqid().'@example.com');
        $user->setFirstName('Marie');
        $user->setLastName('Martin');
        $user->setPassword('$2y$13$hashed');
        $user->setRoles(['ROLE_ORGANIZER']);
        $user->setCompanyName('Mon Asso');
        $user->setSiret('12345678901234');
        $user->setAddress('12 rue de la Paix');
        $user->setPostalCode('75001');
        $user->setCity('Paris');
        $user->setPhone('0612345678');
        $user->setEmailVerificationToken('orga-token-'.uniqid());
        $em->persist($user);
        $em->flush();

        $token = $user->getEmailVerificationToken();
        $client->request('GET', '/verification-email/'.$token);

        self::assertResponseIsSuccessful();
        self::assertSelectorTextContains('body', '48h');
    }

    public function testVerifyEmailWithInvalidToken(): void
    {
        $client = static::createClient();
        $client->request('GET', '/verification-email/invalid-token');

        self::assertResponseRedirects('/connexion');
    }
}
