<?php

namespace AppBundle\Controller\Legacy;

use AppBundle\Entity\Company;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserManagerInterface;
use AppBundle\Mail\NewsletterMailer;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\RouterInterface;
use AppBundle\Entity\User;
use AppBundle\Enum\UserType;
use AppBundle\Form\Type\Front\User\Legacy\RegistrationStep1FormType;
use AppBundle\Form\Type\Front\User\Legacy\RegistrationStep2IngeFormType;
use AppBundle\Form\Type\Front\User\Legacy\RegistrationStep2ProfFormType;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

/**
 *
 */
class RegistrationController extends BaseController
{
    /**
     * @var EventDispatcherInterface
     */
    private $dispatcher;

    /**
     * @var FormFactoryInterface
     */
    private $formFactory;

    /**
     * @var NewsletterMailer
     */
    private $newsletterMailer;

    /**
     * @var RouterInterface
     */
    private $router;

    /**
     * @var SessionInterface
     */
    private $session;

    /**
     * @var TokenStorageInterface
     */
    private $tokenStorage;

    /**
     * @var UserManagerInterface
     */
    private $userManager;
    
    public function __construct(
        EventDispatcherInterface $dispatcher,
        FormFactoryInterface $formFactory,
        NewsletterMailer $newsletterMailer,
        RouterInterface $router,
        SessionInterface $session,
        TokenStorageInterface $tokenStorage,
        UserManagerInterface $userManager
    )
    {
        $this->dispatcher = $dispatcher;
        $this->formFactory = $formFactory;
        $this->newsletterMailer = $newsletterMailer;
        $this->router = $router;
        $this->session = $session;
        $this->tokenStorage = $tokenStorage;
        $this->userManager = $userManager;
    }

    /**
     * Gestion du formulaire d'inscription (2 étapes) d'un utilisateur :
     * - la première étape dispose d'un type de formulaire unique.
     * - la seconde étape dispose d'un formulaire spécifique au type d'utilisateur (professeur ou ingénieur) créé.
     * Principe de fonctionnement :
     * 1. Affichage du formulaire de l'étape 1
     * 2. Lorsqu'il est soumis (POST) et valide, les données du formulaire sont stockées en session et l'utilisateur est redirigé à l'étape 2
     * 3. Lorsque le formulaire de l'étape 2 est soumis et valide, on enregistre l'utilisateur
     * @param Request $request
     * @return null|RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function registerAction(Request $request)
    {
        // Récupération de la variable de session du formulaire d'inscription
        $userSession = $this->session->get('user_registration');

        // Récupération des variables $userType et $formStep de l'URL
        $userType = $request->query->get('type');
        $formStep = $request->query->getInt('step', 1);
        if (2 === $formStep) {
            // Redirection à l'étape 1 si aucune données du formulaire d'inscription de l'étape 1 n'existe (n'est en session) :
            // cas où l'accès à l'étape 2 se fait autrement que via la soumission du formulaire de l'étape 1.
            if (null === $userSession) {
                return new RedirectResponse($this->router->generate('fos_user_registration_register', [
                    'type' => $userType,
                    'step' => 1,
                ]));
            }

            $formStep = 2;
        } else {
            $formStep = 1;
        }

        // Initialisation de l'utilisateur
        $user = $this->userManager->createUser();
        $user->setEnabled(true);
        if ('professeur' === $userType) {
            $user->setType(UserType::TEACHER);
        } else {
            $user->setType(UserType::ENGINEER);
        }
        if (null !== $userSession) {
            $user->setUsername($userSession['username']);
            $user->setFirstname($userSession['firstname']);
            $user->setLastname($userSession['lastname']);
            $user->setEmail($userSession['email']);
            $user->setPlainPassword($userSession['plainPassword']);
            $user->setBirthday($userSession['birthday']);
            $user->setPhone($userSession['phone']);
            $user->setMobile($userSession['mobile']);
        }

        $event = new GetResponseUserEvent($user, $request);
        $this->dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);

        if (1 === $formStep) {
            $form = $this->prepareRegistrationFormStep1($user, $userType);
            $form->setData($user);

            $form->handleRequest($request);

            if ($form->isSubmitted() && $form->isValid()) {
                $formData = $form->getData();

                // Sauvegarde des données du formulaire de l'étape 1 en session
                $this->session->set('user_registration', [
                    'username'      => $formData->getUsername(),
                    'firstname'     => $formData->getFirstname(),
                    'lastname'      => $formData->getLastname(),
                    'email'         => $formData->getEmail(),
                    'plainPassword' => $formData->getPlainPassword(),
                    'birthday'      => $formData->getBirthday(),
                    'phone'         => $formData->getPhone(),
                    'mobile'        => $formData->getMobile(),
                ]);

                // Redirection de l'utilisateur à l'étpae 2
                return new RedirectResponse($this->router->generate('fos_user_registration_register', [
                    'type' => $userType,
                    'step' => 2,
                ]));
            }
        } else { // $formStep === 2
            $form = $this->prepareRegistrationFormStep2($user, $userType);

            $form->handleRequest($request);

            // Le formulaire est valide, l'utilisateur est créé
            if ($form->isSubmitted() && $form->isValid()) {
                // If the enginner set a custom company, first check if it does not already exists.
                // If not, then create it.
                if (UserType::ENGINEER === $user->getType() && $companyNameOther = $form->get('establishmentNameOther')->getData()) {
                    $em = $this->getDoctrine()->getManager();
                    $company = $em->getRepository(Company::class)->findOneByName($companyNameOther);

                    if (!$company && $companyNameOther != "") {
                        $company = new Company();
                        $company->setName($companyNameOther);
                        $company->setAvailableForUsers(true);

                        $em->persist($company);
                        $em->flush();
                    }

                    $user->setEstablishment($company);
                }
                
                $this->session->remove('user_registration'); // Suppression des données de session

                $event = new FormEvent($form, $request);
                $this->dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

                $this->userManager->updateUser($user);

                // Inscription à la newsletter
                $this->newsletterMailer->subscribe($user);

                if (null === $response = $event->getResponse()) {
                    $url = $this->generateUrl('fos_user_registration_confirmed');
                    $response = new RedirectResponse($url);
                }

                $this->dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

                return $response;
            }
        }

        return $this->render('FOSUserBundle:Registration:register.html.twig', [
            'form' => $form->createView(),
            'step' => $formStep,
            'type' => $userType,
        ]);
    }
    
    /**
     *
     * @param User $user
     * @param string $userType
     * @return \Symfony\Component\Form\FormInterface
     */
    private function prepareRegistrationFormStep1(User $user, string $userType): FormInterface
    {
        return $this->formFactory->create(RegistrationStep1FormType::class, $user, [
            'action' => $this->generateUrl('fos_user_registration_register', [
                'type' => $userType,
                'step' => 1,
            ])
        ]);
    }


    /**
     *
     * @param User $user
     * @param string $userType
     * @return \Symfony\Component\Form\FormInterface
     */
    private function prepareRegistrationFormStep2(User $user, string $userType): FormInterface
    {
        $formTypeClassname = UserType::TEACHER === $user->getType()
            ? RegistrationStep2ProfFormType::class
            : RegistrationStep2IngeFormType::class
        ;

        return $this->formFactory->create($formTypeClassname, $user, [
            'action' => $this->generateUrl('fos_user_registration_register', [
                'type' => $userType,
                'step' => 2,
            ])
        ]);
    }
}
