<?php

namespace app\middleware;

use app\model\ApiKey;
use app\model\Client;
use app\model\Permission;
use app\service\Signature;
use think\Request;
use think\Response;

/**
 * API鉴权中间件
 */
class Auth
{
    /**
     * 处理请求
     */
    public function handle(Request $request, \Closure $next)
    {
        // 1. 提取必要Headers
        $apiKey = $request->header('X-API-Key');
        $timestamp = $request->header('X-Timestamp');
        $sign = $request->header('X-Sign');

        if (empty($apiKey) || empty($timestamp) || empty($sign)) {
            return json([
                'code' => 401,
                'msg' => '缺少鉴权头: 需要 X-API-Key, X-Timestamp, X-Sign'
            ], 401);
        }

        // 2. 查询API Key（连带查询client和permission）
        $apiKeyObj = ApiKey::with(['client', 'permission'])
            ->where('api_key', $apiKey)
            ->find();

        if (!$apiKeyObj) {
            return json([
                'code' => 401,
                'msg' => '无效的 API Key'
            ], 401);
        }

        // 3. 检查状态
        if ($apiKeyObj->status != ApiKey::STATUS_ENABLED) {
            return json([
                'code' => 403,
                'msg' => 'API Key 已被禁用'
            ], 403);
        }

        $clientObj = $apiKeyObj->client;
        if (!$clientObj || $clientObj->status != Client::STATUS_ENABLED) {
            return json([
                'code' => 403,
                'msg' => '客户账号已被停用，API 访问被拒绝'
            ], 403);
        }

        // 4. 验证签名
        $params = $request->param();
        if (!Signature::verify($params, $timestamp, $sign, $apiKeyObj->api_secret_hash)) {
            return json([
                'code' => 401,
                'msg' => '签名验证失败'
            ], 401);
        }

        // 5. 检查权限配置
        $permission = Permission::where('api_key_id', $apiKeyObj->id)->find();
        if (!$permission) {
            return json([
                'code' => 403,
                'msg' => '未配置 API 权限，请联系管理员'
            ], 403);
        }
        // 6. 将鉴权上下文存入请求
        $request->authContext = [
            'api_key_id' => $apiKeyObj->id,
            'api_key' => $apiKeyObj->api_key,
            'client_id' => $clientObj->id,
            'client_name' => $clientObj->name,
            'permission' => $permission,
            'rate_limit_per_minute' => $apiKeyObj->rate_limit_per_minute,
            'rate_limit_per_day' => $apiKeyObj->rate_limit_per_day,
        ];

        return $next($request);
    }
}