<?php

declare(strict_types=1);

namespace App\Middleware;

use App\Services\JwtService;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;

class JwtAuthMiddleware implements MiddlewareInterface
{
    private JwtService $jwt;
    private ResponseFactoryInterface $responseFactory;

    public function __construct(JwtService $jwt, ResponseFactoryInterface $responseFactory)
    {
        $this->jwt = $jwt;
        $this->responseFactory = $responseFactory;
    }

    public function process(Request $request, RequestHandler $handler): Response
    {
        $header = $request->getHeaderLine('Authorization');

        if (!preg_match('/^Bearer\s+(.+)$/i', $header, $matches)) {
            return $this->unauthorized('Token no proporcionado');
        }

        try {
            $payload = $this->jwt->decode($matches[1]);
        } catch (\Throwable $e) {
            return $this->unauthorized('Token inválido o expirado');
        }

        if (($payload['type'] ?? '') !== 'access') {
            return $this->unauthorized('Tipo de token inválido');
        }

        $request = $request
            ->withAttribute('usuario_id', (int) $payload['sub'])
            ->withAttribute('usuario_rol', $payload['rol']);

        return $handler->handle($request);
    }

    private function unauthorized(string $mensaje): Response
    {
        $response = $this->responseFactory->createResponse(401);
        $response->getBody()->write(json_encode(['error' => $mensaje]));

        return $response->withHeader('Content-Type', 'application/json');
    }
}
