<?php

declare(strict_types=1);

namespace NoahVet\Reef\Security\IAM\TokenExchange;

use NoahVet\Reef\Exception\OAuthRequestException;
use NoahVet\Reef\Security\Token\JWTDecoderInterface;
use Psr\Cache\CacheItemPoolInterface;

class CachedTokenExchangerDecorator implements TokenExchangerInterface
{
    public function __construct(
        private readonly CacheItemPoolInterface $cache,
        private readonly JWTDecoderInterface $JWTDecoder,
        private readonly string $reefClientId,
        private readonly TokenExchangerInterface $innerTokenExchanger,
    ) {
    }

    public function exchangeTokenForCurrentClient(string $bearerToken): string
    {
        $cacheKey = 'reef_token_exchanged_'.$this->reefClientId.'_'.$bearerToken;

        $cacheItem = $this->cache->getItem($cacheKey);

        if (!$cacheItem->isHit()) {
            $newAccessToken = $this->innerTokenExchanger->exchangeTokenForCurrentClient($bearerToken);

            $parsedToken = $this->JWTDecoder->decodeJWT($newAccessToken);

            if (null === $parsedToken) {
                throw new OAuthRequestException('Exchanged access token is expired : '.$newAccessToken);
            }

            $cacheItem->set($newAccessToken);
            $cacheItem->expiresAt(new \DateTimeImmutable('@'.$parsedToken->exp));

            $this->cache->save($cacheItem);
        }

        return (string) $cacheItem->get();
    }
}
