<?php 
 
namespace App\Controller; 
 
use App\Entity\User; 
use App\Form\ChangePasswordFormType; 
use App\Form\ResetPasswordRequestFormType; 
use App\Form\RequestResetPasswordType; 
use App\Form\ResetPasswordWithSecurityQuestionType; 
use Symfony\Bridge\Twig\Mime\TemplatedEmail; 
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 
use Symfony\Component\HttpFoundation\RedirectResponse; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\Mailer\MailerInterface; 
use Symfony\Component\Mime\Address; 
use Symfony\Component\Routing\Annotation\Route; 
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; 
use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait; 
use SymfonyCasts\Bundle\ResetPassword\Exception\ResetPasswordExceptionInterface; 
use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface; 
use Doctrine\ORM\EntityManagerInterface; 
 
 
/** 
 * @Route("/reset-password") 
 */ 
class ResetPasswordController extends AbstractController 
{ 
    use ResetPasswordControllerTrait; 
 
    private $resetPasswordHelper; 
 
    public function __construct(ResetPasswordHelperInterface $resetPasswordHelper) 
    { 
        $this->resetPasswordHelper = $resetPasswordHelper; 
    } 
 
 
 
    /** 
     * Display & process form to request a password reset. 
     * 
     * @Route("", name="app_forgot_password_request") 
     */ 
    public function requestResetPassword(Request $request, EntityManagerInterface $em): Response 
    { 
        $form = $this->createForm(RequestResetPasswordType::class); 
        $form->handleRequest($request); 
 
        if ($form->isSubmitted() && $form->isValid()) { 
            $email = $form->get('email')->getData(); 
            $user = $em->getRepository(User::class)->findOneBy(['email' => $email]); 
 
            if (!$user) { 
                $this->addFlash('error', 'No user found with this email.'); 
                return $this->redirectToRoute('app_reset_password'); 
            } 
 
            // Rediriger vers l'étape de réponse à la question de sécurité 
            return $this->redirectToRoute('app_verify_security_answer', ['id' => $user->getId()]); 
        } 
 
        return $this->render('reset_password/request.html.twig', [ 
            'requestForm' => $form->createView(), 
        ]); 
    } 
    /*public function request(Request $request, MailerInterface $mailer): Response 
    { 
        $form = $this->createForm(ResetPasswordRequestFormType::class); 
        $form->handleRequest($request); 
 
        if ($form->isSubmitted() && $form->isValid()) { 
            return $this->processSendingPasswordResetEmail( 
                $form->get('email')->getData(), 
                $mailer 
            ); 
        } 
 
        return $this->render('reset_password/request.html.twig', [ 
            'requestForm' => $form->createView(), 
        ]); 
    }*/ 
 
    /** 
     * Confirmation page after a user has requested a password reset. 
     * 
     * @Route("/check-email", name="app_check_email") 
     */ 
    public function checkEmail(): Response 
    { 
        // Generate a fake token if the user does not exist or someone hit this page directly. 
        // This prevents exposing whether or not a user was found with the given email address or not 
        if (null === ($resetToken = $this->getTokenObjectFromSession())) { 
            $resetToken = $this->resetPasswordHelper->generateFakeResetToken(); 
        } 
 
        return $this->render('reset_password/check_email.html.twig', [ 
            'resetToken' => $resetToken, 
        ]); 
    } 
 
    /** 
     * Validates and process the reset URL that the user clicked in their email. 
     * 
     * @Route("/reset/{token}", name="app_reset_password") 
     */ 
    public function reset(Request $request, UserPasswordEncoderInterface $userPasswordEncoderInterface, string $token = null): Response 
    { 
        if ($token) { 
            // We store the token in session and remove it from the URL, to avoid the URL being 
            // loaded in a browser and potentially leaking the token to 3rd party JavaScript. 
            $this->storeTokenInSession($token); 
            return $this->redirectToRoute('app_reset_password'); 
        } 
 
        $token = $this->getTokenFromSession(); 
        if (null === $token) { 
            throw $this->createNotFoundException('No reset password token found in the URL or in the session.'); 
        } 
 
        try { 
            $user = $this->resetPasswordHelper->validateTokenAndFetchUser($token); 
        } catch (ResetPasswordExceptionInterface $e) { 
            $this->addFlash('reset_password_error', sprintf( 
                'There was a problem validating your reset request - %s', 
                $e->getReason() 
            )); 
 
            return $this->redirectToRoute('app_forgot_password_request'); 
        } 
 
        // The token is valid; allow the user to change their password. 
        $form = $this->createForm(ChangePasswordFormType::class); 
        $form->handleRequest($request); 
 
        if ($form->isSubmitted() && $form->isValid()) { 
            // A password reset token should be used only once, remove it. 
            $this->resetPasswordHelper->removeResetRequest($token); 
 
            // Encode(hash) the plain password, and set it. 
            $encodedPassword = $userPasswordEncoderInterface->encodePassword( 
                $user, 
                $form->get('plainPassword')->getData() 
            ); 
 
            $user->setPassword($encodedPassword); 
            $this->getDoctrine()->getManager()->flush(); 
 
            // The session is cleaned up after the password has been changed. 
            $this->cleanSessionAfterReset(); 
            $this->addFlash('success', 'Your password has been successfully reset. You can log in with the new password'); 
            return $this->redirectToRoute('app_login'); 
        } 
 
        return $this->render('reset_password/reset.html.twig', [ 
            'resetForm' => $form->createView(), 
        ]); 
    } 
 
