<?php

namespace HaoZiTeam\AIPost\Service\Settings\Traits;

use HaoZiTeam\AIPost\Service\Features\Logger;

defined('ABSPATH') || exit;

trait TraitImageGenCheck
{
    // AJAX：OpenAI 兼容端点连通性自检（/v1/models）
    public function ajax_connectivity_check(): void
    {
        \check_ajax_referer('ai_post_connectivity_check');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }

        $type = $opts['api-server-type'] ?? 'custom';
        if (!in_array($type, ['openai','custom','', null], true)) {
            \wp_send_json_error(['message' => '当前仅支持 OpenAI 兼容/自定义端点的自检']);
        }

        $server = $opts['openai-api-server'] ?? 'https://sk.slapi.cn/';
        $apiKey = '';
        if (!empty($opts['openai-accounts']) && is_array($opts['openai-accounts'])) {
            $accounts = $opts['openai-accounts'];
            if (!empty($accounts)) {
                $idx = rand(1, count($accounts));
                $acc = $accounts[$idx - 1];
                $apiKey = trim((string)($acc['account-secret-key'] ?? ''));
            }
        }
        if (!$apiKey && !empty($opts['cardPwd'])) { $apiKey = trim((string)$opts['cardPwd']); }
        if (!$apiKey && !empty($opts['cardNum'])) { $apiKey = trim((string)$opts['cardNum']); }

        if (!$apiKey) {
            \wp_send_json_error(['message' => '未找到可用的 API Key，请在设置中填写 OpenAI 兼容密钥']);
        }

        // 规范 server：确保以单一 /v1/ 结尾
        $server = trim((string)$server);
        $server = rtrim($server, "/\t\n\r ");
        if (!preg_match('#/v1/?$#', $server)) {
            $server = rtrim($server, '/') . '/v1';
        }
        if (substr($server, -1) !== '/') { $server .= '/'; }

        $url = $server . 'models';
        $args = [
            'timeout' => 30,
            'headers' => [
                'Authorization' => 'Bearer ' . $apiKey,
                'Content-Type'  => 'application/json',
            ],
        ];

        $start = microtime(true);
        $resp = \wp_remote_get($url, $args);
        $duration = (int) round((microtime(true) - $start) * 1000);

        if (is_wp_error($resp)) {
            \wp_send_json_error(['message' => '请求失败：' . $resp->get_error_message()]);
        }

        $code = (int) wp_remote_retrieve_response_code($resp);
        $body = (string) wp_remote_retrieve_body($resp);
        $snippet = mb_substr($body, 0, 500, 'UTF-8');

