<?php

namespace apexl\Io\modules\user\services;

use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\exceptions\JwtException;
use apexl\Io\modules\user\Factories\JwtFromRequestServiceFactory;
use apexl\Io\modules\user\interfaces\JwtKeyProviderInterface;
use DateTimeImmutable;
use Deprecated;
use DI\DependencyException;
use DI\NotFoundException;
use Exception;
use Firebase\JWT\JWT;
use Psr\Http\Message\ServerRequestInterface;
use function apexl\Io\container;

final readonly class currentUser
{
    #[Deprecated(message: 'Use apexl\\Io\\modules\\user\\services\\JwtCreator')]
    public static function createJWT(
        userEntity $user,
        string $sessionId,
        string $secretKey,
        string $algorithm,
        int $lifetime
    ): string {
        return container()->get(JwtCreator::class)->forUser($user, $sessionId);
    }

    /**
     * Authenticate a JSON Web Token
     * @todo Review functionality; should probably throw an exception rather that return an array with an error
     */
    #[Deprecated(message: 'Use apexl\\Io\\modules\\user\\services\\JwtFromRequestService')]
    public static function authenticateJWT(ServerRequestInterface $request, string $secretKey, string $algorithm): array
    {
        try {
            return [container()->get(JwtFromRequestServiceFactory::class)->make($request)->token(), null];
        } catch (DependencyException|NotFoundException|JwtException $e) {
            return [false, $e->getMessage()];
        }
    }

    public static function requestHasBearerAuthHeader(ServerRequestInterface $request, &$matches = []): bool
    {
        return self::requestHasAuthHeader($request, 'Bearer', $matches);
    }

    private static function requestHasAuthHeader(ServerRequestInterface $request, string $type, &$matches = []): bool
    {
        $header = self::authHeader($request);
        $pattern = sprintf('/^%s\s(\S+)/', $type);

        return preg_match($pattern, $header, $matches);
    }

    private static function authHeader(ServerRequestInterface $request): string
    {
        if ($request->hasHeader('Authorization')) {
            return $request->getHeader('Authorization')[0];
        }

        return '';
    }

    #[Deprecated(message: 'Use apexl\\Io\\modules\\user\\services\\SessionInfoFromJwtTokenService')]
    public static function getClaimsFromJWT(ServerRequestInterface $request): ?object
    {
        try {
            return container()->get(SessionInfoFromJwtTokenService::class)->info($request);
        } catch (DependencyException|NotFoundException|JwtException) {
            return null;
        }
    }

    private static function getSessionInfoFromToken(string $encodedToken): object
    {
        [, $encodedSessionInfo] = explode('.', $encodedToken);

        return json_decode(base64_decode($encodedSessionInfo));
    }

    public static function getTokenExpiryFromNow(string $encodedToken): int
    {
        $sessionInfo = self::getSessionInfoFromToken($encodedToken);

        return max($sessionInfo->exp - time(), 0);
    }

    public static function requestHasBasicAuthHeader(ServerRequestInterface $request, &$matches = []): bool
    {
        return self::requestHasAuthHeader($request, 'Basic', $matches);
    }

}
