<?php

declare(strict_types=1);

namespace NoahVet\Reef\Security\Token;

use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use NoahVet\Reef\Exception\NotJWTException;
use NoahVet\Reef\Security\IAM\IAMPublicKeyProviderInterface;

class JWTDecoder implements JWTDecoderInterface
{
    /**
     * @var array<string, \stdClass|null>
     */
    private array $decodedTokens = [];

    public function __construct(
        private readonly IAMPublicKeyProviderInterface $IAMPublicKeyProvider,
    ) {
    }

    /**
     * @throws NotJWTException
     */
    public function decodeJWT(string $jwt): ?\stdClass
    {
        if (!isset($this->decodedTokens[$jwt])) {
            if (empty($jwt)) {
                throw new NotJWTException();
            }

            $tks = \explode('.', $jwt);
            if (3 !== \count($tks)) {
                throw new NotJWTException();
            }

            try {
                $decodedToken = JWT::decode($jwt, $this->IAMPublicKeyProvider->getIAMPublicKeys());
            } catch (ExpiredException) {
                return null;
            } catch (\UnexpectedValueException) {
                throw new NotJWTException();
            }

            $this->decodedTokens[$jwt] = $decodedToken;
        }

        return $this->decodedTokens[$jwt];
    }
}
