<?php

namespace App\Controller;

use App\Entity\User;
use App\Service\MailerService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route;

class ForgotPasswordController extends AbstractController
{
    private const TEMPLATE = 'security/forgot_password.html.twig';
    private const CODE_EXPIRATION_MINUTES = 15;
    private const BREADCRUMBS = [
        ['name' => 'Accueil', 'url' => '/'],
        ['name' => 'Mot de passe oublie', 'url' => '/mot-de-passe-oublie'],
    ];

    #[Route('/mot-de-passe-oublie', name: 'app_forgot_password', methods: ['GET', 'POST'])]
    public function index(
        Request $request,
        EntityManagerInterface $em,
        MailerService $mailerService,
        UserPasswordHasherInterface $passwordHasher,
    ): Response {
        $step = $request->request->getString('step', 'email');
        $email = $request->request->getString('email', $request->getSession()->get('reset_email', ''));

        if ($request->isMethod('POST')) {
            if ('email' === $step) {
                return $this->handleEmailStep($request, $em, $mailerService, $email);
            }

            if ('code' === $step) {
                return $this->handleCodeStep($request, $em, $passwordHasher, $email);
            }
        }

        return $this->render(self::TEMPLATE, [
            'step' => 'email',
            'email' => '',
            'breadcrumbs' => self::BREADCRUMBS,
        ]);
    }

    private function handleEmailStep(Request $request, EntityManagerInterface $em, MailerService $mailerService, string $email): Response
    {
        $email = trim($email);

        if ('' === $email) {
            $this->addFlash('error', 'Veuillez saisir votre adresse email.');

            return $this->render(self::TEMPLATE, [
                'step' => 'email',
                'email' => $email,
                'breadcrumbs' => self::BREADCRUMBS,
            ]);
        }

        $user = $em->getRepository(User::class)->findOneBy(['email' => $email]);

        if ($user && null === $user->getKeycloakId()) {
            $code = str_pad((string) random_int(0, 999999), 6, '0', \STR_PAD_LEFT);
            $user->setResetCode($code);
            $user->setResetCodeExpiresAt(new \DateTimeImmutable(sprintf('+%d minutes', self::CODE_EXPIRATION_MINUTES)));
            $em->flush();

            $html = $this->renderView('email/reset_code.html.twig', [
                'firstName' => $user->getFirstName(),
                'code' => $code,
                'expirationMinutes' => self::CODE_EXPIRATION_MINUTES,
            ]);

            $mailerService->sendEmail(
                to: $email,
                subject: 'Votre code de reinitialisation - E-Ticket',
                content: $html,
                withUnsubscribe: false,
            );
        }

        $request->getSession()->set('reset_email', $email);
        $this->addFlash('success', 'Si un compte existe avec cet email, un code vous a ete envoye.');

        return $this->render(self::TEMPLATE, [
            'step' => 'code',
            'email' => $email,
            'breadcrumbs' => self::BREADCRUMBS,
        ]);
    }

    private function handleCodeStep(Request $request, EntityManagerInterface $em, UserPasswordHasherInterface $passwordHasher, string $email): Response
    {
        $code = trim($request->request->getString('code'));
        $password = $request->request->getString('password');

        if ('' === $code || '' === $password) {
            $this->addFlash('error', 'Veuillez remplir tous les champs.');

            return $this->render(self::TEMPLATE, [
                'step' => 'code',
                'email' => $email,
            ]);
        }

        $user = $em->getRepository(User::class)->findOneBy([
            'email' => $email,
            'resetCode' => $code,
        ]);

        if (!$user || !$user->getResetCodeExpiresAt() || $user->getResetCodeExpiresAt() < new \DateTimeImmutable()) {
            $this->addFlash('error', 'Code invalide ou expire.');

            return $this->render(self::TEMPLATE, [
                'step' => 'code',
                'email' => $email,
            ]);
        }

        $user->setPassword($passwordHasher->hashPassword($user, $password));
        $user->setResetCode(null);
        $user->setResetCodeExpiresAt(null);
        $em->flush();

        $request->getSession()->remove('reset_email');
        $this->addFlash('success', 'Mot de passe modifie avec succes. Vous pouvez vous connecter.');

        return $this->redirectToRoute('app_login');
    }
}
