<?php

namespace App\Service\ResetPassword;

use App\Entity\Account;
use App\Entity\AccountResetPasswordRequest;
use App\Service\Generator\TempPasswordGenerator;
use App\Service\Mailer\Mailer;
use App\Service\ResetPassword\Event\ResetPasswordEvent;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

#[AsEventListener(event: ResetPasswordEvent::class, method: 'onResetPassword')]
class ResetPasswordSubscriber
{
    public function __construct(
        private readonly UrlGeneratorInterface $urlGenerator,
        private readonly EntityManagerInterface $entityManager,
        private readonly Mailer $mailer,
        private readonly RequestStack $requestStack,
    ) {
    }

    public function onResetPassword(ResetPasswordEvent $resetPasswordEvent): void
    {
        $email = $resetPasswordEvent->getEmail();
        $account = $this->entityManager->getRepository(Account::class)->findOneBy(['email' => $email]);

        if (!$account instanceof Account) {
            return;
        }

        $existingRequest = $this->entityManager->getRepository(AccountResetPasswordRequest::class)
            ->findOneBy(['Account' => $account]);

        $now = new \DateTimeImmutable();
        $sendNewRequest = true;
        $request = null;

        if ($existingRequest instanceof AccountResetPasswordRequest) {
            $expiredAt = $existingRequest->getExpiresAt();
            if ($expiredAt < $now) {
                $this->entityManager->remove($existingRequest);
            } else {
                $sendNewRequest = false;
                $request = $existingRequest;
            }
        }

        if ($sendNewRequest) {
            $expiredAt = $now->modify('+1 hour');

            $request = new AccountResetPasswordRequest();
            $request->setAccount($account);
            $request->setToken(TempPasswordGenerator::generate(50, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'));
            $request->setRequestedAt($now);
            $request->setExpiresAt($expiredAt);

            $this->entityManager->persist($request);
            $this->entityManager->flush();
        }

        $resetLink = $this->urlGenerator->generate(
            'app_forgot_password_confirm',
            ['id' => $account->getId(), 'token' => $request->getToken()],
            UrlGeneratorInterface::ABSOLUTE_URL
        );

        $this->mailer->send(
            $account->getEmail(),
            $account->getUsername(),
            '[E-Cosplay] - Lien pour réinitialiser votre mot de passe',
            'mails/reset.twig',
            [
                'account' => $account,
                'request' => $request,
                'resetLink' => $resetLink,
            ]
        );
    }
}
