<?php

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\Components\Security;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\Security\ForgotPasswordType;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\Security\Model\ForgotPasswordRequest;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Security\PasswordResetService;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\Components\Behavior\HasTemplateOverride;
use CpCreation\VitiCore\User\Repository\UserRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\ComponentWithFormTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;

#[AsLiveComponent('security:ForgotPasswordForm', template: '@components/security/ForgotPasswordForm.html.twig')]
final class ForgotPasswordForm extends AbstractController
{
    use ComponentWithFormTrait;
    use DefaultActionTrait;
    use HasTemplateOverride;

    private const SESSION_RESET_PENDING_EMAIL = 'security.reset_pending.email';

    public function __construct(
        private readonly UserRepository $userRepository,
        private readonly PasswordResetService $passwordResetService,
        private readonly RequestStack $requestStack,
    ) {
    }

    protected function instantiateForm(): FormInterface
    {
        return $this->createForm(ForgotPasswordType::class, new ForgotPasswordRequest());
    }

    #[LiveAction]
    public function submitForgotPassword(): ?Response
    {
        try {
            $this->submitForm();
        } catch (UnprocessableEntityHttpException) {
            return null;
        }

        $data = $this->form?->getData();
        if ($data instanceof ForgotPasswordRequest) {
            $email = $this->normalizeEmail($data->getEmail());
            $user = $this->userRepository->findOneBy(['email' => $email]);

            if (null !== $user) {
                $this->passwordResetService->sendResetEmail($user);
            }

            $this->getSession()?->set(self::SESSION_RESET_PENDING_EMAIL, $email);
        }

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

    public function canSubmit(): bool
    {
        $email = $this->formValues['email'] ?? null;

        return \is_string($email) && false !== filter_var($email, \FILTER_VALIDATE_EMAIL);
    }

    private function getSession(): ?SessionInterface
    {
        return $this->requestStack->getCurrentRequest()?->getSession();
    }

    private function normalizeEmail(?string $email): string
    {
        return mb_strtolower(mb_trim((string) $email));
    }
}