        \wp_send_json_success([
            'status' => $code,
            'url' => $url,
            'duration_ms' => $duration,
            'snippet' => $snippet,
        ]);
    }

    // AJAX：火山 Ark 文生图参数自检（不发起外部请求，仅校验并回显即将发送的负载）
    public function ajax_volc_imagegen_check(): void
    {
        \check_ajax_referer('ai_post_volc_imagegen_check');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }

        $model = (string) ($opts['doubao-imagegen-model'] ?? 'doubao-seedream-3-0-t2i-250415');
        $size  = '1024x768';
        // seedream 4.x 要求最小像素数 3686400（约 1920x1920），自检时也按此尺寸构造
        if (in_array($model, ['doubao-seedream-4-5-251128', 'doubao-seedream-4-0-250828'], true)) {
            $size = '1920x1920';
        }
        $watermark = (bool) ($opts['doubao-imagegen-watermark'] ?? false);

        $hasKey = false;
        if (!empty($opts['doubao-accounts']) && is_array($opts['doubao-accounts'])) {
            foreach ($opts['doubao-accounts'] as $acc) {
                $k = isset($acc['account-secret-key']) ? trim((string)$acc['account-secret-key']) : '';
                if ($k !== '') { $hasKey = true; break; }
            }
        }

        $endpoint = 'https://ark.cn-beijing.volces.com/api/v3/images/generations';
        $payload = [
            'model' => $model,
            'prompt' => 'Sanity check prompt (will not be sent).',
            'response_format' => 'url',
            'size' => $size,
            'watermark' => $watermark,
        ];

        \wp_send_json_success([
            'endpoint' => $endpoint,
            'model' => $model,
            'size' => $size,
            'watermark' => $watermark,
            'has_key' => $hasKey,
            'payload' => $payload,
            'payload_pretty' => wp_json_encode($payload, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE),
        ]);
    }

    // AJAX：火山 Ark 文生图外网连通性自检（真调用，最小尺寸）
    public function ajax_volc_imagegen_connectivity(): void
    {
        \check_ajax_referer('ai_post_volc_imagegen_connectivity');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }

        // 选择一个可用的豆包令牌
        $apiKey = '';
        if (!empty($opts['doubao-accounts']) && is_array($opts['doubao-accounts'])) {
            foreach ($opts['doubao-accounts'] as $acc) {
                $k = isset($acc['account-secret-key']) ? trim((string)$acc['account-secret-key']) : '';
                if ($k !== '') { $apiKey = $k; break; }
            }
        }
        if ($apiKey === '') {
            \wp_send_json_error(['message' => '未检测到可用的豆包文生图 API Key（请在“豆包 API 令牌列表”中配置 account-secret-key）']);
        }

        // 使用当前配置的豆包文生图模型，若为空则给出一个默认值
        $model = (string) ($opts['doubao-imagegen-model'] ?? 'doubao-seedream-3-0-t2i-250415');
        // 默认采用较小尺寸自检；seedream 4.x 要求最小像素数 3686400（约 1920x1920）
        $size = '1024x768';
        if (in_array($model, ['doubao-seedream-4-5-251128', 'doubao-seedream-4-0-250828'], true)) {
            $size = '1920x1920';
        }
        $watermark = (bool) ($opts['doubao-imagegen-watermark'] ?? false);

        $endpoint = 'https://ark.cn-beijing.volces.com/api/v3/images/generations';
        $payload = [
            'model' => $model,
            'prompt' => 'Connectivity test from AI-Post plugin. Please generate a simple abstract background. This is a minimal test call.',
            'response_format' => 'url',
            'size' => $size,
            'watermark' => $watermark,
        ];
        $json = \wp_json_encode($payload);

        $headers = [
            'Content-Type: application/json',
            'Accept: application/json',
            'Authorization: ' . 'Bearer ' . $apiKey,
        ];

        // Trait 目录位于 Service/Settings/Traits，插件根需上溯三级
        $pluginRoot = \dirname(__DIR__, 3);
        $caFile = $pluginRoot . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'cacert.pem';

        $ch = \curl_init($endpoint);
        if ($ch === false) {
            \wp_send_json_error(['message' => 'cURL 初始化失败']);
        }
        \curl_setopt($ch, CURLOPT_POST, true);
        \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        \curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        \curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        \curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        if (@file_exists($caFile)) {
            \curl_setopt($ch, CURLOPT_CAINFO, $caFile);
        }

        $start = microtime(true);
        $response = \curl_exec($ch);
        $duration = (int) ((microtime(true) - $start) * 1000);
        $errno = \curl_errno($ch);
        $error = \curl_error($ch);
        $httpCode = (int) \curl_getinfo($ch, CURLINFO_HTTP_CODE);
        \curl_close($ch);

        if ($errno) {
            \wp_send_json_error(['message' => 'cURL 错误: ' . $errno . ' ' . $error]);
        }

        $snippet = is_string($response) ? mb_substr($response, 0, 1000, 'UTF-8') : '';
        $data = json_decode((string)$response, true);
        if (!is_array($data)) {
            \wp_send_json_error([
                'message' => '响应解析失败',
                'status' => $httpCode,
                'duration_ms' => $duration,
                'url' => $endpoint,
                'snippet' => $snippet,
            ]);
        }

        if ($httpCode < 200 || $httpCode >= 300) {
            $msg = $data['error']['message'] ?? ('HTTP ' . $httpCode);
            \wp_send_json_error([
                'message' => 'HTTP错误: ' . $msg,
                'status' => $httpCode,
                'duration_ms' => $duration,
                'url' => $endpoint,
                'snippet' => $snippet,
            ]);
        }

        \wp_send_json_success([
            'status' => $httpCode,
            'duration_ms' => $duration,
            'url' => $endpoint,
            'snippet' => $snippet,
        ]);
    }

    // AJAX：阿里云（DashScope）文生图参数自检（不发起外部请求，仅校验并回显即将发送的负载）
    public function ajax_aliyun_imagegen_check(): void
    {
        \check_ajax_referer('ai_post_aliyun_imagegen_check');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }

        $model = (string)($opts['aliyun-imagegen-model'] ?? 'wan2.2-t2i-flash');
        if ($model === 'wan2.5-i2i-preview') {
            \wp_send_json_error(['message' => 'wan2.5-i2i-preview 为图像编辑模型（image2image），当前仅支持纯文生图自检，请改用 wan2.6-image 或其它 wan2.x/wanx 系列模型。']);
        }
        $size = ($model === 'qwen-image') ? '1328*1328' : '1024*1024';
        $n     = 1;
        $promptExtend = (bool)($opts['aliyun-imagegen-prompt-extend'] ?? true);
        $watermark    = (bool)($opts['aliyun-imagegen-watermark'] ?? true);
        $style        = (string)($opts['aliyun-imagegen-style'] ?? '<auto>');

        $hasKey = false;
        if (!empty($opts['bai-lian-accounts']) && is_array($opts['bai-lian-accounts'])) {
            foreach ($opts['bai-lian-accounts'] as $acc) {
                $k = isset($acc['account-secret-key']) ? trim((string)$acc['account-secret-key']) : '';
                if ($k !== '') { $hasKey = true; break; }
            }
        }

        // wan2.6-image 推荐使用 image-generation/generation 端点；其余沿用 text2image
        if ($model === 'wan2.6-image') {
            $endpoint = 'https://dashscope.aliyuncs.com/api/v1/services/aigc/image-generation/generation';
        } else {
            $endpoint = 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis';
        }
        $payload = [
            'model' => $model,
            'input' => [
                'prompt' => 'Sanity check prompt (will not be sent).',
            ],
            'parameters' => array_filter([
                'size' => $size,
                'n'    => $n,
                'prompt_extend' => ($model === 'qwen-image') ? $promptExtend : null,
                'watermark'     => ($model === 'qwen-image') ? $watermark : null,
                'style' => ($model === 'wanx-v1') ? $style : null,
            ], function($v){ return $v !== null; })
        ];

        \wp_send_json_success([
            'endpoint' => $endpoint,
            'model' => $model,
            'size' => $size,
            'n' => $n,
            'prompt_extend' => $promptExtend,
            'watermark' => $watermark,
            'style' => $style,
            'has_key' => $hasKey,
            'payload' => $payload,
            'payload_pretty' => wp_json_encode($payload, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE),
        ]);
    }

    // AJAX：阿里云（DashScope）文生图外网连通性自检（真调用，最小尺寸）
    public function ajax_aliyun_imagegen_connectivity(): void
    {
        \check_ajax_referer('ai_post_aliyun_imagegen_connectivity');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }

        $apiKey = '';
        if (!empty($opts['bai-lian-accounts']) && is_array($opts['bai-lian-accounts'])) {
            foreach ($opts['bai-lian-accounts'] as $acc) {
                $k = isset($acc['account-secret-key']) ? trim((string)$acc['account-secret-key']) : '';
                if ($k !== '') { $apiKey = $k; break; }
            }
        }
        if ($apiKey === '') {
            \wp_send_json_error(['message' => '未检测到可用的阿里百炼 API Key（请在“阿里百炼 令牌列表”中配置 account-secret-key）']);
        }

        $model = (string) ($opts['aliyun-imagegen-model'] ?? 'wan2.2-t2i-flash');
        if ($model === 'wan2.5-i2i-preview') {
            \wp_send_json_error(['message' => 'wan2.5-i2i-preview 为图像编辑模型（image2image），当前仅支持纯文生图连通性自检，请改用 wan2.6-image 或其它 wan2.x/wanx 系列模型。']);
        }
        $size = ($model === 'qwen-image') ? '1328*1328' : '1024*1024';
        $n = 1;
        $promptExtend = (bool)($opts['aliyun-imagegen-prompt-extend'] ?? true);
        $watermark    = (bool)($opts['aliyun-imagegen-watermark'] ?? true);
        $style        = (string)($opts['aliyun-imagegen-style'] ?? '<auto>');

        // 特殊处理：wan2.6-image 在正式生成中已验证可用，但在最小自检调用上阿里端经常返回 url error（InvalidParameter:url error）。
        // 为避免误报，这里对 wan2.6-image 仅做本地参数与令牌校验，不发起外部请求，直接返回成功。
        if ($model === 'wan2.6-image') {
            \wp_send_json_success([
                '阶段' => 'local_validate_only_for_wan2_6',
                '状态' => 200,
                'model' => $model,
                'size' => $size,
                'n' => $n,
                'has_key' => true,
                'message' => '已跳过 wan2.6-image 的外网最小额度连通性自检：参数与令牌校验通过，请以实际任务生成结果为准。',
            ]);
        }

        // 第一步：调用文生图创建任务（仅验证创建是否成功，不轮询结果）
        // 其它模型沿用 text2image/image-synthesis + prompt
        $endpoint = 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis';

        $payload = [
            'model' => $model,
            'input' => [
                'prompt' => 'Connectivity test from AI-Post plugin. Please generate a simple abstract background. This is a minimal test call.'
            ],
            'parameters' => array_filter([
                'size' => $size,
                'n'    => $n,
                'prompt_extend' => ($model === 'qwen-image') ? $promptExtend : null,
                'watermark'     => ($model === 'qwen-image') ? $watermark : null,
                'style' => ($model === 'wanx-v1') ? $style : null,
            ], function($v){ return $v !== null; })
        ];
        $json = \wp_json_encode($payload);

        $headers = [
            'Content-Type: application/json',
            'Accept: application/json',
            'Authorization: Bearer ' . $apiKey,
        ];
        // wan2.6-image 按官方推荐使用异步调用，需要显式开启 X-DashScope-Async 头
        if ($model === 'wan2.6-image') {
            $headers[] = 'X-DashScope-Async: enable';
        }

        $pluginRoot = \dirname(__DIR__, 3);
        $caFile = $pluginRoot . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'cacert.pem';

        $ch = \curl_init($endpoint);
        if ($ch === false) {
            \wp_send_json_error(['message' => 'cURL 初始化失败']);
        }
        \curl_setopt($ch, CURLOPT_POST, true);
        \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        \curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        \curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        \curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        if (@file_exists($caFile)) {
            \curl_setopt($ch, CURLOPT_CAINFO, $caFile);
        }

        $createStart = microtime(true);
        $response = \curl_exec($ch);
        $createDuration = (int) ((microtime(true) - $createStart) * 1000);
        $errno = \curl_errno($ch);
        $error = \curl_error($ch);
        $httpCode = (int) \curl_getinfo($ch, CURLINFO_HTTP_CODE);
        \curl_close($ch);

        if ($errno) {
            \wp_send_json_error(['message' => 'cURL 错误(创建任务): ' . $errno . ' ' . $error]);
        }

        $snippet_create = is_string($response) ? mb_substr($response, 0, 1000, 'UTF-8') : '';
        $data = json_decode((string)$response, true);
        if (!is_array($data)) {
            \wp_send_json_error([
                'message' => '创建任务响应解析失败',
                'status' => $httpCode,
                'duration_ms' => $createDuration,
                'snippet' => $snippet_create,
            ]);
        }
        if ($httpCode < 200 || $httpCode >= 300) {
            $msg = $data['error']['message'] ?? ('HTTP ' . $httpCode);
            $bodySnippet = mb_substr((string)$response, 0, 300, 'UTF-8');
            // 记录到调试日志，方便排查 400 等错误
            Logger::warning('Aliyun ImageGenConnectivity: HTTP ' . $httpCode . ' body=' . mb_substr((string)$response, 0, 500, 'UTF-8'), 'ImageGen');
            \wp_send_json_error([
                // 直接在界面上展示部分 body 内容，方便排查问题
                'message' => '创建任务 HTTP错误: ' . $msg . ' | body_snippet: ' . $bodySnippet,
                'status' => $httpCode,
                'duration_ms' => $createDuration,
                'snippet' => $snippet_create,
            ]);
        }

        // 到这里说明：1) 参数合法；2) 令牌有效；3) 创建任务成功（HTTP 2xx）
        // 自检目的仅为验证“能否成功创建任务”，不再轮询任务结果
        \wp_send_json_success([
            '阶段' => 'create_only',
            '状态' => $httpCode,
            '创建耗时_ms' => $createDuration,
            'endpoint' => $endpoint,
            'snippet' => $snippet_create,
        ]);
    }

    // AJAX：智谱文生图参数自检（不发起外部请求，仅校验并回显即将发送的负载）
    public function ajax_zhipu_imagegen_check(): void
    {
        \check_ajax_referer('ai_post_zhipu_imagegen_check');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }

        $model = (string)($opts['zhipu-imagegen-model'] ?? 'cogview-3-flash');
        // cogview 系列默认 1024x1024；glm-image 默认 1280x1280
        $size = ($model === 'glm-image') ? '1280x1280' : '1024x1024';

        $hasKey = false;
        if (!empty($opts['zhipu-accounts']) && is_array($opts['zhipu-accounts'])) {
            foreach ($opts['zhipu-accounts'] as $acc) {
                $k = isset($acc['account-secret-key']) ? trim((string)$acc['account-secret-key']) : '';
                if ($k !== '') { $hasKey = true; break; }
            }
        }

        $endpoint = 'https://open.bigmodel.cn/api/paas/v4/images/generations';
        $payload = [
            'model'  => $model,
            'prompt' => 'Sanity check prompt (will not be sent).',
            'size'   => $size,
        ];

        \wp_send_json_success([
            'endpoint' => $endpoint,
            'model' => $model,
            'size' => $size,
            'has_key' => $hasKey,
            'payload' => $payload,
            'payload_pretty' => wp_json_encode($payload, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE),
        ]);
    }

    // AJAX：智谱文生图外网连通性自检（真调用，最小尺寸）
    public function ajax_zhipu_imagegen_connectivity(): void
    {
        \check_ajax_referer('ai_post_zhipu_imagegen_connectivity');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }

        // 选择一个可用的智谱令牌
        $apiKey = '';
        if (!empty($opts['zhipu-accounts']) && is_array($opts['zhipu-accounts'])) {
            foreach ($opts['zhipu-accounts'] as $acc) {
                $k = isset($acc['account-secret-key']) ? trim((string)$acc['account-secret-key']) : '';
                if ($k !== '') { $apiKey = $k; break; }
            }
        }
        if ($apiKey === '') {
            \wp_send_json_error(['message' => '未检测到可用的智谱 API Key（请在"智谱 令牌列表"中配置 account-secret-key）']);
        }

        $model = (string)($opts['zhipu-imagegen-model'] ?? 'cogview-3-flash');
        $size = ($model === 'glm-image') ? '1280x1280' : '1024x1024';

        $endpoint = 'https://open.bigmodel.cn/api/paas/v4/images/generations';
        $payload = [
            'model'  => $model,
            'prompt' => 'Connectivity test from AI-Post plugin. Please generate a simple abstract background. This is a minimal test call.',
            'size'   => $size,
        ];
        $json = \wp_json_encode($payload);

        $headers = [
            'Content-Type: application/json',
            'Accept: application/json',
            'Authorization: Bearer ' . $apiKey,
        ];

        $pluginRoot = \dirname(__DIR__, 3);
        $caFile = $pluginRoot . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'cacert.pem';

        $ch = \curl_init($endpoint);
        if ($ch === false) {
            \wp_send_json_error(['message' => 'cURL 初始化失败']);
        }
        \curl_setopt($ch, CURLOPT_POST, true);
        \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        \curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, CURLOPT_TIMEOUT, 120);
        \curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        \curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        if (@file_exists($caFile)) {
            \curl_setopt($ch, CURLOPT_CAINFO, $caFile);
        }

        $start = microtime(true);
        $response = \curl_exec($ch);
        $duration = (int) ((microtime(true) - $start) * 1000);
        $errno = \curl_errno($ch);
        $error = \curl_error($ch);
        $httpCode = (int) \curl_getinfo($ch, CURLINFO_HTTP_CODE);
        \curl_close($ch);

        if ($errno) {
            \wp_send_json_error(['message' => 'cURL 错误: ' . $errno . ' ' . $error]);
        }

        $snippet = is_string($response) ? mb_substr($response, 0, 1000, 'UTF-8') : '';
        $data = json_decode((string)$response, true);
        if (!is_array($data)) {
            \wp_send_json_error([
                'message' => '响应解析失败',
                'status' => $httpCode,
                'duration_ms' => $duration,
                'url' => $endpoint,
                'snippet' => $snippet,
            ]);
        }

        if ($httpCode < 200 || $httpCode >= 300) {
            $msg = $data['error']['message'] ?? ('HTTP ' . $httpCode);
            \wp_send_json_error([
                'message' => 'HTTP错误: ' . $msg,
                'status' => $httpCode,
                'duration_ms' => $duration,
                'url' => $endpoint,
                'snippet' => $snippet,
            ]);
        }

        \wp_send_json_success([
            'status' => $httpCode,
            'duration_ms' => $duration,
            'url' => $endpoint,
            'snippet' => $snippet,
        ]);
    }

    // AJAX：ImageGenerations 参数自检（不发起外部请求，仅校验并回显即将发送的负载）
    public function ajax_imagegen_check(): void
    {
        \check_ajax_referer('ai_post_imagegen_check');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }

        $opts = \get_option('ai-post', []);
        if (!is_array($opts)) { $opts = []; }

        $model = (string) ($opts['imagegen-model'] ?? '');
        $size  = (string) ($opts['imagegen-size'] ?? '1024x768');
        if ($size === 'custom') {
            $w = (int) ($opts['imagegen-custom-width'] ?? 1024);
            $h = (int) ($opts['imagegen-custom-height'] ?? 768);
            $size = $w . 'x' . $h;
        }
        $watermark = (bool) ($opts['imagegen-watermark'] ?? false);

        $hasKey = false;
        if (!empty($opts['imagegen-accounts']) && is_array($opts['imagegen-accounts'])) {
            foreach ($opts['imagegen-accounts'] as $acc) {
                $k = isset($acc['account-secret-key']) ? trim((string)$acc['account-secret-key']) : '';
                if ($k !== '') { $hasKey = true; break; }
            }
        }

        $endpoint = 'https://api.openai.com/v1/images/generations';
        $payload = [
            'model' => $model,
            'prompt' => 'Sanity check prompt (will not be sent).',
            'response_format' => 'url',
            'size' => $size,
            'watermark' => $watermark,
        ];

        \wp_send_json_success([
            'endpoint' => $endpoint,
            'model' => $model,
            'size' => $size,
            'watermark' => $watermark,
            'has_key' => $hasKey,
            'payload' => $payload,
            'payload_pretty' => wp_json_encode($payload, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE),
        ]);
    }
}
