<?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\Model\ResetPasswordRequest;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\Security\ResetPasswordType;
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\Response;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\ComponentWithFormTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;

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

    #[LiveProp]
    public string $token;

    public function __construct(
        private readonly PasswordResetService $passwordResetService,
        private readonly UserRepository $userRepository,
        private readonly TranslatorInterface $translator,
    ) {
    }

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

    #[LiveAction]
    public function validatePasswords(): void
    {
        $formName = $this->getFormName();
        $this->validatedFields = [
            $formName,
            $formName.'.plainPassword',
            $formName.'.passwordConfirmation',
        ];

        try {
            $this->submitForm(false);
        } catch (UnprocessableEntityHttpException) {
        }
    }

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

        $data = $this->form?->getData();
        if (!$data instanceof ResetPasswordRequest) {
            return null;
        }

        $user = $this->userRepository->findOneBy(['resetPasswordToken' => $this->token]);

        if (null === $user) {
            $this->addFlash('error', $this->translator->trans('security.error.reset_link_invalid', [], 'messages'));

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

        if ($this->passwordResetService->isExpired($user)) {
            $this->addFlash('error', $this->translator->trans('security.error.reset_link_expired', [], 'messages'));

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

        $user->setPlainPassword($data->getPlainPassword());
        $this->passwordResetService->clear($user);
        $this->addFlash('success', $this->translator->trans('security.success.password_updated', [], 'messages'));

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

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

        return \is_string($plainPassword)
            && '' !== mb_trim($plainPassword)
            && \is_string($passwordConfirmation)
            && '' !== mb_trim($passwordConfirmation)
            && $plainPassword === $passwordConfirmation;
    }
}
