<?php

namespace AppBundle\Security;

use AppBundle\Entity\Ban;
use AppBundle\Form\Security\LoginForm;
use AppBundle\Service\LogService;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
//use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;

class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
    private $formFactory;
    private $em;
    private $router;
    private $passwordEncoder;
    private $session;
    private $ipUser;

    public function __construct(/*SessionInterface $session, */FormFactoryInterface $formFactory, EntityManagerInterface $em, RouterInterface $router, UserPasswordEncoderInterface $passwordEncoder)
    {
        $this->formFactory = $formFactory;
        $this->em = $em;
        $this->router = $router;
        $this->passwordEncoder = $passwordEncoder;
//        $this->session = $session;
    }

    public function getCredentials(Request $request)
    {
        $this->session = $request->getSession();
        $isLoginSubmit = $request->getPathInfo() == '/connexion' && $request->isMethod('POST');

        if(!$isLoginSubmit) {
            return;
        }

        $ip = $request->getClientIp();
        $this->ipUser = $ip;
        $ban = $this->em->getRepository("AppBundle:Ban")->findBy([
            'ip' => $ip
        ], [ 'dateFinBan' => 'desc' ]);

        foreach ($ban as $b) {
            if ($b->getDateFinBan() > new DateTime()) {

                $this->session->getFlashBag()->add('error', "Vous avez effectué trop de tentatives de connexion. Votre compte a été bloqué, réessayez dans 3 minutes.");
                return;
            } else {
                $this->em->remove($b);
                $this->em->flush();
            }
        }

        $attemps = $this->session->get('AUTH_ATTEMPTS');
        
        /*
        if ($attemps >= 3 ) {
            $fin = new \DateTime();
            $ban = new Ban($ip, $fin->add(new \DateInterval('PT'. 3 .'M')));
            $this->em->persist($ban);
            $this->em->flush();
            $this->session->set('AUTH_ATTEMPTS', 0);
            $this->session->getFlashBag()->add('error', "Vous avez effectué trop de tentatives de connexion. Votre compte a été bloqué, réessayez dans 3 minutes.");
            return;
        }
        */

        $form = $this->formFactory->create(LoginForm::class);
        $form->handleRequest($request);
        $data = $form->getData();

        $request->getSession()->set(
            Security::LAST_USERNAME,
            $data['_username']
        );

        $isValid = $this->em->getRepository('AppBundle:Utilisateur')->isValid($data['_username']);
        if($isValid == false) throw new AuthenticationException();


        return $data;
    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $username = $credentials['_username'];

        return $this->em->getRepository("AppBundle:Utilisateur")->findOneBy(['email' => $username]);
    }

    public function checkCredentials($credentials, UserInterface $user)
    {
        $password = $credentials['_password'];

        if ($this->passwordEncoder->isPasswordValid($user, $password)) {

            $log = new LogService($this->em);
            $log->logHistoNow("Connexion", 'Utilisateur', "Login utilisateur", $user);
            $this->session->set('AUTH_ATTEMPTS', 0);

            return true;
        } else {
            $attemps = $this->session->get('AUTH_ATTEMPTS');
            if ($attemps) {
                $this->session->set('AUTH_ATTEMPTS', $attemps+1);
                $attemps++;
            } else {
                $attemps=1;
                $this->session->set('AUTH_ATTEMPTS', 1);
            }
        }


        if ($attemps == 2) {
            $this->session->getFlashBag()->add('warning', "Dernier essai avant bloquage du compte pour 3 minutes.");
        }



        if ($attemps == 3) {
            $fin = new \DateTime();
            $ban = new Ban($this->ipUser, $fin->add(new \DateInterval('PT'. 3 .'M')));
            $this->em->persist($ban);
            $this->em->flush();
            $this->session->set('AUTH_ATTEMPTS', 0);
            $this->session->getFlashBag()->add('error', "Vous avez effectué trop de tentatives de connexion. Votre compte a été bloqué, réessayez dans 3 minutes.");
                    }
        return false;
    }

    protected function getLoginUrl()
    {
        return $this->router->generate('security_login');
    }

    protected function getDefaultSuccessRedirectUrl()
    {
        return $this->router->generate('homepage');
    }


}