<?php

namespace ControleFrotas\Utils;

use Firebase\JWT\JWT as FirebaseJWT;
use Firebase\JWT\Key;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\SignatureInvalidException;

/**
 * Classe para gerenciar autenticação JWT
 */
class JWT
{
    private static string $secret = '';
    private static string $algorithm = 'HS256';
    private static int $expiration = 3600; // 1 hora

    /**
     * Configura os parâmetros JWT
     */
    public static function configure(string $secret, int $expiration = 3600): void
    {
        self::$secret = $secret;
        self::$expiration = $expiration;
    }

    /**
     * Gera um token JWT
     */
    public static function generate(array $payload): string
    {
        $now = time();
        
        $tokenPayload = array_merge($payload, [
            'iat' => $now,           // Issued at
            'exp' => $now + self::$expiration,  // Expiration
            'iss' => 'controle-frotas-api',     // Issuer
        ]);

        return FirebaseJWT::encode($tokenPayload, self::$secret, self::$algorithm);
    }

    /**
     * Valida e decodifica um token JWT
     */
    public static function decode(string $token): ?array
    {
        try {
            $decoded = FirebaseJWT::decode($token, new Key(self::$secret, self::$algorithm));
            return (array) $decoded;
        } catch (ExpiredException $e) {
            error_log("JWT expired: " . $e->getMessage());
            return null;
        } catch (SignatureInvalidException $e) {
            error_log("JWT signature invalid: " . $e->getMessage());
            return null;
        } catch (\Exception $e) {
            error_log("JWT decode error: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Extrai o token do header Authorization
     */
    public static function extractFromHeader(): ?string
    {
        $headers = getallheaders();
        
        if (!isset($headers['Authorization'])) {
            return null;
        }

        $authHeader = $headers['Authorization'];
        
        if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) {
            return null;
        }

        return $matches[1];
    }

    /**
     * Gera um token de refresh
     */
    public static function generateRefreshToken(string $userId): string
    {
        $payload = [
            'user_id' => $userId,
            'type' => 'refresh',
            'exp' => time() + (7 * 24 * 3600) // 7 dias
        ];

        return FirebaseJWT::encode($payload, self::$secret, self::$algorithm);
    }

    /**
     * Valida se um token é válido
     */
    public static function isValid(string $token): bool
    {
        return self::decode($token) !== null;
    }

    /**
     * Obtém o payload de um token sem validar expiração
     */
    public static function getPayloadWithoutValidation(string $token): ?array
    {
        try {
            $parts = explode('.', $token);
            if (count($parts) !== 3) {
                return null;
            }

            $payload = base64_decode($parts[1]);
            return json_decode($payload, true);
        } catch (\Exception $e) {
            error_log("JWT payload extraction error: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Verifica se um token está prestes a expirar
     */
    public static function isExpiringSoon(string $token, int $bufferSeconds = 300): bool
    {
        $payload = self::getPayloadWithoutValidation($token);
        
        if (!$payload || !isset($payload['exp'])) {
            return true;
        }

        return ($payload['exp'] - time()) <= $bufferSeconds;
    }

    /**
     * Obtém informações sobre um token
     */
    public static function getTokenInfo(string $token): array
    {
        $payload = self::getPayloadWithoutValidation($token);
        
        if (!$payload) {
            return ['valid' => false, 'error' => 'Invalid token format'];
        }

        $now = time();
        $isExpired = isset($payload['exp']) && $payload['exp'] < $now;
        $isValid = self::isValid($token);
        
        return [
            'valid' => $isValid,
            'expired' => $isExpired,
            'payload' => $payload,
            'issued_at' => isset($payload['iat']) ? date('Y-m-d H:i:s', $payload['iat']) : null,
            'expires_at' => isset($payload['exp']) ? date('Y-m-d H:i:s', $payload['exp']) : null,
            'time_to_expire' => isset($payload['exp']) ? max(0, $payload['exp'] - $now) : 0
        ];
    }
} 