    private function processSendingPasswordResetEmail(string $emailFormData, MailerInterface $mailer): RedirectResponse 
    { 
        $user = $this->getDoctrine()->getRepository(User::class)->findOneBy([ 
            'email' => $emailFormData, 
        ]); 
 
 
        // Do not reveal whether a user account was found or not. 
        if (!$user) { 
            return $this->redirectToRoute('app_check_email'); 
        } 
 
        try { 
            $resetToken = $this->resetPasswordHelper->generateResetToken($user); 
        } catch (ResetPasswordExceptionInterface $e) { 
            // If you want to tell the user why a reset email was not sent, uncomment 
            // the lines below and change the redirect to 'app_forgot_password_request'. 
            // Caution: This may reveal if a user is registered or not. 
            // 
            $this->addFlash('reset_password_error', sprintf( 
                'There was a problem handling your password reset request - %s', 
                $e->getReason() 
            )); 
            return $this->redirectToRoute('app_check_email'); 
        } 
 
        $email = (new TemplatedEmail()) 
            ->from(new Address( 
                $this->getParameter('app_mail_from_address'), 
                $this->getParameter('app_mail_from_name') 
            )) 
            ->to($user->getEmail()) 
            ->subject('Your password reset request') 
            ->htmlTemplate('reset_password/email.html.twig') 
            ->context([ 
                'resetToken' => $resetToken, 
                'tokenLifetime' => $this->resetPasswordHelper->getTokenLifetime(), 
            ]); 
 
        $mailer->send($email); 
        // Store the token object in session for retrieval in check-email route. 
        $this->setTokenObjectInSession($resetToken); 
        return $this->redirectToRoute('app_check_email'); 
    } 
 
      
 
    /** 
     * @Route("/verify-security-answer/{id}", name="app_verify_security_answer") 
     */ 
    public function verifySecurityAnswer(User $user, Request $request, EntityManagerInterface $em, UserPasswordEncoderInterface $passwordEncoder): Response 
    { 
        $form = $this->createForm(ResetPasswordWithSecurityQuestionType::class); 
        $form->handleRequest($request); 
 
        if ($form->isSubmitted() && $form->isValid()) { 
            $securityAnswer = $form->get('securityAnswer')->getData(); 
            // Vérification de la réponse à la question de sécurité 
            if ($user->getSecurityAnswer() !== $securityAnswer) { 
                $this->addFlash('error', 'Incorrect answer to the security question.'); 
                return $this->redirectToRoute('app_verify_security_answer', ['id' => $user->getId()]); 
            } 
            
            // Si la réponse est correcte, réinitialiser le mot de passe 
            $newPassword = $form->get('newPassword')->getData(); 
            $encodedPassword = $passwordEncoder->encodePassword($user, $newPassword); 
            $user->setPassword($encodedPassword); 
 
            $em->flush(); 
 
            $this->addFlash('success', 'Password successfully reset!'); 
            return $this->redirectToRoute('app_login'); 
        } 
 
        switch ( $user->getSecurityQuestion()) { 
            case "cin_number": 
                $securityQuestion=  'Numero de CNI?'; 
                break; 
         
            case "mother_birthplace": 
                $securityQuestion ='Quelle est la ville de naissance de maman?'; 
                break; 
         
            case "favorite_job": 
                $securityQuestion ='Le metier dont tu reves d\'exercer depuis ton enfance?'; 
                break; 
            case "residence": 
                $securityQuestion =  'Quel est ton quartier de residence?'; 
                break; 
         
            default: 
                 $securityQuestion =" Quel est le nom de l'etablisement ?"; 
                break; 
        } 
 
        return $this->render('reset_password/verify_security_answer.html.twig', [ 
            'securityQuestion' => $securityQuestion, 
            'verifyForm' => $form->createView(), 
        ]); 
    } 
}