<?php

namespace App\Security;

use App\Repository\UserRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;

class JsonAesAuthenticator extends AbstractAuthenticator
{
    use TargetPathTrait;

    private UserRepository $userRepository;
    private UrlGeneratorInterface $urlGenerator;

    public function __construct(UrlGeneratorInterface $urlGenerator, UserRepository $userRepository)
    {
        $this->urlGenerator = $urlGenerator;
        $this->userRepository = $userRepository;
    }


    public function supports(Request $request): ?bool
    {
        return ($request->attributes->get('_route') == 'app_login_json')
        && $request->query->has('token')
        && null != $_ENV['LOGIN_JSON_AES_KEY']
        && !empty($_ENV['LOGIN_JSON_AES_KEY']);
    }

    public function authenticate(Request $request): Passport
    {

        $apiToken = $request->query->get('token');
        if (null === $apiToken) {
            throw new AccessDeniedHttpException('No API token provided');
        }

        $tokenDecoded = openssl_decrypt($apiToken, 'aes-256-cbc', $_ENV['LOGIN_JSON_AES_KEY'], 0);
        $tokenInfos = json_decode($tokenDecoded);

        return new SelfValidatingPassport(new UserBadge($tokenInfos->email, function (string $userIdentifier) {
            return $this->userRepository->findOneBy(['email' => $userIdentifier]);
        }));
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {

        if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
            return new RedirectResponse($targetPath);
        }

        return new RedirectResponse($this->urlGenerator->generate('home'));
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        return new RedirectResponse($this->urlGenerator->generate('app_login_json'));
    }
}
