<?php
declare(strict_types=1);

namespace app\api\middleware;

use app\api\cache\AuthTokenCache;
use app\api\util\ReturnCode;
use plugin\saiadmin\exception\ApiException;
use Tinywan\Jwt\JwtToken;
use Tinywan\Jwt\Exception\JwtTokenException;
use Tinywan\Jwt\Exception\JwtTokenExpiredException;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;

/**
 * 校验 auth-token 请求头（JWT）
 * 用于 /api/v1/* 接口（除 /api/v1/authtoken 外）
 * 请求头需携带 auth-token，通过后注入 request->agent_id
 */
class AuthTokenMiddleware implements MiddlewareInterface
{
    public function process(Request $request, callable $handler): Response
    {
        $token = $request->header('auth-token');
        $token = $token !== null ? trim((string) $token) : '';
        if ($token === '') {
            throw new ApiException('请携带 auth-token', ReturnCode::UNAUTHORIZED);
        }

        try {
            $decoded = JwtToken::verify(1, $token);
        } catch (JwtTokenExpiredException $e) {
            throw new ApiException('auth-token 已过期', ReturnCode::TOKEN_INVALID);
        } catch (JwtTokenException $e) {
            throw new ApiException('auth-token 无效', ReturnCode::TOKEN_INVALID);
        } catch (\Throwable $e) {
            throw new ApiException('auth-token 格式无效', ReturnCode::TOKEN_INVALID);
        }

        $extend = $decoded['extend'] ?? [];
        if ((string) ($extend['plat'] ?? '') !== 'api_auth_token') {
            throw new ApiException('auth-token 无效', ReturnCode::TOKEN_INVALID);
        }
        $agentId = trim((string) ($extend['agent_id'] ?? ''));
        if ($agentId === '') {
            throw new ApiException('auth-token 无效', ReturnCode::TOKEN_INVALID);
        }

        $currentToken = AuthTokenCache::getTokenByAgentId($agentId);
        if ($currentToken === null || $currentToken !== $token) {
            throw new ApiException('auth-token 无效或已失效', ReturnCode::TOKEN_INVALID);
        }

        $request->agent_id = $agentId;
        return $handler($request);
    }
}
