<?php

declare(strict_types=1);

namespace Fennec\Security;

use Fennec\Http\JsonResponse;
use Fennec\Http\Request;
use Fennec\Middleware\MiddlewareInterface;
use Fennec\Security\Jwt\ExpiredTokenException;
use Fennec\Security\Jwt\InvalidTokenException;
use Fennec\Security\Jwt\Jwt;

/**
 * Vérifie le token Bearer JWT s'il est présent, et attache le rôle authentifié à la requête.
 *
 * Un token absent laisse la requête passer en anonyme — c'est RoleMiddleware qui décide
 * si l'absence d'authentification doit bloquer l'accès à une route donnée. Un token
 * présent mais invalide ou expiré court-circuite immédiatement avec une 401.
 */
final class AuthenticationMiddleware implements MiddlewareInterface
{
    public function __construct(private readonly Jwt $jwt)
    {
    }

    public function process(Request $request, \Closure $next): JsonResponse
    {
        $token = $request->getBearerToken();

        if ($token === null) {
            return $next($request);
        }

        try {
            $claims = $this->jwt->decode($token);
        } catch (InvalidTokenException|ExpiredTokenException) {
            return JsonResponse::error(
                'UNAUTHORIZED',
                'Authentification invalide ou expirée.',
                null,
                401,
            );
        }

        $request->setAttribute('role', $claims['role'] ?? null);
        $request->setAttribute('sub', $claims['sub'] ?? null);

        return $next($request);
    }
}
