<?php

namespace XZD\AI\V5\REST;

use WP_REST_Request;
use WP_REST_Response;

/**
 * REST 控制器基类 — 统一响应格式与权限检查
 *
 * 响应格式: {"success": bool, "data": mixed, "message": string, "code": string}
 */
abstract class BaseController
{
    protected string $namespace = 'xzdbk-ai/v1';

    /** 注册路由（子类实现） */
    abstract public function registerRoutes(): void;

    // 响应工厂

    protected function success(mixed $data = null, string $message = 'ok', int $status = 200): WP_REST_Response
    {
        return new WP_REST_Response([
            'success' => true,
            'data'    => $data,
            'message' => $message,
            'code'    => 'ok',
        ], $status);
    }

    protected function error(string $message, string $code = 'error', int $status = 400, mixed $data = null): WP_REST_Response
    {
        $response = [
            'success' => false,
            'data'    => $data,
            'message' => $message,
            'code'    => $code,
        ];
        return new WP_REST_Response($response, $status);
    }

    protected function created(mixed $data = null, string $message = '创建成功'): WP_REST_Response
    {
        return $this->success($data, $message, 201);
    }

    protected function noContent(string $message = '已删除'): WP_REST_Response
    {
        return $this->success(null, $message, 204);
    }

    // 参数获取

    protected function getParam(WP_REST_Request $request, string $key, mixed $default = null): mixed
    {
        $value = $request->get_param($key);
        return $value !== null ? $value : $default;
    }

    protected function getIntParam(WP_REST_Request $request, string $key, int $default = 0): int
    {
        return (int) $this->getParam($request, $key, $default);
    }

    protected function getBoolParam(WP_REST_Request $request, string $key, bool $default = false): bool
    {
        $value = $this->getParam($request, $key, $default);
        if (is_bool($value)) {
            return $value;
        }
        return filter_var($value, FILTER_VALIDATE_BOOLEAN);
    }

    protected function getJsonParam(WP_REST_Request $request, string $key, array $default = []): array
    {
        $value = $this->getParam($request, $key);
        if (is_array($value)) {
            return $value;
        }
        if (is_string($value)) {
            $decoded = json_decode($value, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return $decoded;
            }
        }
        return $default;
    }

    // 请求体

    /**
     * 获取请求体参数（兼容 JSON 和 form 格式）
     */
    protected function getBodyParams(WP_REST_Request $request): array
    {
        $json = $request->get_json_params();
        if (!empty($json)) {
            return $json;
        }
        return $request->get_body_params();
    }

    // 权限

    /**
     * 检查当前用户是否具有指定权限
     */
    protected function can(string $capability): bool
    {
        return current_user_can($capability);
    }

    /**
     * 验证请求的 WP Nonce
     */
    protected function verifyNonce(WP_REST_Request $request): bool
    {
        $nonce = $request->get_header('X-WP-Nonce');
        if (!$nonce) {
            $nonce = $this->getParam($request, '_wpnonce', '');
        }
        if (empty($nonce)) {
            return false;
        }
        return wp_verify_nonce($nonce, 'wp_rest') !== false;
    }

    /**
     * 授权守卫 — 检查当前授权等级是否达到要求
     *
     * @param string $minLevel 最低要求等级: 'free' | 'pro' | 'ultimate'，默认 'pro'
     * @return WP_REST_Response|null 不足时返回 402，通过返回 null
     */
    protected function guardLicense(string $minLevel = 'pro'): ?WP_REST_Response
    {
        $currentLevel = \XZD\AI\V5\Core\LicenseService::instance()->getLevel();

        if (!\XZD\AI\V5\Core\ToolPermissions::levelMeets($currentLevel, $minLevel)) {
            $levelInfo = \XZD\AI\V5\Core\ToolPermissions::getLevelInfo($minLevel);
            return $this->error(
                "此功能需要{$levelInfo['name']}授权，当前为免费版",
                'license_level_insufficient',
                402
            );
        }
        return null;
    }

    /**
     * 注册带标准权限的 GET 路由
     */
    protected function registerGet(string $route, callable $handler, string $permission = 'read'): void
    {
        register_rest_route($this->namespace, $route, [
            'methods'             => 'GET',
            'callback'            => $handler,
            'permission_callback' => fn() => $this->can($permission),
        ]);
    }

    /**
     * 注册带标准权限的 POST 路由
     */
    protected function registerPost(string $route, callable $handler, string $permission = 'edit_posts'): void
    {
        register_rest_route($this->namespace, $route, [
            'methods'             => 'POST',
            'callback'            => $handler,
            'permission_callback' => fn() => $this->can($permission),
        ]);
    }

    /**
     * 注册带标准权限的 PUT 路由
     */
    protected function registerPut(string $route, callable $handler, string $permission = 'edit_posts'): void
    {
        register_rest_route($this->namespace, $route, [
            'methods'             => 'PUT',
            'callback'            => $handler,
            'permission_callback' => fn() => $this->can($permission),
        ]);
    }

    /**
     * 注册带标准权限的 DELETE 路由
     */
    protected function registerDelete(string $route, callable $handler, string $permission = 'delete_posts'): void
    {
        register_rest_route($this->namespace, $route, [
            'methods'             => 'DELETE',
            'callback'            => $handler,
            'permission_callback' => fn() => $this->can($permission),
        ]);
    }

    /**
     * 注册公开 GET 路由（游客可访问）
     */
    protected function registerGetPublic(string $route, callable $handler): void
    {
        register_rest_route($this->namespace, $route, [
            'methods'             => 'GET',
            'callback'            => $handler,
            'permission_callback' => '__return_true',
        ]);
    }

    /**
     * 注册公开 POST 路由
     *
     * Basic Auth / Application Password 认证的请求跳过 nonce 检查，
     * 因为 Authorization 头部天然防 CSRF，且 WP Application Passwords 不依赖 nonce。
     */
    protected function registerPostPublic(string $route, callable $handler): void
    {
        register_rest_route($this->namespace, $route, [
            'methods'             => 'POST',
            'callback'            => $handler,
            'permission_callback' => function (WP_REST_Request $request): bool {
                // 游客：允许访问
                if (!is_user_logged_in()) {
                    return true;
                }
                // Basic Auth / Application Password：Authorization 头防 CSRF，无需 nonce
                if ($request->get_header('Authorization')) {
                    return true;
                }
                // Cookie 认证：必须验证 nonce（防 CSRF）
                return $this->verifyNonce($request);
            },
        ]);
    }
}
