<?php

namespace App\Tests\Service\ResetPassword;

use App\Entity\Account;
use App\Entity\AccountResetPasswordRequest;
use App\Service\Mailer\Mailer;
use App\Service\ResetPassword\Event\ResetPasswordEvent;
use App\Service\ResetPassword\ResetPasswordSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class ResetPasswordSubscriberTest extends TestCase
{
    public function testOnResetPasswordAccountNotFound(): void
    {
        $urlGenerator = $this->createStub(UrlGeneratorInterface::class);
        $entityManager = $this->createStub(EntityManagerInterface::class);
        $mailer = $this->createMock(Mailer::class);
        $requestStack = $this->createStub(RequestStack::class);

        $subscriber = new ResetPasswordSubscriber($urlGenerator, $entityManager, $mailer, $requestStack);

        $event = new ResetPasswordEvent();
        $event->setEmail('unknown@example.com');

        $repo = $this->createStub(EntityRepository::class);
        $entityManager->method('getRepository')->with(Account::class)->willReturn($repo);
        $repo->method('findOneBy')->with(['email' => 'unknown@example.com'])->willReturn(null);

        $mailer->expects($this->never())->method('send');

        $subscriber->onResetPassword($event);
    }

    public function testOnResetPasswordSuccess(): void
    {
        $urlGenerator = $this->createStub(UrlGeneratorInterface::class);
        $entityManager = $this->createMock(EntityManagerInterface::class);
        $mailer = $this->createMock(Mailer::class);
        $requestStack = $this->createStub(RequestStack::class);

        $subscriber = new ResetPasswordSubscriber($urlGenerator, $entityManager, $mailer, $requestStack);

        $event = new ResetPasswordEvent();
        $event->setEmail('user@example.com');

        $account = $this->createStub(Account::class);
        $account->method('getEmail')->willReturn('user@example.com');
        $account->method('getUsername')->willReturn('user');
        $account->method('getId')->willReturn(1);

        $repoAccount = $this->createStub(EntityRepository::class);
        $repoRequest = $this->createStub(EntityRepository::class);

        $entityManager->method('getRepository')->willReturnMap([
            [Account::class, $repoAccount],
            [AccountResetPasswordRequest::class, $repoRequest],
        ]);

        $repoAccount->method('findOneBy')->with(['email' => 'user@example.com'])->willReturn($account);
        $repoRequest->method('findOneBy')->with(['Account' => $account])->willReturn(null);

        $entityManager->expects($this->once())->method('persist')->with($this->isInstanceOf(AccountResetPasswordRequest::class));
        $entityManager->expects($this->once())->method('flush');

        $urlGenerator->method('generate')->willReturn('http://reset-link');

        $mailer->expects($this->once())->method('send');

        $subscriber->onResetPassword($event);
    }
}
