<?php

declare(strict_types=1);

namespace App\Middleware;

use App\Core\Request;
use App\Core\Response;

/**
 * Middleware de Autenticação API (JWT)
 * Verifica token JWT para acesso à API
 */
class ApiAuthMiddleware
{
    private string $jwtSecret;

    public function __construct()
    {
        $config = require \ROOT_PATH . '/config/app.php';
        $this->jwtSecret = $config['security']['jwt_secret'];
    }

    /**
     * Processa a requisição
     */
    public function handle(Request $request, Response $response): bool
    {
        $token = $this->extractToken($request);

        if (!$token) {
            $response->unauthorized('Token não fornecido');
            return false;
        }

        $payload = $this->validateToken($token);

        if (!$payload) {
            $response->unauthorized('Token inválido ou expirado');
            return false;
        }

        // Armazena informações do token na requisição
        $_REQUEST['_api_user'] = $payload;

        return true;
    }

    /**
     * Extrai o token do header Authorization
     */
    private function extractToken(Request $request): ?string
    {
        $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';

        if (empty($authHeader)) {
            return null;
        }

        if (preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) {
            return $matches[1];
        }

        return null;
    }

    /**
     * Valida o token JWT
     */
    private function validateToken(string $token): ?array
    {
        try {
            $parts = explode('.', $token);

            if (count($parts) !== 3) {
                return null;
            }

            [$header, $payload, $signature] = $parts;

            // Verifica assinatura
            $validSignature = hash_hmac(
                'sha256',
                $header . '.' . $payload,
                $this->jwtSecret,
                true
            );

            $validSignature = $this->base64UrlEncode($validSignature);

            if ($signature !== $validSignature) {
                return null;
            }

            // Decodifica payload
            $payloadData = json_decode($this->base64UrlDecode($payload), true);

            // Verifica expiração
            if (isset($payloadData['exp']) && $payloadData['exp'] < time()) {
                return null;
            }

            return $payloadData;

        } catch (\Exception $e) {
            error_log("Erro ao validar token: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Codifica Base64 URL-safe
     */
    private function base64UrlEncode(string $data): string
    {
        return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }

    /**
     * Decodifica Base64 URL-safe
     */
    private function base64UrlDecode(string $data): string
    {
        return base64_decode(strtr($data, '-_', '+/'));
    }
}

