<?php

namespace Lc\SovBundle\Authenticator;

use Lc\SovBundle\Builder\User\UserBuilder;
use Lc\SovBundle\Container\User\UserContainer;
use Lc\SovBundle\Model\User\UserInterface;
use Lc\SovBundle\Repository\User\UserStore;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;

class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
    use TargetPathTrait;

    public const LOGIN_ROUTE = 'sov_login';

    protected UrlGeneratorInterface $urlGenerator;
    protected UserStore $userStore;
    protected UserBuilder $userBuilder;
    protected FormFactoryInterface $formFactory;
    protected ParameterBagInterface $parameterBag;

    public function __construct(
            UrlGeneratorInterface $urlGenerator,
            UserContainer $userContainer,
            FormFactoryInterface $formFactory,
            ParameterBagInterface $parameterBag
    ) {
        $this->urlGenerator = $urlGenerator;
        $this->userStore = $userContainer->getStore();
        $this->userBuilder = $userContainer->getBuilder();
        $this->formFactory = $formFactory;
        $this->parameterBag = $parameterBag;
    }

    public function supports(Request $request): bool
    {
        return $request->isMethod('POST') && $this->getLoginUrl($request) === $request->getPathInfo();
    }

    public function authenticate(Request $request): PassportInterface
    {

        $email = trim($request->request->get('email'));
        $password = $request->request->get('password');
        $csrfToken = $request->request->get('_csrf_token');

        return new Passport(
                new UserBadge($email, function ($userIdentifier) {
                    return $this->userStore->getOneByEmail($userIdentifier);
                }),
                new PasswordCredentials($password),
                [
                        new CsrfTokenBadge('authenticate', $csrfToken),
                        new RememberMeBadge()
                ]
        );
    }

    public function onAuthenticationSuccess(
            Request $request,
            TokenInterface $token,
            string $providerKey
    ): RedirectResponse {



        $routeName = 'home';
        $email = trim($request->request->get('email'));
        $loginRedirection = $this->parameterBag->get('lc_sov.login_redirection');
        $useReferer = $loginRedirection['redirect_referer'];
        $rolesRedirection = $loginRedirection['roles_redirection'];


        $user = $this->userStore->getOneByEmail($email);

        if (isset($useReferer) && $useReferer == true) {
            $url = $request->request->get('_target_path');
        } else {
            if (!empty($user)) {
                $roles = $user->getRoles();

                foreach ($rolesRedirection as $roleRedirect) {
                    if (in_array($roleRedirect['role'], $roles)) {
                        $routeName = $roleRedirect['redirect'];
                    }
                }
            }
        }
        $this->userBuilder->setLastLogin($user);

        if (isset($url) && !empty($url)) {
            return new RedirectResponse($url);
        } else {
            return new RedirectResponse($this->urlGenerator->generate($routeName));
        }
    }

    protected function getLoginUrl(Request $request): string
    {
        return $this->urlGenerator->generate(self::LOGIN_ROUTE);
    }
}