<?php

namespace App\Tests\Controller;

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

class ForgotPasswordControllerTest extends WebTestCase
{
    public function testPageReturnsSuccess(): void
    {
        $client = static::createClient();
        $client->request('GET', '/mot-de-passe-oublie');

        self::assertResponseIsSuccessful();
    }

    public function testEmailStepWithEmptyEmail(): void
    {
        $client = static::createClient();
        $client->request('POST', '/mot-de-passe-oublie', [
            'step' => 'email',
            'email' => '',
        ]);

        self::assertResponseIsSuccessful();
    }

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

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

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

        $client->request('POST', '/mot-de-passe-oublie', [
            'step' => 'email',
            'email' => $user->getEmail(),
        ]);

        self::assertResponseIsSuccessful();

        $em->refresh($user);
        self::assertNotNull($user->getResetCode());
        self::assertNotNull($user->getResetCodeExpiresAt());
    }

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

        $user = new User();
        $user->setEmail('test-sso-'.uniqid().'@example.com');
        $user->setFirstName('SSO');
        $user->setLastName('User');
        $user->setPassword('');
        $user->setKeycloakId('kc-'.uniqid());
        $em->persist($user);
        $em->flush();

        $client->request('POST', '/mot-de-passe-oublie', [
            'step' => 'email',
            'email' => $user->getEmail(),
        ]);

        self::assertResponseIsSuccessful();

        $em->refresh($user);
        self::assertNull($user->getResetCode());
    }

    public function testEmailStepWithUnknownEmailDoesNotReveal(): void
    {
        $client = static::createClient();
        $client->request('POST', '/mot-de-passe-oublie', [
            'step' => 'email',
            'email' => 'unknown-'.uniqid().'@example.com',
        ]);

        self::assertResponseIsSuccessful();
    }

    public function testCodeStepWithEmptyFields(): void
    {
        $client = static::createClient();
        $client->request('POST', '/mot-de-passe-oublie', [
            'step' => 'code',
            'email' => 'test@example.com',
            'code' => '',
            'password' => '',
        ]);

        self::assertResponseIsSuccessful();
    }

    public function testCodeStepWithInvalidCode(): void
    {
        $client = static::createClient();
        $client->request('POST', '/mot-de-passe-oublie', [
            'step' => 'code',
            'email' => 'test@example.com',
            'code' => '000000',
            'password' => 'NewPassword123!',
        ]);

        self::assertResponseIsSuccessful();
    }

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

        $user = new User();
        $user->setEmail('test-expired-'.uniqid().'@example.com');
        $user->setFirstName('Test');
        $user->setLastName('User');
        $user->setPassword('$2y$13$hashed');
        $user->setResetCode('123456');
        $user->setResetCodeExpiresAt(new \DateTimeImmutable('-1 hour'));
        $em->persist($user);
        $em->flush();

        $client->request('POST', '/mot-de-passe-oublie', [
            'step' => 'code',
            'email' => $user->getEmail(),
            'code' => '123456',
            'password' => 'NewPassword123!',
        ]);

        self::assertResponseIsSuccessful();
    }

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

        $user = new User();
        $user->setEmail('test-reset-'.uniqid().'@example.com');
        $user->setFirstName('Test');
        $user->setLastName('User');
        $user->setPassword('$2y$13$hashed');
        $user->setResetCode('654321');
        $user->setResetCodeExpiresAt(new \DateTimeImmutable('+15 minutes'));
        $em->persist($user);
        $em->flush();

        $client->request('POST', '/mot-de-passe-oublie', [
            'step' => 'code',
            'email' => $user->getEmail(),
            'code' => '654321',
            'password' => 'NewPassword123!',
        ]);

        self::assertResponseRedirects('/connexion');

        $em->refresh($user);
        self::assertNull($user->getResetCode());
        self::assertNull($user->getResetCodeExpiresAt());
        self::assertNotSame('$2y$13$hashed', $user->getPassword());
    }
}
