<?php

namespace HaoZiTeam\AIPost\Service;

use CGPS;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitFontTools;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitDebugLog;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitImageGenCheck;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitSelfDiagnose;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitExportImport;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitTasksRouteAndValidate;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitPromptPresets;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitRunLogPanel;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitVersionInfo;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitCronTokenPanel;
use HaoZiTeam\AIPost\Service\Settings\Traits\TraitAdminInjections;

defined('ABSPATH') || exit;

class Setting
{
    use TraitFontTools;
    use TraitDebugLog;
    use TraitImageGenCheck;
    use TraitSelfDiagnose;
    use TraitExportImport;
    use TraitTasksRouteAndValidate;
    use TraitPromptPresets;
    use TraitRunLogPanel;
    use TraitVersionInfo;
    use TraitCronTokenPanel;
    use TraitAdminInjections;

    private string $prefix = 'ai-post';
    /**
     * 标记：系统调试与日志面板是否已通过回调渲染。
     */
    protected bool $debug_panel_rendered = false;
    // CA 状态日志输出逻辑已迁移至 TraitSelfDiagnose::maybe_log_ca_status_on_admin_init()
    
    // （方法已迁移至 TraitPromptPresets）

    // （方法已迁移至 TraitPromptPresets）

    // （方法已迁移至 TraitDebugLog）

    // （方法已迁移至 TraitSelfDiagnose）

    // 通信令牌（Cron/REST）面板已迁移至 TraitCronTokenPanel::render_cron_token_panel()

    // 适配 CGPS 的 AJAX 保存：$_POST['data'] 为 JSON，含 ai-post/ai-post-tasks
    // （方法已迁移至 TraitTasksRouteAndValidate）

    // 校验：每个任务的文章步骤最后一项必须“接收回复=true 且 接收回复作为=主体(content)”
    // 若不满足：阻止保存（返回旧值），并设置一次性提示。
    // （方法已迁移至 TraitTasksRouteAndValidate）

    // 在后台顶部输出一次性提示
    // （方法已迁移至 TraitTasksRouteAndValidate）

    // 页脚注入：AJAX 保存失败后，移除灰层并展示友好提示，避免界面卡住
    // （方法已迁移至 TraitTasksRouteAndValidate）

    // AJAX：火山 Ark 文生图外网连通性自检（真调用，最小尺寸）
    // （方法已迁移至 TraitImageGenCheck）

    // AJAX：OpenAI 兼容端点连通性自检（/v1/models）
    // （方法已迁移至 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 与 key（参考 ApiClientService 的优先级，简化为全局 openai-accounts/cardPwd/cardNum）
        $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,
        ]);
    }

    public function maybe_schedule_ai_comments_task_cleanup_on_save($new_value, $old_value, $option)
    {
        try {
            if ($option !== 'ai-post-tasks') {
                return $new_value;
            }
            if (!is_array($new_value) || !is_array($old_value)) {
                return $new_value;
            }
            foreach ($new_value as $task_key => $task) {
                if (!is_array($task)) { continue; }
                $new_enabled = isset($task['task-ai-comments']) ? (bool)$task['task-ai-comments'] : true;
                $old_task = $old_value[$task_key] ?? null;
                $old_enabled = true;
                if (is_array($old_task) && array_key_exists('task-ai-comments', $old_task)) {
                    $old_enabled = (bool)$old_task['task-ai-comments'];
                }
                if ($old_enabled && !$new_enabled) {
                    $task_key_str = (string)$task_key;
                    if ($task_key_str === '') { continue; }
                    if (!\wp_next_scheduled('aipost_ai_comments_task_cleanup', [$task_key_str])) {
                        \wp_schedule_single_event(time() + 30, 'aipost_ai_comments_task_cleanup', [$task_key_str]);
                    }
                }
            }
        } catch (\Throwable $e) {
            \error_log('[AI-Post][AIComments] task cleanup schedule error: ' . $e->getMessage());
        }
        return $new_value;
    }

    // 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 = []; }

        // 读取 ImageGenerations 相关配置（API级尺寸已移除，这里仅展示占位尺寸）
        $model = (string) ($opts['doubao-imagegen-model'] ?? 'doubao-seedream-3-0-t2i-250415');
        $size  = '1024x768';
        $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：阿里云（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');
        // API级尺寸与数量已移除，由任务级决定；此处仅用于展示时给出模型对应的推荐尺寸与固定 n=1 的占位
        $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; }
            }
        }

        $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,
                // qwen-image 专属
                'prompt_extend' => ($model === 'qwen-image') ? $promptExtend : null,
                'watermark'     => ($model === 'qwen-image') ? $watermark : null,
                // wanx-v1 专属
                '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');
        // 连接性自检为最小有效调用，这里采用各模型推荐的最小尺寸，数量固定 1。
        $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 使用新版 image-generation/generation + messages 结构，其余模型沿用 text2image/image-synthesis + prompt
        if ($model === 'wan2.6-image') {
            $endpoint = 'https://dashscope.aliyuncs.com/api/v1/services/aigc/image-generation/generation';

            $payload = [
                'model' => $model,
                'input' => [
                    'messages' => [
                        [
                            'role' => 'user',
                            'content' => [
                                [
                                    'type' => 'text',
                                    'text' => 'Connectivity test from AI-Post plugin. Please generate a simple abstract background. This is a minimal test call.',
                                ],
                            ],
                        ],
                    ],
                ],
                'parameters' => [
                    'size' => $size,
                    'n'    => $n,
                    'enable_interleave' => true,
                ],
            ];
        } else {
            $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,
        ];
        if ($model === 'wan2.6-image') {
            $headers[] = 'X-DashScope-Async: enable';
        }

        $pluginRoot = \dirname(__DIR__);
        $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) : '';
        $data = json_decode((string)$response, true);
        if (!is_array($data)) {
            \wp_send_json_error([
                'message' => '响应解析失败',
                'status' => $httpCode,
                'duration_ms' => $duration,
                '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,
                'snippet' => $snippet,
            ]);
        }

        \wp_send_json_success([
            'status' => $httpCode,
            'duration_ms' => $duration,
            '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 = []; }

        // 读取 ImageGenerations 相关配置
        $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);

        // 检查是否存在至少一个 ImageGenerations 令牌
        $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),
        ]);
    }

    // （方法已迁移至 TraitDebugLog）

    // （方法已迁移至 TraitDebugLog）

    // （方法已迁移至 TraitDebugLog）

    // （方法已迁移至 TraitDebugLog）

    public function __construct()
    {
        \add_filter('cgps_welcome_page', '__return_false');

        $this->compat_disable_broken_link_checker_seo_in_ai_post();
        \add_action('admin_enqueue_scripts', [$this, 'compat_disable_broken_link_checker_seo_in_ai_post'], 0);
        \add_action('admin_enqueue_scripts', [$this, 'compat_dequeue_broken_link_checker_seo_assets_in_ai_post'], 9999);

        // 恢复：初始化、资源与保存前校验钩子
        $this->admin_init();
        \add_action('admin_enqueue_scripts', function(){
            \wp_enqueue_code_editor(['type' => 'text/css']);
        });
        // 保存前校验：文章步骤最后一步必须为“主体且接收回复”
        \add_filter('pre_update_option_ai-post', [$this, 'validate_steps_before_save'], 10, 3);
        // 兼容某些版本/分离存储：任务可能保存在 ai-post-tasks 选项
        \add_filter('pre_update_option_ai-post-tasks', [$this, 'validate_steps_before_save'], 10, 3);
        // 只读日志回显：任务保存前把关键图像生成开关与参数输出到 debug.log（不改变入库值）
        \add_filter('pre_update_option_ai-post-tasks', [$this, 'log_task_flags_on_save'], 20, 3);
        \add_filter('pre_update_option_ai-post-tasks', [$this, 'maybe_schedule_ai_comments_task_cleanup_on_save'], 30, 3);
        // 在 CGPS 提交阶段进行一次校验
        \add_filter('ajax_save', [$this, 'validate_steps_on_ajax_save']);
        // 错误提示与UI恢复
        \add_action('admin_notices', [$this, 'maybe_show_steps_validation_notice']);
        \add_action('admin_footer', [$this, 'inject_ajax_fail_recovery_js']);
        // 方案A：统一写入 ai-post-tasks（在通过校验之后再路由）
        \add_filter('pre_update_option_ai-post', [$this, 'route_tasks_on_save'], 20, 3);

        // 方案A（读取端合并）：任何位置读取 ai-post 时，自动把 ai-post-tasks 合并到内存视图，
        // 确保设置页/表单渲染等仍能看到任务列表，避免“刷新后任务消失”的错觉。
        \add_filter('option_ai-post', [$this, 'merge_tasks_into_ai_post'], 10, 1);

        // 展示一次性提示：任务已被路由到独立选项
        \add_action('admin_notices', [$this, 'maybe_show_tasks_routed_notice']);

        // 保存前：阻止过期卡密入库，并在后台显示一次性错误提示
        \add_filter('pre_update_option_ai-post', [$this, 'guard_expired_on_save'], 5, 3);
        \add_action('admin_notices', [$this, 'maybe_show_expired_notice']);

        // AJAX：运行日志表格与保留天数
        \add_action('wp_ajax_ai_post_get_runlog_table', [$this, 'ajax_get_runlog_table']);
        \add_action('wp_ajax_ai_post_save_retention_days', [$this, 'handle_save_retention_days']);

        // AJAX：通信令牌（Cron/REST）生成/获取/清空
        \add_action('wp_ajax_aipost_generate_cron_token', [$this, 'ajax_generate_cron_token']);
        \add_action('wp_ajax_aipost_get_cron_token', [$this, 'ajax_get_cron_token']);
        \add_action('wp_ajax_aipost_clear_cron_token', [$this, 'ajax_clear_cron_token']);

        // 前端：授权过期则禁用保存按钮
        \add_action('admin_footer', [$this, 'inject_license_expire_guard_js']);

        // AJAX：调试日志 预览/下载/删除
        \add_action('wp_ajax_ai_post_preview_debug_log', [$this, 'ajax_preview_debug_log']);
        \add_action('wp_ajax_ai_post_download_debug_log', [$this, 'ajax_download_debug_log']);
        \add_action('wp_ajax_ai_post_delete_debug_log', [$this, 'ajax_delete_debug_log']);
        
        // AJAX：授权即时校验
        \add_action('wp_ajax_ai_post_check_license', [$this, 'ajax_check_license']);
        
        // AJAX：连通性与参数自检
        \add_action('wp_ajax_ai_post_connectivity_check', [$this, 'ajax_connectivity_check']);
        \add_action('wp_ajax_ai_post_volc_imagegen_check', [$this, 'ajax_volc_imagegen_check']);
        \add_action('wp_ajax_ai_post_volc_imagegen_connectivity', [$this, 'ajax_volc_imagegen_connectivity']);
        \add_action('wp_ajax_ai_post_aliyun_imagegen_check', [$this, 'ajax_aliyun_imagegen_check']);
        \add_action('wp_ajax_ai_post_aliyun_imagegen_connectivity', [$this, 'ajax_aliyun_imagegen_connectivity']);
        
        // AJAX：今日统计
        \add_action('wp_ajax_ai_post_debug_log_stats', [$this, 'ajax_debug_log_stats']);

        // 导出/导入设置（AJAX）
        if (is_admin()) {
            \add_action('wp_ajax_ai_post_export_settings', [$this, 'handle_export_settings']);
            \add_action('wp_ajax_ai_post_import_settings', [$this, 'handle_import_settings']);
            \add_action('wp_ajax_ai_post_self_diagnose', [$this, 'ajax_self_diagnose']);
        }
    }

    public function compat_disable_broken_link_checker_seo_in_ai_post(): void
    {
        if (!is_admin()) {
            return;
        }
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (!isset($_GET['page']) || $_GET['page'] !== 'ai-post') {
            return;
        }
        if (!function_exists('aioseoBrokenLinkChecker')) {
            return;
        }

        try {
            $blc = aioseoBrokenLinkChecker();
            if (is_object($blc) && isset($blc->main) && is_object($blc->main)) {
                \remove_action('admin_enqueue_scripts', [$blc->main, 'enqueueStandaloneApp']);
                \remove_action('admin_footer', [$blc->main, 'adminFooter']);
            }

            if (is_object($blc) && isset($blc->notifications) && is_object($blc->notifications)) {
                \remove_action('admin_notices', [$blc->notifications, 'renderNotices']);
            }

            if (is_object($blc) && isset($blc->admin) && is_object($blc->admin)) {
                \remove_action('admin_footer', [$blc->admin, 'addAioseoModalPortal']);
            }

            if (is_object($blc) && isset($blc->core) && is_object($blc->core) && isset($blc->core->assets) && is_object($blc->core->assets)) {
                \remove_filter('script_loader_tag', [$blc->core->assets, 'scriptLoaderTag'], 10);
            }
        } catch (\Throwable $e) {
            return;
        }
    }

    public function compat_dequeue_broken_link_checker_seo_assets_in_ai_post(): void
    {
        if (!is_admin()) {
            return;
        }
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (!isset($_GET['page']) || $_GET['page'] !== 'ai-post') {
            return;
        }

        global $wp_scripts, $wp_styles;

        if ($wp_scripts instanceof \WP_Scripts && is_array($wp_scripts->registered)) {
            foreach ($wp_scripts->registered as $handle => $obj) {
                $src = '';
                if (is_object($obj) && isset($obj->src)) {
                    $src = (string)$obj->src;
                }
                $handleStr = (string)$handle;
                $matchHandle = (
                    0 === strpos($handleStr, 'aioseoBrokenLinkChecker') ||
                    false !== strpos($handleStr, 'aioseo-blc') ||
                    false !== strpos($handleStr, 'aioseo_blc')
                );
                if (
                    false !== strpos($src, 'broken-link-checker-seo') ||
                    false !== strpos($src, 'aioseo-blc') ||
                    $matchHandle
                ) {
                    \wp_dequeue_script($handle);
                    \wp_deregister_script($handle);
                }
            }
        }

        if ($wp_styles instanceof \WP_Styles && is_array($wp_styles->registered)) {
            foreach ($wp_styles->registered as $handle => $obj) {
                $src = '';
                if (is_object($obj) && isset($obj->src)) {
                    $src = (string)$obj->src;
                }
                $handleStr = (string)$handle;
                $matchHandle = (
                    0 === strpos($handleStr, 'aioseoBrokenLinkChecker') ||
                    false !== strpos($handleStr, 'aioseo-blc') ||
                    false !== strpos($handleStr, 'aioseo_blc')
                );
                if (
                    false !== strpos($src, 'broken-link-checker-seo') ||
                    false !== strpos($src, 'aioseo-blc') ||
                    $matchHandle
                ) {
                    \wp_dequeue_style($handle);
                    \wp_deregister_style($handle);
                }
            }
        }
    }
    public function admin_init(): void
    {
        // 节流：5 分钟内只打印一次“正在初始化插件设置...”，避免频繁刷屏
        $init_throttle_key = 'aipost_admin_init_log_last';
        $should_log_init = true;
        if (function_exists('get_transient')) {
            $should_log_init = !get_transient($init_throttle_key);
        }
        if ($should_log_init) {
            error_log('正在初始化插件设置...');
            if (function_exists('set_transient')) {
                set_transient($init_throttle_key, time(), 5 * MINUTE_IN_SECONDS);
            }
        }

        // 仅在本插件设置页输出“方式二字体工具”前端脚本（从 Plugin.php 迁移）
        if (isset($_GET['page']) && $_GET['page'] === 'ai-post') { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            \add_action('admin_footer', [$this, 'render_font_tools_inline']);
            // 兜底：若 CGPS 未调用回调渲染“系统调试与日志”面板，则在页脚兜底输出一次
            \add_action('admin_footer', [$this, 'maybe_fallback_render_debug_panel'], 99);
        }

        // 追加（节流）：初始化阶段输出一次当前 CA 状态（逻辑迁移至 TraitSelfDiagnose）
        if (method_exists($this, 'maybe_log_ca_status_on_admin_init')) {
            $this->maybe_log_ca_status_on_admin_init();
        } else {
            // 兼容旧缓存环境，避免致命错误
            error_log('AI Post SSL: maybe_log_ca_status_on_admin_init() not available yet (cache/autoload), skip this round.');
        }
        // 初始化后台菜单与设置（占位符已移除）
        
        // 构建版本显示文本（迁移至 TraitVersionInfo）
        $version_text = $this->build_version_footer_text();

        // 修改菜单注册方式，以支持多站点
        $menu_type = 'submenu';
        $menu_parent = 'options-general.php';
        $capability = 'manage_options';

        // 如果是在子站点中，使用子站点菜单
        if (is_multisite() && !is_main_site() && !is_network_admin()) {
            $menu_type = 'submenu';
            $menu_parent = 'options-general.php';
            $capability = 'manage_options';
        }

        CGPS::createOptions($this->prefix, [
            'framework_title' => '插件设置',
            'menu_title' => 'AI Post',
            'menu_slug' => 'ai-post',
            'menu_type' => $menu_type,
            'menu_parent' => $menu_parent,
            'capability' => $capability,
            'show_bar_menu' => false,
            'show_sub_menu' => false,
            'show_search' => false,
            'footer_text' => $version_text,
            'theme' => 'light',
        ]);

        CGPS::createSection($this->prefix, [
            'title' => '插件授权',
            'fields' => [
                [
                    'type' => 'callback',
                    'title' => '授权操作',
                    'function' => [$this, 'render_license_block'],
                ],

                [
                    'id' => 'cardNum',
                    'type' => 'text',
                    'title' => '授权卡号',
                    'desc' => '输入购买的授权卡号：为19为纯数字',
                ],
                [
                    'id' => 'cardPwd',
                    'type' => 'text',
                    'title' => '授权卡密',
                    'desc' => '输入购买的授权卡密：字母和数字组合，保存后刷新页面查看授权期限',
                ]

            ],
        ]);

        CGPS::createSection($this->prefix, [
            'title' => 'API设置',
            'fields' => [
                // API 服务器类型选择
                [
                    'id' => 'api-server-type',
                    'type' => 'button_set',
                    'title' => 'API 服务器类型',
                    'options' => [
                        'custom' => '<div class="server-type-block"><img src="' . plugins_url('/assets/images/slapi.png', __FILE__) . '" class="api-logo" alt="自定义服务器"><span>自定义服务器</span></div>',
                        'zhipu' => '<div class="server-type-block"><img src="data:image/svg+xml;utf8,<?xml version=\'1.0\' encoding=\'UTF-8\'?><svg xmlns=\'http://www.w3.org/2000/svg\' width=\'24\' height=\'24\' viewBox=\'0 0 24 24\'><rect x=\'0\' y=\'0\' width=\'24\' height=\'24\' rx=\'4\' fill=\'%23111827\'/><text x=\'50%\' y=\'50%\' dominant-baseline=\'middle\' text-anchor=\'middle\' font-family=\'system-ui, -apple-system, Segoe UI, Roboto\' font-size=\'12\' fill=\'%23ffffff\'>谱</text></svg>" class="api-logo" alt="智谱AI"><span>智谱AI</span></div>',
                        'spark' => '<div class="server-type-block"><img src="data:image/svg+xml;utf8,<?xml version=\'1.0\' encoding=\'UTF-8\'?><svg xmlns=\'http://www.w3.org/2000/svg\' width=\'24\' height=\'24\' viewBox=\'0 0 24 24\'><rect x=\'0\' y=\'0\' width=\'24\' height=\'24\' rx=\'4\' fill=\'%23f97316\'/><text x=\'50%\' y=\'50%\' dominant-baseline=\'middle\' text-anchor=\'middle\' font-family=\'system-ui, -apple-system, Segoe UI, Roboto\' font-size=\'12\' fill=\'%23ffffff\'>火</text></svg>" class="api-logo" alt="讯飞星火"><span>讯飞星火</span></div>',
                        'deepseek' => '<div class="server-type-block"><img src="' . plugins_url('/assets/images/deepseek-copy.png', __FILE__) . '" class="api-logo" alt="DeepSeek API"><span>DeepSeek API</span></div>',
                        'moonshot' => '<div class="server-type-block"><img src="data:image/svg+xml;utf8,<?xml version=\'1.0\' encoding=\'UTF-8\'?><svg xmlns=\'http://www.w3.org/2000/svg\' width=\'24\' height=\'24\' viewBox=\'0 0 24 24\'><rect x=\'0\' y=\'0\' width=\'24\' height=\'24\' rx=\'4\' fill=\'%230b1220\'/><text x=\'50%\' y=\'50%\' dominant-baseline=\'middle\' text-anchor=\'middle\' font-family=\'system-ui, -apple-system, Segoe UI, Roboto\' font-size=\'10\' fill=\'%23ffffff\'>Kimi</text></svg>" class="api-logo" alt="Moonshot"><span>Kimi</span></div>',
                        'doubao' => '<div class="server-type-block"><img src="' . plugins_url('/assets/images/huoshan.png', __FILE__) . '" class="api-logo" alt="豆包 API"><span>豆包 API <span class="t2i-badge" title="支持文生图">文生图</span></span></div>',
                        'bai-lian' => '<div class="server-type-block"><img src="' . plugins_url('/assets/images/alibaba.png', __FILE__) . '" class="api-logo" alt="阿里百炼 API"><span>阿里百炼 API <span class="t2i-badge" title="支持文生图">文生图</span></span></div>',
                        // 使用内联 SVG 图标，避免缺失 baidu.png
                        'wenxin' => '<div class="server-type-block"><img src="data:image/svg+xml;utf8,<?xml version=\'1.0\' encoding=\'UTF-8\'?><svg xmlns=\'http://www.w3.org/2000/svg\' width=\'24\' height=\'24\' viewBox=\'0 0 24 24\'><defs/><rect x=\'0\' y=\'0\' width=\'24\' height=\'24\' rx=\'4\' fill=\'%232271b1\'/><text x=\'50%\' y=\'50%\' dominant-baseline=\'middle\' text-anchor=\'middle\' font-family=\'system-ui, -apple-system, Segoe UI, Roboto\' font-size=\'12\' fill=\'%23ffffff\'>度</text></svg>" class="api-logo" alt="文心一言 API"><span>文心一言 API</span></div>'
                    ],
                    'default' => 'custom',
                    'desc' => '默认使用选择的 API 服务器，不同的任务可使用不同的api服务。',
                    'class' => 'server-type-selector',
                    'after' => '<style>
                        .server-type-selector .cgps--button-group {
                            display: flex;
                            gap: 10px;
                            margin-bottom: 15px;
                        }
                        .server-type-selector .cgps--button {
                            flex: 1;
                            max-width: 180px;
                            border: 1px solid #ddd;
                            border-radius: 6px;
                            padding: 10px;
                            text-align: center;
                            cursor: pointer;
                            transition: all 0.3s ease;
                            background: #fff; /* 确保背景是白色 */
                            height: auto; /* 允许按钮自适应高度 */
                        }
                        .server-type-selector .cgps--button:hover {
                            border-color: #2271b1;
                            background: #f0f6fc;
                        }
                        .server-type-selector .cgps--active {
                            border-color: #2271b1;
                            background: #f0f6fc;
                        }
                        .server-type-block {
                            display: flex;
                            flex-direction: column;
                            align-items: center;
                            gap: 5px; /* 增加一点间距 */
                        }
                        /* 移除旧的 i 标签样式 */
                        /* .server-type-block i { ... } */
                        .api-logo { /* 新增图片样式 */
                            width: 24px; /* 或您希望的尺寸 */
                            height: 24px; /* 或您希望的尺寸 */
                            margin-bottom: 5px; /* 图片下方间距 */
                            object-fit: contain; /* 保持图片比例 */
                        }
                        .server-type-block span {
                            font-size: 13px;
                            font-weight: 500;
                            color: #2271b1;
                        }
                        .server-type-block small {
                            font-size: 11px;
                            color: #666;
                        }
                        .t2i-badge {
                            display: inline-block;
                            margin-left: 6px;
                            padding: 1px 6px;
                            font-size: 10px;
                            line-height: 1.6;
                            color: #fff;
                            background: #2271b1; /* WP blue */
                            border-radius: 9999px;
                            vertical-align: middle;
                        }
                        /* 提高优先级，避免被 .server-type-block span 的颜色覆盖 */
                        .server-type-block .t2i-badge { color: #fff !important; }
                    </style>'
                ],
                // 自定义服务器配置
                [
                    'id' => 'openai-api-server',
                    'type' => 'text',
                    'title' => 'API 服务器',
                    'subtitle' => 'API 接口地址',
                    'desc' => '使用默认API服务器地址https://sk.slapi.cn/</code>',
                    'default' => 'https://sk.slapi.cn/',
                    'dependency' => [['api-server-type', '==', 'custom']]
                ],

                // DeepSeek API 和豆包 API 地址已内置，无需用户配置
                // 自定义服务器令牌配置
                [
                    'id' => 'openai-accounts',
                    'type' => 'group',
                    'title' => '令牌列表',
                    'subtitle' => '添加 AI 令牌',
                    'desc' => '添加多个 AI 令牌，将会自动进行轮询，以降低账号被限制的风险',
                    'button_title' => '添加令牌',
                    'accordion_title_number' => true,
                    'dependency' => [['api-server-type', '==', 'custom']],
                    'fields' => [
                        [
                            'id' => 'account-note',
                            'type' => 'text',
                            'title' => '令牌备注',
                            'desc' => '令牌备注，用于区分令牌',
                        ],
                        [
                            'id' => 'account-secret-key',
                            'type' => 'text',
                            'title' => '令牌',
                            'subtitle' => 'sk-开头的Key',
                            'desc' => '前后都不要有空格！！！,<a href="https://sk.slapi.cn/" target="_blank">获取key</a>',
                        ],
                        [
                            'id' => 'model-selection',
                            'type' => 'select',
                            'title' => '选择模型',
                            'options' => [
                                'gpt-4o-mini' => 'gpt-4o-mini低价稳定高效',
                                'gpt-4o-mini-2024-07-18' => 'gpt-4o-mini-2024-07-18',
                                'gpt-4o' => 'gpt-4o',
                                'gpt-4o-2024-05-13' => 'gpt-4o-2024-05-13',
                                'gpt-3.5-turbo-0613' => 'gpt-3.5-turbo-0613',
                                'custom' => '自定义模型/不懂请勿配置'
                            ],
                            'desc' => '选择要使用的 AI 模型，强烈推荐使用gpt-4o-mini，或选择自定义模型',
                        ],
                        [
                            'id' => 'custom-model-name',
                            'type' => 'text',
                            'title' => '自定义模型名称',
                            'subtitle' => '输入自定义的模型名称',
                            'desc' => '当选择"自定义模型"时，请在此输入完整的模型名称',
                            'dependency' => [['model-selection', '==', 'custom']],
                        ],
                    ],
                ],

                // Moonshot（Kimi） 令牌配置
                [
                    'id' => 'moonshot-accounts',
                    'type' => 'group',
                    'title' => 'Moonshot（Kimi） 令牌列表',
                    'subtitle' => '添加 Moonshot API Key（支持多账号轮询）',
                    'desc' => 'Moonshot 官方接口 base URL 已内置为 https://api.moonshot.cn/v1/ 。',
                    'button_title' => '添加令牌',
                    'accordion_title_number' => true,
                    'dependency' => [['api-server-type', '==', 'moonshot']],
                    'fields' => [
                        [
                            'id' => 'account-note',
                            'type' => 'text',
                            'title' => '令牌备注',
                            'desc' => '令牌备注，用于区分令牌',
                        ],
                        [
                            'id' => 'account-secret-key',
                            'type' => 'text',
                            'title' => 'API Key',
                            'subtitle' => 'Moonshot API Key',
                            'desc' => '前后都不要有空格！！！',
                        ],
                        [
                            'id' => 'model-selection',
                            'type' => 'select',
                            'title' => '选择模型',
                            'options' => [
                                'moonshot-v1-8k' => 'moonshot-v1-8k（短文本，上下文长度 8k）',
                                'moonshot-v1-32k' => 'moonshot-v1-32k（长文本，上下文长度 32k）',
                                'moonshot-v1-128k' => 'moonshot-v1-128k（超长文本，上下文长度 128k）',
                                'kimi-k2.5' => 'kimi-k2.5（上下文长度 256k，全能的模型）',
                                'kimi-k2-0905-preview' => 'kimi-k2-0905-preview（上下文长度 256k）',
                                'kimi-k2-0711-preview' => 'kimi-k2-0711-preview（上下文长度 128k）',
                                'kimi-k2-turbo-preview' => 'kimi-k2-turbo-preview（上下文长度 256k，K2 的高速版本）',
                                'kimi-k2-thinking' => 'kimi-k2-thinking（支持 256k 上下文，K2 长思考模型，支持多步工具调用与思考，擅长解决更复杂的问题）',
                                'kimi-k2-thinking-turbo' => 'kimi-k2-thinking-turbo（K2 长思考模型的高速版本，支持 256k 上下文，擅长深度推理，输出速度提升至每秒 60-100 tokens）',
                                'custom' => '自定义模型/不懂请勿配置'
                            ],
                            'desc' => '选择要使用的 Moonshot 模型，或选择自定义模型。',
                        ],
                        [
                            'id' => 'custom-model-name',
                            'type' => 'text',
                            'title' => '自定义模型名称',
                            'subtitle' => '输入自定义的模型名称',
                            'desc' => '当选择"自定义模型"时，请在此输入完整的模型名称',
                            'dependency' => [['model-selection', '==', 'custom']],
                        ],
                    ],
                ],

                // 智谱AI 令牌配置
                [
                    'id' => 'zhipu-accounts',
                    'type' => 'group',
                    'title' => '智谱AI 令牌列表',
                    'subtitle' => '添加 智谱AI 令牌（支持多账号轮询）',
                    'desc' => '添加智谱 BigModel API Key。支持为每个账号选择默认模型。',
                    'button_title' => '添加令牌',
                    'accordion_title_number' => true,
                    'dependency' => [['api-server-type', '==', 'zhipu']],
                    'fields' => [
                        [
                            'id' => 'account-note',
                            'type' => 'text',
                            'title' => '令牌备注',
                            'desc' => '令牌备注，用于区分令牌',
                        ],
                        [
                            'id' => 'account-secret-key',
                            'type' => 'text',
                            'title' => 'API Key',
                            'subtitle' => '智谱 BigModel API Key',
                            'desc' => '前后都不要有空格！！！<a href="https://bigmodel.cn/usercenter/proj-mgmt/apikeys" target="_blank">获取key</a>',
                        ],
                        [
                            'id' => 'model-selection',
                            'type' => 'select',
                            'title' => '选择模型',
                            'options' => [
                                'glm-4.7-flashx' => 'glm-4.7-flashx（推荐-轻量高速/翻译、长文本、情感/上下文200k/最大输出128k）',
                                'glm-4.7-flash' => 'glm-4.7-flash（免费普惠/200k上下文/最大输出128k）',
                                'glm-4-flash-250414' => 'glm-4-flash-250414（免费多语言/128k上下文/最大输出16k）',
                                'glm-4.7' => 'glm-4.7（高智能/200k上下文/最大输出128k）',
                                'glm-5' => 'glm-5（编程对齐claude）',
                                'custom' => '自定义模型/不懂请勿配置',
                            ],
                            'desc' => '选择要使用的智谱模型，或使用自定义模型名称。<a href="https://docs.bigmodel.cn/cn/guide/start/model-overview" target="_blank">模型列表</a>',
                        ],
                        [
                            'id' => 'custom-model-name',
                            'type' => 'text',
                            'title' => '自定义模型名称',
                            'subtitle' => '输入自定义的模型名称',
                            'desc' => '当选择"自定义模型"时，请在此输入完整的模型名称',
                            'dependency' => [['model-selection', '==', 'custom']],
                        ],
                    ],
                ],

                // 讯飞星火 令牌配置
                [
                    'id' => 'spark-accounts',
                    'type' => 'group',
                    'title' => '讯飞星火 令牌列表',
                    'subtitle' => '添加 讯飞星火 APIPassword（支持多账号轮询）',
                    'desc' => '添加讯飞星火 HTTP 接口的 APIPassword。注意：不同模型/不同版本的 APIPassword 不共用（x1/spark-x/spark-pro/spark-max 使用 v2 接口，lite 使用 v1 接口）。如果选择自定义模型名称为 spark-pro 或 spark-max，将优先使用对应的 APIPassword 字段。获取入口：<a href="https://console.xfyun.cn/services/sparkapiCenter" target="_blank">https://console.xfyun.cn/services/sparkapiCenter</a>',
                    'button_title' => '添加令牌',
                    'accordion_title_number' => true,
                    'dependency' => [['api-server-type', '==', 'spark']],
                    'fields' => [
                        [
                            'id' => 'account-note',
                            'type' => 'text',
                            'title' => '令牌备注',
                            'desc' => '令牌备注，用于区分令牌',
                        ],
                        [
                            'id' => 'account-secret-key-v2',
                            'type' => 'text',
                            'title' => 'APIPassword（v2：x1 / spark-x）',
                            'subtitle' => '用于spark-x模型',
                            'desc' => '前后都不要有空格！！！',
                        ],
                        [
                            'id' => 'account-secret-key-pro',
                            'type' => 'text',
                            'title' => 'APIPassword（v2：spark-pro）',
                            'subtitle' => '当模型为 spark-pro 时使用',
                            'desc' => '前后都不要有空格！！！',
                        ],
                        [
                            'id' => 'account-secret-key-max',
                            'type' => 'text',
                            'title' => 'APIPassword（v2：spark-max）',
                            'subtitle' => '当模型为 spark-max 时使用',
                            'desc' => '前后都不要有空格！！！',
                        ],
                        [
                            'id' => 'account-secret-key-v1',
                            'type' => 'text',
                            'title' => 'APIPassword（v1：lite）',
                            'subtitle' => 'lite模型使用',
                            'desc' => '前后都不要有空格！！！',
                        ],
                        [
                            'id' => 'model-selection',
                            'type' => 'select',
                            'title' => '选择模型',
                            'options' => [
                                'x1' => 'Spark X1.5（x1）',
                                'spark-x' => 'Spark X2（spark-x）',
                                'lite' => 'Spark Lite（lite）',
                                'spark-pro' => 'Spark Pro（spark-pro）',
                                'spark-max' => 'Spark Max（spark-max）',
                                'custom' => '自定义模型/不懂请勿配置',
                            ],
                            'desc' => '支持 x1 / spark-x / lite / spark-pro / spark-max 或自定义模型名称；请确保所填 APIPassword 与模型版本对应。',
                        ],
                        [
                            'id' => 'custom-model-name',
                            'type' => 'text',
                            'title' => '自定义模型名称',
                            'subtitle' => '输入自定义的模型名称（例如 spark-pro / spark-max）',
                            'desc' => '当选择"自定义模型"时，请在此输入完整的模型名称。',
                            'dependency' => [['model-selection', '==', 'custom']],
                        ],
                    ],
                ],
                // 文心一言 账号配置
                [
                    'id' => 'wenxin-accounts',
                    'type' => 'group',
                    'title' => '文心一言 账号列表',
                    'subtitle' => '添加 文心一言 账号（支持多账号轮询）',
                    'desc' => '添加百度智能云千帆（文心一言）账号的 API Key 与 Secret Key。支持为每个账号单独设置默认参数。',
                    'button_title' => '添加账号',
                    'accordion_title_number' => true,
                    'dependency' => [['api-server-type', '==', 'wenxin']],
                    'fields' => [
                        [
                            'id' => 'account-note',
                            'type' => 'text',
                            'title' => '账号备注',
                            'desc' => '用于区分不同账号，可留空',
                        ],
                        [
                            'id' => 'api-key',
                            'type' => 'text',
                            'title' => 'API Key',
                            'subtitle' => '百度智能云 千帆平台 API Key',
                            'desc' => '在百度智能云千帆平台控制台创建应用后获取 API Key。获取页面：<a href="https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application/v1" target="_blank">千帆控制台 → 应用与APIKey</a>',
                        ],
                        [
                            'id' => 'secret-key',
                            'type' => 'text',
                            'title' => 'Secret Key',
                            'subtitle' => '百度智能云 千帆平台 Secret Key',
                            'desc' => '与 API Key 配对使用。若选择直签鉴权（signature），将用 AK/SK 进行签名。获取页面：<a href="https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application/v1" target="_blank">千帆控制台 → 应用与APIKey</a>',
                        ],
                        [
                            'id' => 'model-selection',
                            'type' => 'select',
                            'title' => '选择模型',
                            'options' => \HaoZiTeam\AIPost\Service\Features\WenXinModelCatalog::optionsForSelect(),
                            'desc' => '选择千帆模型（接入点ID全部为小写）。将根据模型自动应用最大输出上限，实际可用模型以账号开通为准。',
                        ],
                        [
                            'id' => 'temperature',
                            'type' => 'number',
                            'title' => '温度 (temperature)',
                            'subtitle' => '控制随机性，范围 0.0 - 1.0，建议 0.7',
                            'min' => 0.0,
                            'max' => 1.0,
                            'step' => 0.1,
                            'unit' => ' ',
                        ],
                        // 已移除：top_p, penalty_score, max_output_tokens, timeout, auth_mode, stream, stop, user_id, disable_search, enable_citation
                    ],
                ],
                // DeepSeek 令牌配置
                [
                    'id' => 'deepseek-accounts',
                    'type' => 'group',
                    'title' => 'DeepSeek 令牌列表',
                    'subtitle' => '添加 DeepSeek 令牌',
                    'desc' => '添加 DeepSeek API 令牌',
                    'button_title' => '添加令牌',
                    'accordion_title_number' => true,
                    'dependency' => [['api-server-type', '==', 'deepseek']],
                    'fields' => [
                        [
                            'id' => 'account-note',
                            'type' => 'text',
                            'title' => '令牌备注',
                            'desc' => '令牌备注，用于区分令牌',
                        ],
                        [
                            'id' => 'account-secret-key',
                            'type' => 'text',
                            'title' => '令牌',
                            'subtitle' => 'DeepSeek API Key',
                            'desc' => '前后都不要有空格！！！,<a href="https://platform.deepseek.com/api_keys" target="_blank">获取key</a>',
                        ],
                        [
                            'id' => 'model-selection',
                            'type' => 'select',
                            'title' => '选择模型',
                            'options' => [
                                'deepseek-chat' => 'DeepSeek-V3',
                                'deepseek-reasoner' => 'DeepSeek-R1',
                                'custom' => '自定义模型/不懂请勿配置'
                            ],
                            'desc' => '选择要使用的 DeepSeek 模型，或选择自定义模型',
                        ],
                        [
                            'id' => 'custom-model-name',
                            'type' => 'text',
                            'title' => '自定义模型名称',
                            'subtitle' => '输入自定义的模型名称',
                            'desc' => '当选择"自定义模型"时，请在此输入完整的模型名称<br>deepseek模型和定价：https://api-docs.deepseek.com/zh-cn/quick_start/pricing',
                            'dependency' => [['model-selection', '==', 'custom']],
                        ],
                    ],
                ],
                // 豆包 令牌配置 (移动到这里)
                [
                    'id' => 'doubao-accounts',
                    'type' => 'group',
                    'title' => '豆包 令牌列表',
                    'subtitle' => '添加 豆包 令牌',
                    'desc' => '添加 豆包 API 令牌',
                    'button_title' => '添加令牌',
                    'accordion_title_number' => true,
                    'dependency' => [['api-server-type', '==', 'doubao']],
                    'fields' => [
                        [
                            'id' => 'account-note',
                            'type' => 'text',
                            'title' => '令牌备注',
                            'desc' => '令牌备注，用于区分令牌',
                        ],
                        [
                            'id' => 'account-secret-key',
                            'type' => 'text',
                            'title' => '令牌',
                            'subtitle' => '豆包 API Key',
                            'desc' => '前后都不要有空格！！！:<a href="https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey" target="_blank">获取key</a>',
                        ],
                        [
                            'id' => 'model-selection',
                            'type' => 'select',
                            'title' => '选择模型',
                            'options' => [
                                'doubao-seed-2-0-mini-260215' => 'doubao-seed-2-0-mini-260215',
                                'doubao-1-5-lite-32k-250115' => 'doubao-1-5-lite-32k-250115',
                                'doubao-1-5-pro-32k-250115' => 'doubao-1-5-pro-32k-250115',
                                'doubao-seed-2-0-pro-260215' => 'doubao-seed-2-0-pro-260215',
                                'doubao-seed-2-0-lite-260215' => 'doubao-seed-2-0-lite-260215',
                                'doubao-seed-2-0-code-preview-260215' => 'doubao-seed-2-0-code-preview-260215',
                                'doubao-seed-1-8-251228' => 'doubao-seed-1-8-251228',
                                'doubao-seed-1-6-flash-250828' => 'doubao-seed-1-6-flash-250828',
                                'doubao-seed-1-6-vision-250815' => 'doubao-seed-1-6-vision-250815',
                                'doubao-seed-1-6-lite-251015' => 'doubao-seed-1-6-lite-251015',
                                'glm-4-7-251222' => 'glm-4-7-251222',
                                'deepseek-v3-2-251201' => 'deepseek-v3-2-251201',
                                'deepseek-v3-1-terminus' => 'deepseek-v3-1-terminus',
                                'deepseek-r1-250528' => 'deepseek-r1-250528',
                                'deepseek-v3-250324' => 'deepseek-v3-250324',
                                'custom' => '自定义模型/不懂请勿配置'
                            ],
                            'desc' => '选择要使用的豆包模型，或选择自定义模型',
                        ],
                        [
                            'id' => 'custom-model-name',
                            'type' => 'text',
                            'title' => '自定义模型名称',
                            'subtitle' => '输入自定义的模型名称',
                            'desc' => '当选择"自定义模型"时，请在此输入完整的模型名称<br>豆包模型列表及定价：https://www.volcengine.com/docs/82379/1330310',
                            'dependency' => [['model-selection', '==', 'custom']],
                        ],
                        // 新增：豆包温度设置
                        [
                            'id' => 'temperature',
                            'type' => 'number',
                            'title' => '温度 (Temperature)',
                            'subtitle' => '控制生成文本的随机性',
                            'desc' => '值越高越随机，越低越确定。范围 0.0 - 2.0，建议 0.7',
                            'default' => 0.7,
                            'min' => 0.0,
                            'max' => 2.0,
                            'step' => 0.1,
                            'unit' => ' ', // 避免显示默认单位
                        ],
                    ],
                ],
                // 火山引擎/豆包 文生图（ImageGenerations）配置
                [
                    'id' => 'doubao-imagegen-model',
                    'type' => 'select',
                    'title' => '文生图默认模型',
                    'subtitle' => 'ImageGenerations 模型',
                    'options' => [
                        'doubao-seedream-3-0-t2i-250415'  => 'doubao-seedream-3-0-t2i-250415（默认，适用于常规场景）',
                        'doubao-seedream-4-5-251128'       => 'doubao-seedream-4-5-251128（Seedream 4.5，高质量，最小 1920x1920）',
                        'doubao-seedream-4-0-250828'       => 'doubao-seedream-4-0-250828（Seedream 4.0，最小 1920x1920）',
                        'custom'                           => '自定义模型（高级用法，不懂请勿选）',
                    ],
                    'after' => '<div style="max-width:620px;font-size:13px;line-height:1.6;background:#fff3f3;border:1px solid #f5c2c2;border-radius:4px;padding:10px 12px;margin-top:8px;"><strong>文生图（ImageGenerations）默认配置</strong><br>以下配置仅在任务级未覆盖时生效。<br>文档：<a href="https://api.volcengine.com/api-docs/view?serviceCode=ark&version=2024-01-01&action=ImageGenerations" target="_blank">Volcengine Ark ImageGenerations</a></div><div style="max-width:620px;font-size:12px;color:#666;margin-top:6px;">默认使用 doubao-seedream-3-0-t2i-250415，可在任务级或后续扩展中覆盖；选择“自定义模型”仅建议熟悉火山 Ark 文档的高级用户使用。</div>',
                    'default' => 'doubao-seedream-3-0-t2i-250415',
                    'dependency' => [['api-server-type', '==', 'doubao']]
                ],
                // 移除豆包 API 级尺寸设置（改由任务级/实现逻辑决定，避免与任务级配置冲突）
                // 阿里百炼 令牌配置
                [
                    'id' => 'bai-lian-accounts',
                    'type' => 'group',
                    'title' => '阿里百炼 令牌列表',
                    'subtitle' => '添加 阿里百炼 令牌',
                    'desc' => '添加阿里百炼 API 令牌',
                    'button_title' => '添加令牌',
                    'accordion_title_number' => true,
                    'dependency' => [['api-server-type', '==', 'bai-lian']],
                    'fields' => [
                        [
                            'id' => 'account-note',
                            'type' => 'text',
                            'title' => '令牌备注',
                            'desc' => '令牌备注，用于区分令牌',
                        ],
                        [
                            'id' => 'account-secret-key',
                            'type' => 'text',
                            'title' => '令牌',
                            'subtitle' => '阿里百炼 API Key',
                            'desc' => '前后都不要有空格！！！<a href="https://bailian.console.aliyun.com/?tab=model#/api-key" target="_blank">获取key</a>',
                        ],
                        [
                            'id' => 'model-selection',
                            'type' => 'select',
                            'title' => '选择模型',
                            'options' => [
                                'qwen-max' => 'Qwen Max (通义千问旗舰版) - 适合复杂任务，能力最强',
                                'qwen-max-latest' => 'Qwen Max Latest (旗舰版最新) - 始终使用最新版本',
                                'qwen-max-2024-09-19' => 'Qwen Max 2024-09-19 - 稳定旗舰版',
                                'qwen-plus' => 'Qwen Plus (通义千问高性能) - 效果、速度、成本均衡',
                                'qwen-plus-latest' => 'Qwen Plus Latest (高性能最新) - 始终使用最新版本',
                                'qwen-plus-2025-01-25' => 'Qwen Plus 2025-01-25 - 稳定高性能版',
                                'qwen-turbo' => 'Qwen Turbo (通义千问流畅版) - 适合简单任务，速度快、成本低',
                                'qwen-turbo-latest' => 'Qwen Turbo Latest (流畅版最新) - 始终使用最新版本',
                                'qwen-long' => 'Qwen Long (通义千问长文本) - 适合大规模文本分析，支持千万级Token',
                                'qwen-long-latest' => 'Qwen Long Latest (长文本最新) - 始终使用最新版本',
                                'custom' => '自定义模型/不懂请勿配置'
                            ],
                            'desc' => '选择要使用的阿里百炼模型，或选择自定义模型。<br>推荐使用：<br>- 普通文章：Qwen Plus (均衡性能和成本)<br>- 复杂内容：Qwen Max (最强能力)<br>- 简单任务：Qwen Turbo (速度快成本低)<br>- 长文档：Qwen Long (支持超长文本)',
                        ],
                        [
                            'id' => 'custom-model-name',
                            'type' => 'text',
                            'title' => '自定义模型名称',
                            'subtitle' => '输入自定义的模型名称',
                            'desc' => '当选择"自定义模型"时，请在此输入完整的模型名称，如：deepseek-r1、deepseek-v3、deepseek-r1-distill-llama-8b等<br>阿里百炼模型及定价<a href="https://help.aliyun.com/zh/model-studio/models" target="_blank">查看详情</a>',
                            'dependency' => [['model-selection', '==', 'custom']],
                        ],
                        // 百炼温度设置
                        [
                            'id' => 'temperature',
                            'type' => 'number',
                            'title' => '温度 (Temperature)',
                            'subtitle' => '控制生成文本的随机性',
                            'desc' => '值越高越随机，越低越确定。范围 0.0 - 2.0，建议 0.7',
                            'default' => 0.7,
                            'min' => 0.0,
                            'max' => 2.0,
                            'step' => 0.1,
                            'unit' => ' ', // 避免显示默认单位
                        ],
                    ],
                ],
                // 阿里百炼 文生图（Text-to-Image）全局默认配置（任务级未覆盖时生效）
                [
                    'id' => 'aliyun-imagegen-model',
                    'type' => 'select',
                    'title' => '阿里云文生图 默认模型',
                    'subtitle' => 'qwen-image / wanx-v1 / wan2.2-t2i-flash',
                    'desc' => '<div style="border-left:4px solid #2563eb;background:#eff6ff;padding:10px 12px;margin:6px 0 12px;line-height:1.6">仅在任务级未配置时生效。<br>文档：<a href="https://help.aliyun.com/zh/model-studio/text-to-image-v2-api-reference" target="_blank">通义万相V2</a> · <a href="https://help.aliyun.com/zh/model-studio/text-to-image-api-reference" target="_blank">通义万相V1</a> · <a href="https://help.aliyun.com/zh/model-studio/qwen-image-api" target="_blank">通义千问·图像</a></div>',
                    'options' => [
                        // 千问图像
                        'qwen-image' => '通义千问·图像（qwen-image） · 参考价 ¥0.25/张',
                        // 万相 V2（wan2.2）
                        'wan2.2-t2i-plus' => '通义万相 V2 Plus（wan2.2-t2i-plus） · 参考价 ¥0.20/张',
                        'wan2.2-t2i-flash' => '通义万相 V2 Flash（wan2.2-t2i-flash） · 参考价 ¥0.14/张',
                        // 万相 2.6 新增模型（纯文生图）
                        'wan2.6-image' => '通义万相 2.6 Image（wan2.6-image） · 参考价 ¥0.20/张',
                        // 万相 2.1 系列
                        'wanx2.1-t2i-plus' => '通义万相 2.1 Plus（wanx2.1-t2i-plus） · 参考价 ¥0.20/张',
                        'wanx2.1-t2i-turbo' => '通义万相 2.1 Turbo（wanx2.1-t2i-turbo） · 参考价 ¥0.14/张',
                        // 兼容保留 V1
                        'wanx-v1' => '通义万相 V1（wanx-v1）',
                    ],
                    'default' => 'wan2.2-t2i-flash',
                    'dependency' => [['api-server-type', '==', 'bai-lian']],
                ],
                // 移除阿里云 API 级尺寸与数量设置（改由任务级控制）
                // 条件参数：仅 qwen-image 支持
                [
                    'id' => 'aliyun-imagegen-prompt-extend',
                    'type' => 'switcher',
                    'title' => 'Prompt 扩写（仅 qwen-image）',
                    'default' => true,
                    'dependency' => [
                        ['api-server-type', '==', 'bai-lian'],
                    ],
                ],
                [
                    'id' => 'aliyun-imagegen-watermark',
                    'type' => 'switcher',
                    'title' => '水印（仅 qwen-image）',
                    'default' => true,
                    'dependency' => [
                        ['api-server-type', '==', 'bai-lian'],
                    ],
                ],
                // 条件参数：仅 wanx-v1 支持
                [
                    'id' => 'aliyun-imagegen-style',
                    'type' => 'text',
                    'title' => '风格（仅 wanx-v1）',
                    'default' => '<auto>',
                    'dependency' => [
                        ['api-server-type', '==', 'bai-lian'],
                    ],
                ],
            ],
        ]);

        CGPS::createSection($this->prefix, [
            'title' => '令牌余额',
            'fields' => [
                [
					'type' => 'callback',
					'title' => '令牌余额查询',
					'subtitle' => '仅支持来自https://sk.slapi.cn/的令牌',
					'function' => function() {
						echo '<div style="position: relative; height: 500px; width: 100%; overflow: hidden;">';
						echo '<div class="aipost-iframe-loading" style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff;color:#666;">加载中...</div>';
						echo '<iframe id="myIframe" style="position:relative;top:-110px;width:100%;height:610px;border:none;" src="https://tool.slapi.cn/" class="hide"></iframe>';
						echo '</div>';
						echo '<script>';
						echo 'document.addEventListener("DOMContentLoaded",function(){';
						echo 'var iframe=document.getElementById("myIframe");';
						echo 'var loadingBox=document.querySelector(".aipost-iframe-loading");';
						echo 'iframe.classList.add("hide");';
						echo 'if(loadingBox)loadingBox.style.display="flex";';
						echo 'iframe.onload=function(){if(loadingBox)loadingBox.style.display="none";iframe.classList.remove("hide");};';
						echo 'iframe.src=iframe.src;';
						echo '});';
						echo '</script>';
					},
                ],
            ],
        ]);

        CGPS::createSection($this->prefix, [
            'title' => '任务管理',
            'fields' => [
                [
                    'id' => 'tasks',
                    'type' => 'group',
                    'title' => '任务列表',
                    'subtitle' => '添加自动发布任务',
                    'desc' => '可以添加多个任务，每个任务都会按照设定的频率/时间段自动发布文章',
                    'button_title' => '添加任务',
                    'accordion_title_number' => true,
                    'fields' => [
                        [
                            'id' => 'task-note',
                            'type' => 'text',
                            'title' => '任务备注',
                            'desc' => '建议填写任务备注，用于区分任务，可以留空',
                        ],
                        [
                            'id' => 'task-status',
                            'type' => 'switcher',
                            'title' => '任务开关',
                            'desc' => '任务开关，开启后才会自动发布文章',
                            'default' => true,
                        ],
                        [
                            'id' => 'task-api-server-type',
                            'type' => 'select',
                            'title' => '任务API类型',
                            'subtitle' => '',
                            'desc' => '选择的api服务请确保已配置正确的令牌',
                            'options' => [
                                'global' => '使用全局设置',
                                'custom' => '自定义端点（OpenAI兼容）',
                                'zhipu' => '智谱AI（BigModel）',
                                'spark' => '讯飞星火（Spark）',
                                'deepseek' => 'DeepSeek',
                                'moonshot' => 'Moonshot（Kimi）',
                                'doubao' => '豆包（火山 Ark）',
                                'bai-lian' => '阿里百炼',
                                'wenxin' => '文心一言',
                            ],
                            'default' => 'global',
                        ],

                        [
                            'id' => 'task-schedule-type',
                            'type' => 'radio',
                            'title' => '调度类型',
                            'options' => [
                                'frequency' => '按频率',
                                'timespan' => '按时间段'
                            ],
                            'default' => 'frequency',  // 默认值设为按频率
                            'inline' => true,
                        ],
                        [
                            'id' => 'task-frequency',
                            'type' => 'number',
                            'title' => '运行频率',
                            'subtitle' => '单位：分',
                            'desc' => '每隔多少分钟运行一次。最小值为 1，最大不限。WordPress的计划任务不能做到精准运行，仅供参考。',
                            'default' => 1,
                            'min' => 1,
                            'max' => 99999999,
                            'dependency' => [['task-schedule-type', '==', 'frequency']],
                        ],
                        [
                            'id' => 'task-timespans',
                            'type' => 'group',
                            'title' => '时间段设置',
                            'subtitle' => '添加多个时间段及其执行频率',
                            'desc' => '采用24小时制，时分用小写冒号分隔，可以添加多个时间段，每个时间段设置开始时间、结束时间和执行频率',
                            'button_title' => '增加',
                            'accordion_title_number' => true,
                            'dependency' => [['task-schedule-type', '==', 'timespan']],
                            'fields' => [
                                [
                                    'id' => 'start-time',
                                    'type' => 'text',
                                    'title' => '开始时间',
                                    'desc' => '格式：HH:MM，例如：03:00',
                                ],
                                [
                                    'id' => 'end-time',
                                    'type' => 'text',
                                    'title' => '结束时间',
                                    'desc' => '格式：HH:MM，例如：05:00',
                                ],
                                [
                                    'id' => 'timespan-frequency',
                                    'type' => 'number',
                                    'title' => '执行频率',
                                    'subtitle' => '在此时间段内每隔X分钟执行一次',
                                    'default' => 1,
                                    'min' => 1,
                                ],
                            ],
                        ],
                        [
                            'id' => 'post-category',
                            'type' => 'select',
                            'title' => '文章分类',
                            'subtitle' => '选择文章分类',
                            'desc' => '选择文章要发布到的分类',
                            'options' => 'categories',
                        ],
                        [
                            'id' => 'post-tags-language',
                            'type' => 'select', // 使用下拉选择框
                            'title' => '文章语言',
                            'subtitle' => '选择生成文章的语言',
                            'desc' => '选择语言后，生成的标签也是该语言，无需单独指定',
                            'options' => [
                                'tags-zh' => '中文简体', // 中文简体选项
                                'tags-zh-fan' => '中文繁体', // 中文繁体选项
                                'tags-en' => '英文', // 英文选项
                                'tags-vi' => '越南语',
                                'tags-ja' => '日语',
                                'tags-ko-KR' => '韩语',
                                'tags-sa-IN' => '梵文-印度',
                                'tags-pt-BR' => '葡萄牙语',
                                'tags-pt-BR-BR' => '巴西葡萄牙语',
                                'tags-es' => '西班牙语',
                                'custom' => '自定义语言',
                            ],
                            'default' => 'tags-zh', // 默认选择中文
                        ],
                        [
                            'id' => 'custom-language-code',
                            'type' => 'text',
                            'title' => '自定义语言代码',
                            'subtitle' => '输入自定义语言的代码',
                            'desc' => '请输入符合ISO标准的语言代码，例如：fr（法语）、de（德语）、ru（俄语）等',
                            'dependency' => [['post-tags-language', '==', 'custom']],
                        ],
                        [
                            'id' => 'custom-language-description',
                            'type' => 'textarea',
                            'title' => '自定义语言规范描述',
                            'subtitle' => '描述该语言的写作规范和特点',
                            'desc' => '请输入对该语言的详细描述，包括语法特点、写作风格等，AI将根据此描述生成相应语言的内容',
                            'dependency' => [['post-tags-language', '==', 'custom']],
                            'placeholder' => '例如：这是一种使用西里尔字母的语言，句子结构为主谓宾，形容词放在名词前，注重使用正式用语和礼貌表达...',
                        ],

                        [
                            'id' => 'post-tags',
                            'type' => 'switcher',
                            'title' => '自动文章标签',
                            'subtitle' => '自动生成文章标签',
                            'desc' => '开启后根据文章内容生成精准高频关键词',
                            'default' => true,
                        ],
                        [
                            'id' => 'post-tags-count',
                            'type' => 'number',
                            'title' => '自动标签生成数量',
                            'subtitle' => '限制 AI 生成的标签个数（1-8，默认 5）',
                            'desc' => '留空或填 0 时，将使用“3-5个高相关的SEO标签”作为生成指令；最少 1 个，最多 8 个。',
                            'default' => 5,
                            'min' => 1,
                            'max' => 8,
                            'dependency' => [['post-tags', '==', 'true']],
                        ],
                        [
                            'id' => 'post-tags-diy',
                            'type' => 'switcher',
                            'title' => '追加自定义标签',
                            'subtitle' => '追加到自动标签后',
                            'desc' => '是否使用自定义标签进行追加显示',
                            'default' => false,
                        ],
                        [
                            'id' => 'post-tags-diy-text',
                            'type' => 'text',
                            'title' => '输入自定义标签',
                            'desc' => '多个标签使用小写逗号分割',
                            'dependency' => [
                                [
                                    'post-tags-diy',
                                    '==',
                                    'true',
                                ],
                            ],
                        ],
                        [
                            'id' => 'post-author',
                            'type' => 'select',
                            'title' => '文章作者',
                            'subtitle' => '选择文章作者',
                            'desc' => '选择发布文章的作者',
                            'options' => 'users',
                        ],

                        [
                            'id' => 'enable-image-url',
                            'type' => 'switcher',
                            'title' => '配图方式一',
                            'subtitle' => '根据随机API地址获取图片',
                            'desc' => '开启后请输入配图网址API',
                            'default' => true,
                        ],
                        [
                            'id' => 'post-image-url',
                            'type' => 'text',
                            'title' => '文章配图API',
                            'subtitle' => '输入网址获取随机图片',
                            'desc' => '输入一个有效的图片网址，以"/"结尾，系统将随机调用该网址的随机图片缓存在本地。<br>推荐自定义图库API;<a href="https://www.2090ai.cn/doc/ai-post.html#sec-25" target="_blank">自建图库API教程</a>',
                            'default' => 'https://img.8due.com/',
                            'placeholder' => 'https://img.8due.com/',
                            'dependency' => [
                                [
                                    'enable-image-url',
                                    '==',
                                    'true',
                                ],
                            ],
                        ],
                        [
                            'id' => 'post-image-url-n',
                            'type' => 'number',
                            'title' => '图片数量',
                            'subtitle' => '希望插入几张图片',
                            'desc' => '最小1张，最大5张，默认为2张。',
                            'default' => '2',
                            'min' => 1,
                            'max' => 5,
                            'dependency' => [
                                [
                                    'enable-image-url',
                                    '==',
                                    'true',
                                ],
                            ],
                        ],

 

                        [
                            'id' => 'enable-image-url-2',
                            'type' => 'switcher',
                            'title' => '配图方式二',
                            'subtitle' => '生成一幅带有标题的图片',
                            'desc' => '开启后会根据标题生成图片，系统生成不消耗令牌',
                            'default' => false,
                        ],
                        [
                            'id' => 'enable-image-url-position',
                            'type' => 'select', // 使用下拉选择框
                            'title' => '图片位置',
                            'subtitle' => '选择图片在文章中的位置',
                            'options' => [
                                '1' => '开头',
                                '2' => '中间',
                                '3' => '结尾',
                                '4' => '随机',
                            ],
                            'default' => '1', // 默认选择开头
                            'dependency' => [
                                [
                                    'enable-image-url-2',
                                    '==',
                                    'true',
                                ],
                            ],
                        ],
                        
                        [
                            'id' => 'font-selection',
                            'type' => 'select', // 使用下拉选择框
                            'title' => '选择字体',
                            'subtitle' => '选择您要使用的字体',
                            'options' => $this->get_fonts_list(), // 获取字体列表
                            'default' => '', // 默认选项
                            'dependency' => [
                                [
                                    'enable-image-url-2',
                                    '==',
                                    'true',
                                ],
                            ],
                        ],
                        
                        [
                            'id' => 'post-image-font-size',
                            'type' => 'number',
                            'title' => '文字大小',
                            'subtitle' => '单位：px',
                            'desc' => '生成图片给中的文字大小，数字越大，字越大',
                            'default' => 30,
                            'min' => 1,
                            'max' => 999,
                            'dependency' => [
	                            [
		                            'enable-image-url-2',
		                            '==',
		                            'true',
	                            ],
                            ],
                        ],
                        [
                            'id' => 'post-image-font-color',
                            'type' => 'text',
                            'title' => '文字颜色',
                            'subtitle' => '设置生成图片中的文字颜色',
                            'desc' => '输入一个有效的16进制颜色编码',
                            'default' => '#ffffff',
                            'placeholder' => '#ffffff',
                            'validate' => 'color',
                            'dependency' => [
                                [
                                    'enable-image-url-2',
                                    '==',
                                    'true',
                                ],
                                [
                                    'post-image-url-2-radio',
                                    '==',
                                    'diy-background',
                                ],
                            ],
                        ],
                        [
                            'id' => 'post-image-url-2-radio',
                            'type' => 'radio',
                            'title' => '选择配图方式',
                            'options' => [
                                'diy-background' => '自定义背景图',
                                'diy-background-color' => '随机背景颜色和标题颜色',
                            ],
                            'default' => 'diy-background-color',
                            'inline' => true,
                            'dependency' => [
                                [
                                    'enable-image-url-2',
                                    '==',
                                    'true',
                                ],
                            ],
                        ],

                        [
                            'id' => 'post-image-url-2-background',
                            'type' => 'text',
                            'title' => '输入本地图片存储路径',
							'subtitle' => '默认为插件目录下的title-img文件夹<br>你可以根据需要修改为其它路径',
                            'desc' => '以wordpress安装目录作为根目录，推荐使用大小统一的横向图片',
                            'default' => '/wp-content/plugins/ai-post/title-img',
                            'placeholder' => '/wp-content/plugins/ai-post/title-img',
                            'dependency' => [
                                [
                                    'enable-image-url-2',
                                    '==',
                                    'true',
                                ],
                                [
                                    'post-image-url-2-radio',
                                    '==',
                                    'diy-background',
                                ],
                            ],
                        ],
                        [
                            'id' => 'post-image-url-2-color',
                            'type' => 'textarea',
                            'title' => '背景颜色|标题颜色',
                            'desc' => '每行一个设置，每个设置可以使用|分隔背景颜色和标题颜色。如果设置只包含一种颜色，则会使用默认的文字颜色',
                            'dependency' => [
                                [
                                    'enable-image-url-2',
                                    '==',
                                    'true',
                                ],
                                [
                                    'post-image-url-2-radio',
                                    '==',
                                    'diy-background-color',
                                ],
                            ],
                            'placeholder' => '#5b8982|#ffffff
#45545f|#cec6b6
#d47655|#e1f8e1
#7379b0|#c6edec',
                            'default' => '#5b8982|#ffffff
#45545f|#cec6b6
#d47655|#e1f8e1
#7379b0|#c6edec',
                        ],
                       // 任务级：火山引擎/豆包 文生图开关
                       [
                        'id' => 'enable-doubao-imagegen',
                        'type' => 'switcher',
                        'title' => '配图方式三',
                        'subtitle' => '火山引擎/豆包文生图',
                        'desc' => '启用后将根据任务提示生成配图。生成图片会消耗令牌额度',
                        'default' => false,
                    ],
                    [
                        'id' => 'imagegen-provider',
                        'type' => 'select',
                        'title' => '文生图模型提供商',
                        'subtitle' => '选择用于本任务的文生图后端',
                        'options' => [
                            'doubao' => '火山引擎/豆包 · 参考价 ¥0.259/张',
                            'aliyun' => '阿里云百炼（DashScope）',
                        ],
                        'default' => 'doubao',
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                        ],
                    ],
                    // 任务级：当选择阿里云百炼时的模型与参数（覆盖全局默认）
                    [
                        // 仅在阿里云 + 万相系列任务模型时显示；qwen-image 固定为 1
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                            [ 'imagegen-provider', '==', 'aliyun' ],
                            [ 'aliyun-imagegen-model-task', 'any', 'wan2.2-t2i-flash,wan2.2-t2i-plus,wanx2.1-t2i-plus,wanx2.1-t2i-turbo,wanx-v1' ],
                        ],
                    ],
                    // 条件参数：qwen-image 专属
                    [
                        'id' => 'aliyun-imagegen-prompt-extend-task',
                        'type' => 'switcher',
                        'title' => 'Prompt 扩写（任务覆盖，仅 qwen-image）',
                        'default' => true,
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                            [ 'imagegen-provider', '==', 'aliyun' ],
                            [ 'aliyun-imagegen-model-task', '==', 'qwen-image' ],
                        ],
                    ],
                    [
                        'id' => 'aliyun-imagegen-watermark-task',
                        'type' => 'switcher',
                        'title' => '水印（任务覆盖，仅 qwen-image）',
                        'default' => true,
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                            [ 'imagegen-provider', '==', 'aliyun' ],
                            [ 'aliyun-imagegen-model-task', '==', 'qwen-image' ],
                        ],
                    ],
                    // 条件参数：wanx-v1 专属
                    [
                        'id' => 'aliyun-imagegen-style-task',
                        'type' => 'text',
                        'title' => '风格（任务覆盖，仅 wanx-v1）',
                        'subtitle' => '填写 <auto> 或其他风格标签',
                        'default' => '<auto>',
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                            [ 'imagegen-provider', '==', 'aliyun' ],
                            [ 'aliyun-imagegen-model-task', '==', 'wanx-v1' ],
                        ],
                    ],
                    [
                        'id' => 'doubao-imagegen-image-count',
                        'type' => 'number',
                        'title' => '生成图片数量',
                        'subtitle' => '豆包文生图一次生成的图片张数',
                        'desc' => '范围建议 1-4，默认 1。注意：是否支持多图由服务端能力与调用策略决定。',
                        'default' => 1,
                        'min' => 1,
                        'max' => 4,
                        'step' => 1,
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                            [ 'imagegen-provider', '==', 'doubao' ],
                        ],
                    ],
                    // 任务级：豆包文生图尺寸下拉（映射由后端解析为具体像素）
                    [
                        'id' => 'doubao-imagegen-size-task',
                        'type' => 'select',
                        'title' => '尺寸（豆包）',
                        'subtitle' => '选择宽高比例（后端将映射为 1024x768 / 1024x576 / 1024x1024）',
                        'options' => [
                            '4:3'  => '4:3（1024x768 推荐）',
                            '16:9' => '16:9（1024x576）',
                            '1:1'  => '1:1（1024x1024）',
                        ],
                        'default' => '4:3',
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                            [ 'imagegen-provider', '==', 'doubao' ],
                        ],
                    ],
                    // 任务级：文生图 → 是否下载到媒体库
                    [
                        'id' => 'doubao-imagegen-download-to-media',
                        'type' => 'switcher',
                        'title' => '文生图下载到媒体库',
                        'subtitle' => '下载生成图片为本地附件',
                        'desc' => '开启后，将把火山引擎返回的图片URL侧载为媒体库附件（未附加到文章）；关闭则直接使用豆包返回的原始图片URL。',
                        'default' => true,
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                        ],
                    ],

                    // 任务级：文生图 → 是否保留AI水印
                    [
                        'id' => 'doubao-imagegen-watermark',
                        'type' => 'switcher',
                        'title' => '文生图保留AI水印',
                        'subtitle' => 'watermark 参数',
                        'desc' => '关闭可尝试去除右下角AI水印（由服务端决定是否支持）。',
                        'default' => false,
                        'dependency' => [
                            [ 'enable-doubao-imagegen', '==', 'true' ],
                        ],
                    ],


                        [
                            'id' => 'system-prompt',
                            'type' => 'textarea',
                            'default' => '我要你担任作家。我将为你提供文章的主题和逻辑关系并指导你完成撰文，你需要尽可能详细地直接回复我你撰写的文章内容，不要加其他无关的东西。',
                            'title' => 'AI 设定',
                            'desc' => '可留空，不影响文章生成，如果你有特殊需求，可在此填入指令；<br>当前任务的ai设定，将作为prompt伴随当前任务',
                            'after' => $this->render_system_prompt_presets(),
                        ],
                        [
                            'id' => 'post-content-shield',
                            'type' => 'textarea',
                            'title' => '内容过滤词',
                            'subtitle' => '输入希望文章中不要出现的词语',
                            'desc' => '每行一个<br>插件已经内置了一部分过滤词，如果你觉得需要追加，请填在这里',
                        ],
                        [
                            'id' => 'enable-builtin-content-filter',
                            'type' => 'switcher',
                            'title' => '启用系统内置过滤词',
                            'subtitle' => '打开后会应用插件内置的常见口水句过滤；关闭则只使用上面的自定义过滤词',
                            'desc' => '建议保持开启以自动清理“在当今信息爆炸的时代、首先、其次、总结”等模板句。',
                            'default' => true,
                        ],
                        [
                            'id' => 'enable-custom-content',
                            'type' => 'switcher',
                            'title' => '插入自定义文章段落',
                            'desc' => '开启后可在文章中插入自定义内容（开头、中间、结尾）',
                            'default' => false,
                        ],
                        [
                            'id' => 'custom-content-tabs',
                            'type' => 'tabbed',
                            'title' => '自定义文章段落',
                            'subtitle' => '选择需要编辑的文章段落位置',
                            'desc' => '在对应选项卡中编辑内容，支持富文本编辑器',
                            'dependency' => [
                                ['enable-custom-content', '==', 'true']
                            ],
                            'tabs' => [
                                [
                                    'title' => '文章开头',
                                    'fields' => [
                                        [
                                            'id' => 'custom-before-content',
                                            'type' => 'wp_editor',
                                            'title' => '',
                                            'subtitle' => '',
                                            'desc' => '此内容将显示在文章开头',
                                            'sanitize' => false,
                                            'settings' => [
                                                'media_buttons' => true,
                                                'textarea_rows' => 10,
                                                'tinymce' => [
                                                    'toolbar1' => 'formatselect,bold,italic,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,unlink,wp_more,spellchecker,wp_adv',
                                                    'toolbar2' => 'strikethrough,hr,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help'
                                                ]
                                            ]
                                        ]
                                    ]
                                ],
                                [
                                    'title' => '文章中间',
                                    'fields' => [
                                        [
                                            'id' => 'custom-middle-content',
                                            'type' => 'wp_editor',
                                            'title' => '',
                                            'subtitle' => '',
                                            'desc' => '此内容将显示在文章中间（50%位置）',
                                            'sanitize' => false,
                                            'settings' => [
                                                'media_buttons' => true,
                                                'textarea_rows' => 10,
                                                'tinymce' => [
                                                    'toolbar1' => 'formatselect,bold,italic,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,unlink,wp_more,spellchecker,wp_adv',
                                                    'toolbar2' => 'strikethrough,hr,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help'
                                                ]
                                            ]
                                        ]
                                    ]
                                ],
                                [
                                    'title' => '文章结尾',
                                    'fields' => [
                                        [
                                            'id' => 'custom-after-content',
                                            'type' => 'wp_editor',
                                            'title' => '',
                                            'subtitle' => '',
                                            'desc' => '此内容将显示在文章结尾',
                                            'sanitize' => false,
                                            'settings' => [
                                                'media_buttons' => true,
                                                'textarea_rows' => 10,
                                                'tinymce' => [
                                                    'toolbar1' => 'formatselect,bold,italic,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,unlink,wp_more,spellchecker,wp_adv',
                                                    'toolbar2' => 'strikethrough,hr,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help'
                                                ]
                                            ]
                                        ]
                                    ]
                                ]
                            ]
                        ],
                        [
                            'id' => 'post-steps',
                            'type' => 'group',
                            'title' => '文章步骤',
                            'subtitle' => '设置自动发布文章的任务步骤<br>无论添加几个步骤<br>第一个必选标题<br>随后都选主体',
                            'desc' => '设置自动发布文章的任务步骤',
                            'button_title' => '添加',
                            'accordion_title_number' => true,
                            'fields' => [
                                [
                                    'id' => 'send',
                                    'type' => 'textarea',
                                    'title' => '发送内容',
                                    'subtitle' => '设置发送给 AI 的内容',
                                    'desc' => '设置发送给 AI 的内容',
                                ],
                                [
                                    'id' => 'receive',
                                    'type' => 'switcher',
                                    'title' => '接收回复',
                                    'subtitle' => '是否使用 AI 的回复内容',
                                    'desc' => '是否使用 AI 的回复内容，对于设定类发送，可以不使用回复内容',
                                    'default' => true,
                                ],
                                [
                                    'id' => 'receive-type',
                                    'type' => 'radio',
                                    'title' => '接收回复作为',
                                    'subtitle' => '设置接收 AI 回复作为',
                                    'inline' => true,
                                    'default' => 'title',
                                    'options' => [
                                        'title' => '标题',
                                        'content' => '主体',
                                    ],
                                    'dependency' => [
                                        [
                                            'receive',
                                            '==',
                                            'true',
                                        ],
                                    ],
                                ],
                                [
                                    'id' => 'title-source',
                                    'type' => 'radio',
                                    'title' => '标题来源',
                                    'subtitle' => '选择标题由 AI 生成，或直接使用发送内容作为标题',
                                    'inline' => true,
                                    'default' => 'ai',
                                    'options' => [
                                        'ai' => 'AI生成标题（根据发送内容/关键词）',
                                        'direct' => '使用发送内容作为标题（不调用AI）',
                                    ],
                                    'dependency' => [
                                        ['receive', '==', 'true'],
                                        ['receive-type', '==', 'title'],
                                    ],
                                ],
                                // 当选择 "标题" 时显示的提示
                                [
                                    'id' => 'receive-type-desc-title',
                                    'type' => 'notice',
                                    'style' => 'info',
                                    'content' => '当选择回复类型为标题时，AI 的回复将作为文章的标题。',
                                    'dependency' => [
                                        ['receive', '==', 'true'],
                                        ['receive-type', '==', 'title'],
                                    ],
                                ],
                                // 当选择 "主体" 时显示的提示
                                [
                                    'id' => 'receive-type-desc-content',
                                    'type' => 'notice',
                                    'style' => 'info',
                                    'content' => '当选择回复类型为主体时，AI 的回复将作为文章的内容。主体可重复使用，将自动追加上一次的回复内容。',
                                    'dependency' => [
                                        ['receive', '==', 'true'],
                                        ['receive-type', '==', 'content'],
                                    ],
                                ],
                            ],
                        ],
                        [
                            'id' => 'task-ai-comments',
                            'type' => 'switcher',
                            'title' => 'AI自动评论（任务级）',
                            'desc' => '仅当全局开启“AI自动评论”时生效。关闭后，该任务生成的文章不会生成AI评论，并会清理该任务文章已有的AI评论与评论计划。',
                            'default' => true,
                        ],
                        [
                            'id' => 'post-final-status',
                            'type' => 'select',
                            'title' => '文章最终状态',
                            'subtitle' => '选择文章生成后的状态',
                            'desc' => '设置任务生成的文章最终是存为草稿还是直接发布。默认为直接发布。',
                            'options' => [
                                'publish' => '立即发布',
                                'draft' => '存为草稿',
                            ],
                            'default' => 'publish',
                        ]
                    ],
                ],
            ],
        ]);

        CGPS::createSection($this->prefix, [
            'title' => '全局设定',
            'fields' => [
                [
                    'type' => 'callback',
                    'function' => function() {
                        echo '<div class="ad-section" style="margin-bottom: 10px; position: relative;">';
                        echo '<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin-bottom: -22px;">';
                        echo '<a href="https://www.2090ai.cn/" target="_blank" class="button button-primary" style="height:30px; padding:0 10px; line-height:1; display:flex; align-items:center; justify-content:center;">';
                        echo '<span class="dashicons dashicons-admin-links" style="font-size:20px; margin-right:5px;"></span>';
                        echo '访问官网';
                        echo '</a>';

                        echo '<a href="https://www.2090ai.cn/doc/ai-post.html" target="_blank" class="button button-primary" style="height:30px; padding:0 10px; width:100%; line-height:1; display:flex; align-items:center; justify-content:center;">';
                        echo '<span class="dashicons dashicons-media-document" style="font-size:20px; margin-right:5px;"></span>';
                        echo '文档教程';
                        echo '</a></div></div>';
                    },
                    'after' => '<style>
                        .ad-section .button {
                            box-sizing: border-box;
                            flex-direction: row !important;
                            transition: all 0.2s ease;
                        }
                        .ad-section .dashicons {
                            vertical-align: middle;
                            position: relative;
                            top: -1px;
                        }
                    </style>',
                ],
                [
                    'id'     => 'global_tabs',
                    'type'   => 'tabbed',
                    'tabs'   => [
                        [
                            'title'  => '基础优化',
                            'icon' => 'dashicons dashicons-search',
                            'fields' => [
                                [
                                    'type' => 'heading',
                                    'content' => '优化设置'
                                ],
                                [
                                    'type'    => 'content',
                                    'content' => '在开启相关选项前，请确认其他插件是否也有相同的参数，如果有，请不要重复开启，否则可能导致重复设置。<br>
                                    '
                                ],
                                [
                                    'id'      => 'meta_description_generation_method', // New ID
                                    'type'    => 'radio', // Changed to radio
                                    'title'   => 'Meta Description 生成方式', // New title
                                    'options' => [
                                        'extract' => '截取内容（默认）',
                                        'ai'      => 'AI 生成（需API，可能增加消耗）',
                                        'none'    => '不生成 Meta Description' // Added option to disable
                                    ],
                                    'default' => 'extract', // Default to extract
                                    'desc'    => '选择如何生成文章的 Meta Description 标签。'
                                ],
                                [
                                    'id'      => 'publish-content-encoding',
                                    'type'    => 'radio',
                                    'title'   => '发布内容编码方式',
                                    'options' => [
                                        'utf8'        => 'UTF-8 可阅读文本',
                                        'html-entity' => 'HTML 十进制实体编码',
                                    ],
                                    'default' => 'utf8',
                                    'desc'    => '仅正文会根据此选项编码入库：选择“HTML 实体”时，正文中的非 ASCII 字符按 &#NNNN; 存储；选择“UTF-8 正常文本”时，保持可阅读中文。标题始终保持 UTF-8。',
                                ],
                                [
                                    'id' => 'seo_keywords_enabled', // New ID for keywords switch
                                    'type' => 'switcher',
                                    'title' => '生成 Meta Keywords',
                                    'desc' => '是否生成 Meta Keywords 标签（Google 已不再使用，建议关闭）。',
                                    'default' => false // Default to off
                                ],
                                [
                                    'id' => 'empty-tags-action',
                                    'type' => 'select',
                                    'title' => '空白标签处理方式',
                                    'subtitle' => '当期望生成标签但最终为空时，控制文章最终状态',
                                    'options' => [
                                        'draft'   => '存入草稿箱',
                                        'publish' => '继续发布文章',
                                        'trash'   => '放入回收站',
                                    ],
                                    'default' => 'draft',
                                ],
                                [
                                    'id' => 'auto-alt-enabled',
                                    'type' => 'switcher',
                                    'title' => '自动添加图片ALT属性',
                                    'desc' => '开启后自动为文章图片添加alt属性，格式为文章标题+序号（如：alt="标题1" alt="标题2"）',
                                    'default' => false
                                ],
                                [
                                    'id' => 'auto-featured-image-enabled',
                                    'type' => 'switcher',
                                    'title' => '开启自动特色图片',
                                    'desc' => '自动提取文章图片作为特色图片',
                                    'default' => false,
                                ],
                                [
                                    'id' => 'featured-image-position',
                                    'type' => 'select',
                                    'title' => '选择图片位置',
                                    'options' => [
                                        '1' => '第一幅图片',
                                        '2' => '第二幅图片',
                                        '3' => '第三幅图片'
                                    ],
                                    'default' => '1',
                                    'sanitize' => function($value) {
                                        return (string)max(1, min(3, absint($value))); // 强制值在1-3之间
                                    },
                                    'dependency' => [['auto-featured-image-enabled', '==', 'true']]
                                ],
                                [
                                    'id' => 'thumbnail-width',
                                    'type' => 'number',
                                    'title' => '缩略图宽度',
                                    'default' => 300,
                                    'unit' => 'px',
                                    'dependency' => [['auto-featured-image-enabled', '==', 'true']]
                                ],
                                [
                                    'id' => 'thumbnail-height', 
                                    'type' => 'number',
                                    'title' => '缩略图高度',
                                    'default' => 225,
                                    'unit' => 'px',
                                    'dependency' => [['auto-featured-image-enabled', '==', 'true']]
                                ],
                                
                            ]
                        ],
                        [
                            'title'  => '内链设置',
                            'icon' => 'dashicons dashicons-admin-links',
                            'fields' => [
                                [
                                    'type' => 'heading',
                                    'content' => '内链设置'
                                ],
                                [
                                    'id' => 'enable-internal-links',
                                    'type' => 'switcher',
                                    'title' => '启用文章互链功能',
                                    'desc' => '开启后自动为文章添加内链，内链URL为你设置的固定链接结构，<br>如：https://example.com/archives/123，与tag标签链接结构不同',
                                    'default' => true
                                ],
                                [
                                    'id' => 'auto-tag-linking',
                                    'type' => 'switcher',
                                    'title' => '自动标签tag内链',
                                    'desc' => '如果文章中出现当前文章tag关键词，则自动将tag标签URL转换为固定链接结构，<br>如：将https://www.example.com/tag/tagname转换为https://www.example.com/archives/123',
                                    'default' => true,
                                    'dependency' => [['enable-internal-links', '==', 'true']]
                                ],
                                [
                                    'id' => 'custom-links',
                                    'type' => 'textarea',
                                    'title' => '自定义内链规则',
                                    'subtitle' => '每行格式：关键词|URL<br>优先级高于文章内链和tag内链<br>可设置站内站外链接',
                                    'desc' => '示例：<br>人工智能|https://example.com/ai<br>机器学习|https://example.com/ml<br>只有文章包含该关键词才会添加指定链接',
                                    'sanitize' => false,
                                    'dependency' => [['enable-internal-links', '==', 'true']],
                                    'attributes' => [
                                        'placeholder' => '关键词|URL',
                                        'rows' => 5
                                    ]
                                ],
                                [
                                    'id' => 'link-nofollow',
                                    'type' => 'switcher',
                                    'title' => '添加nofollow属性',
                                    'desc' => '为文章内链添加rel="nofollow"属性，告诉搜索引擎不要将权重传递给该链接目标页面',
                                    'dependency' => [['enable-internal-links', '==', 'true']],
                                    'default' => false
                                ],
                                [
                                    'id' => 'link-replace-count',
                                    'type' => 'number',
                                    'title' => '关键词替换次数',
                                    'desc' => '每个关键词在文章中最多替换为链接的次数',
                                    'default' => 2,
                                    'min' => 1,
                                    'max' => 100,
                                    'dependency' => [['enable-internal-links', '==', 'true']]
                                ],
                                [
                                    'id' => 'related-post-criteria',
                                    'type' => 'select',
                                    'title' => '文章内链匹配逻辑',
                                    'options' => [
                                        'date' => '最新文章',
                                        'comment_count' => '最多评论',
                                        'rand' => '随机文章'
                                    ],
                                    'default' => 'date',
                                    'dependency' => [['enable-internal-links', '==', 'true']]
                                ],
                                [
                                    'id' => 'related-post-fallback',
                                    'type' => 'switcher',
                                    'title' => '启用备用链接',
                                    'desc' => '当没有找到关键词匹配的文章时，使用标签TAG链接：格式为https://www.example.com/tag/tagname',
                                    'default' => true,
                                    'dependency' => [['enable-internal-links', '==', 'true']]
                                ],
                            ]
                        ],
                        [
                            'title' => '标题处理',
                            'icon' => 'dashicons dashicons-editor-textcolor',
                            'fields' => [
                                [
                                    'type' => 'heading',
                                    'content' => '标题处理设置'
                                ],
                                [
                                    'id' => 'custom-title-examples',
                                    'type' => 'textarea',
                                    'title' => '自定义示例标题',
                                    'subtitle' => '每行一个示例标题（留空使用默认示例）',
                                    'desc' => '可以用汉语标题，建议输入和站点语言相同的标题<br>输入您希望AI参考的标题样式，生成的标题将自动匹配这些示例的语义风格<br>示例标题越多越好，建议找50-80个不同风格的示例标题，ai会随机抽取一个作为参照示例生成标题',
                                    'placeholder' => '',
                                    'default' => '
老师现场提了一个问题，同学的回答亮了；
那些整天熬夜加班的人注意了；
这个小技巧，99%的人都不知道；
掌握这3点，轻松玩转母婴行业私域运营；
我用了2个月，做坏了6次热点营销；
上海和深圳对比，未来你更看好谁?
',
                                    'sanitize' => false
                                ],
                                [
                                    'id' => 'enable-time-line',
                                    'type' => 'switcher',
                                    'title' => '启用时间线',
                                    'desc' => '开启后可自定义时间线（如：2025年），AI生成内容会参考此时间线',
                                    'default' => true,
                                ],
                                [
                                    'id' => 'time-line',
                                    'type' => 'text',
                                    'title' => '时间线',
                                    'desc' => '请输入当前时间线，如：2025年',
                                    'default' => '2025年',
                                    'dependency' => [
                                        ['enable-time-line', '==', 'true']
                                    ],
                                ],
                                [
                                    'id' => 'zh-title-limit',
                                    'type' => 'number',
                                    'title' => '中文标题限制',
                                    'desc' => '中文字符最大长度（1个汉字=3字节）96字节为32个汉字',
                                    'default' => 96,
                                    'unit' => '字节',
                                ],
                                [
                                    'id' => 'en-title-limit',
                                    'type' => 'number',
                                    'title' => '英文标题限制',
                                    'desc' => '英文字符最大长度（1字母=1字符）',
                                    'default' => 65,
                                    'unit' => '字符',
                                ],
                                [
                                    'id' => 'title-rewrite-enabled',
                                    'type' => 'switcher',
                                    'title' => 'AI改写超长标题',
                                    'desc' => '标题超长时自动调用AI改写',
                                    'default' => true,
                                    'dependency' => [
                                        ['zh-title-limit', '>', 0],
                                        ['en-title-limit', '>', 0]
                                    ]
                                ],
                                [
                                    'id' => 'empty-title-action',
                                    'type' => 'select',
                                    'title' => '空标题处理方式',
                                    'options' => [
                                        'trash' => '放入回收站',
                                        'draft' => '存入草稿箱',
                                        'ai-rewrite' => 'AI自动改写',
                                        'first-heading' => '正文第一个标题（h1/h2/h3/h4）'
                                    ],
                                    'default' => 'trash'
                                ],
                                [
                                    'id' => 'duplicate-check-enabled',
                                    'type' => 'switcher',
                                    'title' => '启用重复标题检查',
                                    'desc' => '开启标题重复检查功能',
                                    'default' => true,
                                ],
                                [
                                    'id' => 'duplicate-action',
                                    'type' => 'select',
                                    'title' => '重复标题处理方式',
                                    'options' => [
                                        'trash' => '放入回收站',
                                        'draft' => '存入草稿箱',
                                        'rewrite' => 'AI自动改写'
                                    ],
                                    'default' => 'trash',
                                    'dependency' => [
                                        ['duplicate-check-enabled', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'duplicate-check-days',
                                    'type' => 'number',
                                    'title' => '重复检查范围',
                                    'subtitle' => '单位：天',
                                    'desc' => '检查最近多少天内的文章标题（0表示检查所有文章）',
                                    'default' => 30,
                                    'min' => 0,
                                    'dependency' => [
                                        ['duplicate-check-enabled', '==', 'true']
                                    ]
                                ],
                            ]
                        ],
                        [
                            'title' => '内容处理',
                            'icon' => 'dashicons dashicons-edit-page',
                            'fields' => [
                                [
                                    'type' => 'heading',
                                    'content' => '内容处理设置'
                                ],
 
                                [
                                    'id' => 'content-replace-rules',
                                    'type' => 'textarea',
                                    'title' => '替换规则',
                                    'desc' => '每行一条规则，格式：旧内容 => 新内容（使用UTF-8编码）',
                                    'sanitize' => false,
                                    // 'dependency' => [['content-check-enabled', '==', 'true']]
                                ],
                                // --- 新增：长文本生成控制 --- 
                                [
                                    'id' => 'enable_long_text_generation',
                                    'type' => 'switcher',
                                    'title' => '启用长文本生成模式',
                                    'desc' => '开启后，AI 将生成更长、段落更详细的文章内容，同时也会消耗更多 Token（实验性功能）。',
                                    'default' => false,
                                    // 'dependency' => [['content-check-enabled', '==', 'true']] // 依赖于内容检查总开关
                                ],
                                [
                                    'id' => 'enable_ai_summary',
                                    'type' => 'switcher',
                                    'title' => '启用AI智能摘要',
                                    'desc' => '开启后，仅在 AI Post 自动生成文章时，会调用 AI 对文章进行总结生成一段摘要，并插入到文章目录树上方。',
                                    'default' => false
                                ],
                                [
                                    'id' => 'ai_summary_title',
                                    'type' => 'text',
                                    'title' => 'AI智能摘要标题',
                                    'desc' => '留空则按文章语言自动显示标题。',
                                    'default' => '',
                                    'dependency' => [
                                        ['enable_ai_summary', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'enable_ai_comments',
                                    'type' => 'switcher',
                                    'title' => '启用AI自动评论',
                                    'desc' => '开启后，仅在 AI Post 自动生成文章时，会调用当前任务所使用的同一个模型，分批生成评论并按计划时间自动发布（实验性功能）。',
                                    'default' => false
                                ],
                                [
                                    'id' => 'ai_comments_total_min',
                                    'type' => 'number',
                                    'title' => 'AI评论总数（最小）',
                                    'desc' => '每篇文章计划生成评论总数的最小值。',
                                    'default' => 6,
                                    'min' => 0,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'ai_comments_total_max',
                                    'type' => 'number',
                                    'title' => 'AI评论总数（最大）',
                                    'desc' => '每篇文章计划生成评论总数的最大值。',
                                    'default' => 12,
                                    'min' => 0,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'ai_comments_days',
                                    'type' => 'number',
                                    'title' => '评论分布天数',
                                    'desc' => '将评论发布时间随机分布在未来 N 天内。',
                                    'default' => 3,
                                    'min' => 1,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'ai_comments_batch_size',
                                    'type' => 'number',
                                    'title' => '每批生成评论数',
                                    'desc' => '每次定时任务最多生成/插入多少条评论（建议 3~5）。',
                                    'default' => 4,
                                    'min' => 1,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'ai_comments_generation_interval_minutes',
                                    'type' => 'number',
                                    'title' => '生成间隔（分钟）',
                                    'desc' => '评论计划未完成时，每隔多少分钟继续生成下一批评论。',
                                    'default' => 10,
                                    'min' => 1,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'ai_comments_max_per_post',
                                    'type' => 'number',
                                    'title' => '每篇评论上限',
                                    'desc' => '文章已存在的评论（含AI评论）超过该阈值后不再生成。',
                                    'default' => 50,
                                    'min' => 0,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'ai_comments_bind_user',
                                    'type' => 'switcher',
                                    'title' => 'AI评论绑定WP用户（拟人化）',
                                    'desc' => '开启后，自动评论会绑定到WP用户（若不存在则自动创建），提升拟人化效果。',
                                    'default' => false,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'ai_comments_enable_avatar',
                                    'type' => 'switcher',
                                    'title' => 'AI评论启用头像（拟人化）',
                                    'desc' => '开启后，会为AI评论作者生成/分配头像。',
                                    'default' => false,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                [
                                    'id' => 'ai_comments_auto_approve',
                                    'type' => 'switcher',
                                    'title' => 'AI评论自动审核',
                                    'desc' => '开启后，AI 自动评论到达计划发布时间时会自动通过审核（仅影响AI评论，不影响真实用户评论）。',
                                    'default' => false,
                                    'dependency' => [
                                        ['enable_ai_comments', '==', 'true']
                                    ]
                                ],
                                // --- 修改：表格生成设置 --- 
                                // 1. 添加总开关
                                [
                                    'id' => 'enable_table_generation', 
                                    'type' => 'switcher',
                                    'title' => '启用AI生成表格',
                                    'desc' => '开启后，会在内容中插入相关的HTML格式表格。',
                                    'default' => false,
                                    // 'dependency' => [['content-check-enabled', '==', 'true']]
                                ],
                                [
                                    'type' => 'heading',
                                    'content' => '文章目录设置'
                                ],
                                [
                                    'id' => 'enable-toc',
                                    'type' => 'switcher',
                                    'title' => '启用文章目录',
                                    'desc' => '在文章开头自动生成内容目录',
                                    'default' => false
                                ],
                                [
                                    'id' => 'toc-title-text',
                                    'type' => 'text',
                                    'title' => '目录标题文字',
                                    'default' => '文章目录',
                                    'dependency' => [['enable-toc', '==', 'true']]
                                ],
                                [
                                    'id' => 'toc-background-color',
                                    'type' => 'color', // 使用 color 类型选择器
                                    'title' => '目录背景颜色',
                                    'default' => '#f9f9f9',
                                    'dependency' => [['enable-toc', '==', 'true']]
                                ],
                                [
                                    'id' => 'toc-link-color', // 重命名 ID
                                    'type' => 'color', // 使用 color 类型选择器
                                    'title' => '目录链接颜色', // 修改标题
                                    'default' => '#1a0dab', // 修改默认值为常见的链接蓝色
                                    'dependency' => [['enable-toc', '==', 'true']]
                                ],
                                [
                                    'id' => 'toc-min-headings',
                                    'type' => 'number',
                                    'title' => '最小生成目录标题数',
                                    'desc' => '文章中至少需要多少个H2/H3标题才生成目录',
                                    'default' => 3,
                                    'min' => 1,
                                    'dependency' => [['enable-toc', '==', 'true']]
                                ],
                                // 新增：目录默认状态
                                [
                                    'id' => 'toc-default-state',
                                    'type' => 'radio',
                                    'title' => '目录默认状态',
                                    'options' => [
                                        'expanded' => '展开',
                                        'collapsed' => '折叠'
                                    ],
                                    'default' => 'expanded',
                                    'inline' => true,
                                    'dependency' => [['enable-toc', '==', 'true']]
                                ],
                                [
                                    'type' => 'heading',
                                    'content' => '图片WebP格式转换'
                                ],
                                [
                                    'id' => 'enable-webp-conversion',
                                    'type' => 'switcher',
                                    'title' => '开启图片WebP格式转换',
                                    // 更新描述，添加扩展要求提示
                                    'desc' => '自动将文章中的本地图片转换为WebP格式以优化加载速度。<br><strong>重要：</strong>此功能需要服务器 PHP 安装并启用 <strong>GD 和EXIF 扩展（并支持 WebP 功能）</strong> 或 <strong>Imagick 扩展</strong>。<br>如未开启扩展，请不要启用此功能<br><a href="https://www.2090ai.cn/doc/ai-post.html#sec-25" target="_blank"><查看宝塔站点如何开启exif扩展></a>',
                                    'default' => false,
                                    // Add sanitize callback to explicitly save 1 or 0
                                    'sanitize' => function( $value ) {
                                        return $value ? '1' : '0';
                                    }
                                ],
                                // 新增：使用 callback 字段显示服务器状态
                                [
                                    'id' => 'webp-support-status', // 给个ID以防万一
                                    'type' => 'callback',
                                    // 'title' => '服务器状态', // 不设置标题，使其紧随上方开关
                                    'function' => [$this, 'get_webp_support_status_html']
                                ],
                                // 为 DIV 选项添加描述
                            ]
                        ],
                        [
                            'title' => 'Google SEO设置',
                            'icon' => 'dashicons dashicons-admin-tools',
                            'fields' => [
                                [
                                    'type'    => 'content',
                                    'content' => '优化文章的搜索引擎表现，包括 Schema.org 结构化数据和社交媒体 Meta 标签等相关设置，可显著提高google评分。<br>
                                    注意：<br>
                                  某些主题自带以下标签，开启前请检查当前文章页面是否已开启相关功能，否则可能导致重复设置。<br>
                                    '
                                ],
                                [
                                    'id'      => 'enable_schema_org',
                                    'type'    => 'switcher',
                                    'title'   => '启用 Schema.org 结构化数据',
                                    'desc'    => '为文章和FAQ（如果生成）添加JSON-LD格式的结构化数据，有助于搜索引擎理解内容。',
                                    'default' => false
                                ],
                                [
                                    'id'      => 'schema_enable_publisher',
                                    'type'    => 'switcher',
                                    'title'   => 'Schema: 添加 Publisher 信息',
                                    'desc'    => '在结构化数据中包含网站发布者信息 (Organization)。',
                                    'default' => true, // Publisher info is generally good
                                    'dependency' => [['enable_schema_org', '==', 'true']]
                                ],
                                [
                                    'id'      => 'schema_enable_author',
                                    'type'    => 'switcher',
                                    'title'   => 'Schema: 添加 Author 信息',
                                    'desc'    => '在结构化数据中包含文章作者信息 (Person)。',
                                    'default' => true, // Author info is good
                                    'dependency' => [['enable_schema_org', '==', 'true']]
                                ],
                                [
                                    'id'      => 'schema_enable_inlanguage',
                                    'type'    => 'switcher',
                                    'title'   => 'Schema: 添加 Language 信息',
                                    'desc'    => '在结构化数据中包含文章内容的语言代码 (inLanguage)，例如 zh-CN, en-US。',
                                    'default' => true, // Language info helps targeting
                                    'dependency' => [['enable_schema_org', '==', 'true']]
                                ],
                                [
                                    'id'      => 'enable_og_twitter_meta',
                                    'type'    => 'switcher',
                                    'title'   => '启用 Open Graph & Twitter Card',
                                    'desc'    => '为文章添加 Open Graph (og:*) 和 Twitter Card (twitter:*) Meta 标签，增强社交媒体分享效果。',
                                    'default' => false
                                ],
                                [
                                    'id' => 'feature_cards_enabled',
                                    'type' => 'switcher',
                                    'title' => '启用特性卡片',
                                    'desc' => '开启后，可在正文第 N 个有效段落之后插入 2×3 特性卡片网格（避开图片和表格）。',
                                    'default' => false,
                                ],
                                [
                                    'id' => 'feature_cards_paragraph_index',
                                    'type' => 'number',
                                    'title' => '特性卡片插入段落序号',
                                    'desc' => '当启用特性卡片时，在第 N 个有效段落之后插入；若正文有效段落不足 N，则插入在最后一个有效段落之后。',
                                    'default' => 5,
                                    'min' => 1,
                                    'max' => 50,
                                    'dependency' => [
                                        ['feature_cards_enabled', '==', 'true'],
                                    ],
                                ],
                                [
                                    'id' => 'stats_cards_enabled',
                                    'type' => 'switcher',
                                    'title' => '启用数据统计卡片',
                                    'desc' => '开启后，可在正文第 N 个有效段落之后插入 1×4 数据统计卡片（移动端自动适配为 2×2 布局）。',
                                    'default' => false,
                                ],
                                [
                                    'id' => 'stats_cards_paragraph_index',
                                    'type' => 'number',
                                    'title' => '数据统计卡片插入段落序号',
                                    'desc' => '当启用数据统计卡片时，在第 N 个有效段落之后插入；若正文有效段落不足 N，则插入在最后一个有效段落之后。',
                                    'default' => 3,
                                    'min' => 1,
                                    'max' => 50,
                                    'dependency' => [
                                        ['stats_cards_enabled', '==', 'true'],
                                    ],
                                ],
                                [
                                    'id' => 'tips_card_enabled',
                                    'type' => 'switcher',
                                    'title' => '启用实用技巧提示卡',
                                    'desc' => '开启后，可在正文第 N 个有效段落之后插入一条“实用技巧”提示卡片，用于给读者提供与主题相关的小窍门。',
                                    'default' => false,
                                ],
                                [
                                    'id' => 'tips_card_paragraph_index',
                                    'type' => 'number',
                                    'title' => '实用技巧提示卡插入段落序号',
                                    'desc' => '当启用实用技巧提示卡时，在第 N 个有效段落之后插入；若正文有效段落不足 N，则插入在最后一个有效段落之后。',
                                    'default' => 6,
                                    'min' => 1,
                                    'max' => 50,
                                    'dependency' => [
                                        ['tips_card_enabled', '==', 'true'],
                                    ],
                                ],
                                [
                                    'id' => 'youtube_auto_embed_enabled',
                                    'type' => 'switcher',
                                    'title' => '启用视频自动插入',
                                    'desc' => '当任务关键词包含特定词（如：wps教程、wps技巧）时，在正文中自动插入预设的视频。',
                                    'default' => false,
                                ],
                                [
                                    'id' => 'youtube_embed_rules',
                                    'type' => 'textarea',
                                    'title' => '视频规则',
                                    'subtitle' => '一行一条规则',
                                    'desc' => '示例：claude编程|https://player.bilibili.com/player.html?bvid=BV187hdzTEx7<br><a href="https://download.2090ai.cn/software/VideoBatchUrl.exe" target="_blank">下载批量url获取工具，支持bilibili、youtub</a>',
                                    'sanitize' => false,
                                    'dependency' => [
                                        ['youtube_auto_embed_enabled', '==', 'true'],
                                    ],
                                ],
                                [
                                    'id' => 'youtube_embed_paragraph_index',
                                    'type' => 'number',
                                    'title' => '视频插入段落序号',
                                    'desc' => '在第 N 个有效段落之后插入视频（建议 2~5），仅在启用自动插入时生效。',
                                    'default' => 2,
                                    'min' => 1,
                                    'max' => 50,
                                    'dependency' => [
                                        ['youtube_auto_embed_enabled', '==', 'true'],
                                    ],
                                ],
                            ]
                        ],
                        [
                            'title' => '全局内容插',
                            'icon' => 'dashicons dashicons-editor-insertmore',
                            'fields' => [
                                [
                                    'type' => 'callback',
                                    'title' => '在全站文章中自定义内容',
                                    'function' => function() {
                                        echo '<p>在全站文章中插入自定义内容文本，支持HTML代码，支持站内站外自定义链接</p>';
                                        echo '<div class="notice notice-info inline" style="margin: 10px 0; padding: 10px;">';
                                        echo '<p><strong>随机段落功能说明：</strong></p>';
                                        echo '<p>1. 使用 <code>**段落内容**</code> 格式标记一个段落</p>';
                                        echo '<p>2. 使用 <code>|</code> 分隔多个段落，例如：<code>**段落一**|**段落二**|**段落三**</code></p>';
                                        echo '<p>3. 如果检测到多个段落标记，系统会在每次显示时随机选择其中一个段落</p>';
                                        echo '<p>4. 段落内可以包含HTML代码和任何格式化内容</p>';
                                        echo '</div>';
                            // 冗余说明保留在下方块中，不再在其它无关段落输出
                                    }
                                ],
                                [
                                    'id' => 'global_before_content',
                                    'type' => 'textarea',
                                    'title' => '全局内容前插入',
                                    'subtitle' => '在所有文章开头添加内容',
                                    'desc' => '支持HTML代码，例如：<br>&lt;div class="notice"&gt;全局公告...&lt;/div&gt;<br>使用 <code>**段落内容**|**另一段落**</code> 格式可实现随机显示其中一个段落',
                                    'sanitize' => false
                                ],
                                [
                                    'id' => 'global_middle_content',
                                    'type' => 'textarea',
                                    'title' => '全局内容中间插入',
                                    'subtitle' => '在所有文章50%位置插入',
                                    'desc' => '内容将插入到文章中间位置<br>支持HTML代码<br>使用 <code>**段落内容**|**另一段落**</code> 格式可实现随机显示其中一个段落',
                                    'sanitize' => false
                                ],
                                [
                                    'id' => 'global_after_content',
                                    'type' => 'textarea',
                                    'title' => '全局内容结尾插入',
                                    'subtitle' => '在所有文章结尾添加内容',
                                    'desc' => '支持HTML代码，例如统计代码等<br>使用 <code>**段落内容**|**另一段落**</code> 格式可实现随机显示其中一个段落',
                                    'sanitize' => false
                                ],
                            ]
                        ],
                        [
                            'title' => '自定义CSS',
                            'icon' => 'dashicons dashicons-art',
                            'fields' => [
                                [
                                    'type' => 'heading',
                                    'content' => 'CSS代码设置'
                                ],
                                [
                                    'id' => 'global_custom_css',
                                    'type' => 'code_editor',
                                    'title' => '自定义CSS代码',
                                    'subtitle' => '',
                                    'desc' => '输入自定义CSS代码，将自动应用到全站',
                                    'default' => '.li {list-style-type: none;}',
                                    'options' => [
                                        'language' => 'css',
                                        'theme' => 'dracula',
                                        'tabSize' => 2,
                                        'height' => 400,
                                        'toolbar' => false
                                    ],
                                    'settings' => [
                                        'codemirror' => [
                                            'lineNumbers' => true,
                                            'foldGutter' => true,
                                            'styleActiveLine' => true
                                        ]
                                    ]
                                ]
                            ]
                        ],
                        // 新增：导入导出选项卡
                        [
                            'title' => '导入导出',
                            'icon' => 'dashicons dashicons-download', // 使用下载图标
                            'fields' => [
                                [
                                    'type' => 'heading',
                                    'content' => '导出配置'
                                ],
                                // 导出按钮
                                [
                                    'id' => 'export_settings_button_wrapper',
                                    'type' => 'callback',
                                    'title' => '导出当前配置',
                                    'function' => function() {
                                        echo '<button type="button" class="button button-primary" onclick="exportAiPostSettings(this); return false;">导出配置到文件</button>';
                                    }
                                ],
                                [
                                    'type' => 'heading',
                                    'content' => '导入配置'
                                ],
                                // 导入文件选择
                                [
                                    'id' => 'import_settings_file_wrapper',
                                    'type' => 'callback',
                                    'title' => '选择配置文件',
                                    'function' => function() {
                                        // 注意 ID 用于 JS 选择器
                                        echo '<input type="file" id="ai_post_import_file_input" accept=".json" />';
                                        echo '<p class="description">选择一个 .json 格式的配置文件进行导入。<a href="https://version.suqianweb.cn/ai-post-settings-example.json" target="_blank">点击下载配置示例（右键另存为）</a></p>';
                                    }
                                ],
                                // 重新添加导入按钮
                                [
                                    'id' => 'import_settings_button_wrapper',
                                    'type' => 'callback',
                                    'title' => '导入配置', // 标题用于左侧标签
                                    'function' => function() {
                                        // 确保按钮的 onclick 调用正确的 JS 函数
                                        echo '<button type="button" class="button button-primary" onclick="importAiPostSettings(this); return false;">点击导入</button>';
                                    }
                                ],
                                // 添加说明和风险提示文本
                                [
                                    'id' => 'import_export_notes',
                                    'type' => 'callback',
                                    'function' => function() {
                                        // 使用 Flexbox 创建两列布局
                                        echo '<div style="display: flex; align-items: flex-start; gap: 20px; padding: 10px; border: 1px solid #ccd0d4; border-left-width: 4px; border-left-color: #d63638; margin-top: 15px;">';
                                        
                                        // 左侧内容区域
                                        echo '<div style="flex: 1;">'; // 占据剩余空间
                                        echo '<p><strong>说明：</strong></p>';
                                        echo '<ul style="list-style: disc; margin-left: 20px; margin-bottom: 15px;">'; // 增加下边距
                                        echo '<li>导出功能会将当前插件的所有配置（授权信息除外）保存为一个 .json 文件，方便备份或迁移。</li>';
                                        echo '<li>导入功能允许您上传之前导出的 .json 文件来恢复配置。</li>';
                                        echo '<li>导入功能不会覆盖你的授权信息和api令牌，只会覆盖插件基础设置。</li>';
                                        echo '</ul>';
                                        echo '<p><strong><span style="color: #d63638;">风险提示：</span></strong></p>';
                                        echo '<ul style="list-style: disc; margin-left: 20px;">';
                                        echo '<li>导入配置将会<strong>覆盖</strong>当前的基础设置，此操作不可逆，请谨慎操作！</li>';
                                        echo '<li>请确保导入的文件是使用<strong>相同版本</strong>的插件导出的，导入不兼容版本的配置文件可能导致未知错误或功能异常。</li>';
                                        echo '<li>导入来源不可靠的配置文件可能存在安全风险。</li>';
                                        echo '</ul>';
                                        echo '</div>'; // 结束左侧内容区域

                                        // 右侧图标区域
                                        echo '<div style="flex-shrink: 0; text-align: center; padding-top: 20px;">'; // 不收缩，居中，增加上边距
                                        // 使用 WordPress Dashicons 作为示例图标 (信息图标)
                                        echo '<span class="dashicons dashicons-info-outline" style="font-size: 64px; color: #787c82; width: 64px; height: 64px;"></span>'; 
                                        echo '</div>'; // 结束右侧图标区域

                                        echo '</div>'; // 结束 Flexbox 容器
                                    }
                                ],
                                // JavaScript for handling export/import
                                [
                                    'type' => 'callback',
                                    // 这个字段不需要 title，因为它只输出 JS
                                    'function' => function() {
                                        // 检查 $this 是否可用，如果不可用则需要传递 prefix
                                        $prefix = isset($this) && isset($this->prefix) ? $this->prefix : 'ai-post'; // 确保 prefix 可用
                                        $export_nonce = \wp_create_nonce('ai_post_export_settings_nonce');
                                        $import_nonce = \wp_create_nonce('ai_post_import_settings_nonce');
                                        ?>
                                        <script>
                                            // --- Export Function --- 
                                            if (typeof exportAiPostSettings !== 'function') {
                                                function exportAiPostSettings(btn) {
                                                    btn.disabled = true;
                                                    btn.textContent = '正在导出...';
                                                    if (typeof ajaxurl === 'undefined') {
                                                        alert('AJAX URL 未定义，无法导出。');
                                                        btn.disabled = false;
                                                        btn.textContent = '导出配置到文件';
                                                        return;
                                                    }
                                                    jQuery.post(ajaxurl, {
                                                        action: 'ai_post_export_settings',
                                                        nonce: '<?php echo $export_nonce; ?>'
                                                    }, function(response) {
                                                        if (response.success && response.data.settings_json) {
                                                            // 创建 Blob 对象
                                                            const blob = new Blob([response.data.settings_json], { type: 'application/json' });
                                                            const url = URL.createObjectURL(blob);
                                                            
                                                            // 创建临时链接并触发下载
                                                            const a = document.createElement('a');
                                                            a.href = url;
                                                            // 获取当前日期和时间用于文件名
                                                            const now = new Date();
                                                            const timestamp = now.getFullYear().toString() +
                                                                            (now.getMonth() + 1).toString().padStart(2, '0') +
                                                                            now.getDate().toString().padStart(2, '0') + '_' +
                                                                            now.getHours().toString().padStart(2, '0') +
                                                                            now.getMinutes().toString().padStart(2, '0') +
                                                                            now.getSeconds().toString().padStart(2, '0');
                                                            a.download = `ai-post-settings-${timestamp}.json`;
                                                            document.body.appendChild(a);
                                                            a.click();
                                                            
                                                            // 清理
                                                            document.body.removeChild(a);
                                                            URL.revokeObjectURL(url);
                                                            alert('配置文件已开始下载。');
                                                        } else {
                                                            alert('导出失败: ' + (response.data && response.data.message ? response.data.message : '未知错误'));
                                                        }
                                                        btn.disabled = false;
                                                        btn.textContent = '导出配置到文件';
                                                    }).fail(function(jqXHR, textStatus, errorThrown) {
                                                        console.error("Export AJAX Error:", textStatus, errorThrown);
                                                        alert('导出请求失败，请检查网络或查看浏览器控制台获取更多信息。');
                                                        btn.disabled = false;
                                                        btn.textContent = '导出配置到文件';
                                                    });
                                                }
                                            }

                                            // --- Import Function --- 
                                            if (typeof importAiPostSettings !== 'function') {
                                                function importAiPostSettings(btn) {
                                                    const fileInput = document.getElementById('ai_post_import_file_input');
                                                    
                                                    if (!fileInput || !fileInput.files || fileInput.files.length === 0) {
                                                        alert('请先选择要导入的 .json 配置文件。');
                                                        return;
                                                    }
                                                    
                                                    const file = fileInput.files[0];
                                                    if (file.type !== 'application/json') {
                                                         alert('请选择一个有效的 .json 文件。');
                                                        return;
                                                    }

                                                    if (!confirm('确定要导入配置吗？当前设置将被覆盖！此操作不可恢复！')) {
                                                        return;
                                                    }

                                                    const reader = new FileReader();
                                                    reader.onload = function(event) {
                                                        const settingsJson = event.target.result;
                                                        
                                                        // 基础 JSON 格式验证
                                                        try {
                                                            JSON.parse(settingsJson);
                                                        } catch (e) {
                                                            alert('导入失败：文件内容不是有效的 JSON 格式。');
                                                            return;
                                                        }

                                                        btn.disabled = true;
                                                        btn.textContent = '正在导入...';
                                                        if (typeof ajaxurl === 'undefined') {
                                                            alert('AJAX URL 未定义，无法导入。');
                                                            btn.disabled = false;
                                                            btn.textContent = '点击导入';
                                                            return;
                                                        }
                                                        jQuery.post(ajaxurl, {
                                                            action: 'ai_post_import_settings',
                                                            nonce: '<?php echo $import_nonce; ?>',
                                                            settings_json: settingsJson // 发送文件内容
                                                        }, function(response) {
                                                            if (response.success) {
                                                                alert('配置已成功导入！页面将刷新以应用更改。');
                                                                location.reload();
                                                            } else {
                                                                alert('导入失败: ' + (response.data && response.data.message ? response.data.message : '未知错误'));
                                                                btn.disabled = false;
                                                                btn.textContent = '点击导入';
                                                            }
                                                        }).fail(function(jqXHR, textStatus, errorThrown) {
                                                            console.error("Import AJAX Error:", textStatus, errorThrown);
                                                            alert('导入请求失败，请检查网络或查看浏览器控制台获取更多信息。');
                                                            btn.disabled = false;
                                                            btn.textContent = '点击导入';
                                                        });
                                                    };
                                                    
                                                    reader.onerror = function() {
                                                        alert('读取文件时发生错误。');
                                                    };
                                                    
                                                    reader.readAsText(file); // 读取文件内容为文本
                                                }
                                            }
                                        </script>
                                        <?php
                                    }
                                ]
                            ]
                        ] // 结束导入导出选项卡
                        ,
                        // 新增：系统调试与日志
                        [
                            'title' => '系统调试与日志',
                            'icon' => 'dashicons dashicons-admin-generic',
                            'fields' => [
                                [
                                    'type' => 'callback',
                                    'title' => '一键自检（WP-Cron/Loopback/证书/权限）',
                                    'subtitle' => '检测系统环境是否满足定时任务运行条件',
                                    'function' => [$this, 'render_self_diagnose_panel'],
                                ],
                                [
                                    'id' => 'enable-debug-log',
                                    'type' => 'switcher',
                                    'title' => '启用调试日志（不修改 wp-config）',
                                    'label' => '开启后将在站点根目录生成 debug.log（不可写则回退到 uploads/ai-post/logs/debug.log）',
                                    'default' => false,
                                    'desc' => '调试完毕请关闭，否则会生成大量日志文件，影响性能',
                                ],
                                [
                                    'type' => 'callback',
                                    'title' => '调试日志操作',
                                    'function' => [$this, 'render_debug_log_panel'],
                                ],
                                [
                                    'type' => 'callback',
                                    'title' => '通信令牌（Cron/REST）',
                                    'function' => [$this, 'render_cron_token_panel'],
                                ],
                            ],
                        ],
                    ]
                ]
            ]
        ]);

        // 运行日志 Tab（迁移为独立回调 render_run_log_panel）
        CGPS::createSection($this->prefix, [
            'id'    => 'log',
            'title' => '运行日志',
            'fields' => [
                [
                    'type' => 'callback',
                    'title' => '',
                    'function' => [$this, 'render_run_log_panel'],
                ],
            ],
        ]);
    }

    // 获取字体列表的方法（方式二专用）：优先扫描 uploads/aipost-fonts，其次扫描插件内 fonts 目录
    private function get_fonts_list() {
        $fonts_options = [];

        // 1) 优先：uploads/aipost-fonts 顶层（不递归）
        try {
            if (!function_exists('wp_upload_dir')) {
                require_once ABSPATH . 'wp-includes/functions.php';
            }
            $uploads = \wp_upload_dir();
            if (is_array($uploads) && !empty($uploads['basedir'])) {
                $upload_fonts_dir = rtrim($uploads['basedir'], '/\\') . DIRECTORY_SEPARATOR . 'aipost-fonts' . DIRECTORY_SEPARATOR;
                if (@is_dir($upload_fonts_dir)) {
                    $files = @scandir($upload_fonts_dir) ?: [];
                    foreach ($files as $f) {
                        if ($f === '.' || $f === '..') continue;
                        if (preg_match('/\.(ttf|otf|ttc)$/i', $f)) {
                            $fonts_options[$f] = $f; // 仅返回文件名，生成时会拼接目录
                        }
                    }
                }
            }
        } catch (\Throwable $e) {
            // 静默
        }

        // 2) 兜底：插件自带 fonts 目录（若存在）
        $plugin_fonts_dir = plugin_dir_path(__FILE__) . '../fonts/';
        if (@is_dir($plugin_fonts_dir)) {
            $plugin_fonts = @glob($plugin_fonts_dir . '*.{ttf,TTF,otf,OTF,ttc,TTC}', GLOB_BRACE) ?: [];
            foreach ($plugin_fonts as $file) {
                $font_name = basename($file);
                if (!isset($fonts_options[$font_name])) {
                    $fonts_options[$font_name] = $font_name;
                }
            }
        }

        // 3) 若仍为空，则提供友好占位提示
        if (empty($fonts_options)) {
            // 注意：部分 UI 框架不支持禁用选项，这里仅返回占位文案；保存时若值为空将视为未选择
            $fonts_options[''] = '未检测到字体文件，请上传字体文件至/wp-content/uploads/aipost-fonts目录下';
        }

        return $fonts_options;
    }

    public function ai_post_cron($task_key)
    {
        // 获取任务信息
        $tasks = get_option($this->prefix . '-tasks', []);
        
        // 从任务键中提取索引
        $task_index = str_replace($this->prefix . '-task-', '', $task_key);
        $task = isset($tasks[$task_index]) ? $tasks[$task_index] : null;
        
        if (!$task) {
            error_log("AI Post: 找不到任务：{$task_index}");
            return;
        }
        
        // 添加调度类型检查，默认为frequency
        $schedule_type = $task['task-schedule-type'] ?? 'frequency';
        
        if ($schedule_type === 'timespan') {
            $should_run = false;
            $current_time = current_time('H:i');
            
            error_log("AI Post Debug: 当前时间 {$current_time}，检查时间段");
            
            if (isset($task['task-timespans']) && is_array($task['task-timespans'])) {
                foreach ($task['task-timespans'] as $timespan) {
                    $start_time = $timespan['start-time'] ?? '';
                    $end_time = $timespan['end-time'] ?? '';
                    $timespan_frequency = intval($timespan['timespan-frequency'] ?? 1);
                    
                    error_log("AI Post Debug: 检查时间段 {$start_time} 至 {$end_time}，频率 {$timespan_frequency}分钟");
                    
                    if ($start_time && $end_time) {
                        // 检查当前时间是否在时间段内
                        if ($this->is_time_between($current_time, $start_time, $end_time)) {
                            error_log("AI Post Debug: 当前时间在时间段 {$start_time} 至 {$end_time} 内");
                            
                            // 检查最后执行时间
                            $last_run = get_option("{$this->prefix}_last_run_{$task_key}", 0);
                            $time_diff = floor((time() - $last_run) / 60);
                            
                            if ($time_diff >= $timespan_frequency) {
                                error_log("AI Post Debug: 时间差 {$time_diff} 分钟，满足执行频率 {$timespan_frequency} 分钟");
                                $should_run = true;
                                break;
                            } else {
                                error_log("AI Post Debug: 时间差 {$time_diff} 分钟，不满足执行频率 {$timespan_frequency} 分钟");
                            }
                        } else {
                            error_log("AI Post Debug: 当前时间不在时间段 {$start_time} 至 {$end_time} 内");
                        }
                    }
                }
            }
            
            if (!$should_run) {
                error_log("AI Post Debug: 当前时间不在任何执行时间段内或未达到执行频率，跳过执行");
                return;
            }
        }
        
        // 更新最后执行时间
        update_option("{$this->prefix}_last_run_{$task_key}", time());
        
        // 继续执行原有的任务逻辑...
    }

    /**
     * 检查当前时间是否在给定的时间段内
     */
    private function is_time_between($current, $start, $end)
    {
        // 将时间转换为分钟数进行比较
        $current_minutes = $this->time_to_minutes($current);
        $start_minutes = $this->time_to_minutes($start);
        $end_minutes = $this->time_to_minutes($end);
        
        error_log("AI Post Debug: 当前分钟数 {$current_minutes}，开始分钟数 {$start_minutes}，结束分钟数 {$end_minutes}");
        
        // 处理跨天的情况
        if ($end_minutes < $start_minutes) {
            return $current_minutes >= $start_minutes || $current_minutes <= $end_minutes;
        }
        
        return $current_minutes >= $start_minutes && $current_minutes <= $end_minutes;
    }

    /**
     * 将时间字符串转换为分钟数
     */
    private function time_to_minutes($time)
    {
        list($hours, $minutes) = explode(':', $time);
        return (intval($hours) * 60) + intval($minutes);
    }

    public function update_plugin(): void
    {
        // 获取当前版本
        $current_version = get_option($this->prefix . '-version');
        $plugin_version = defined('HAOZI_AIPOST_VERSION') ? HAOZI_AIPOST_VERSION : '2.8.8';
        
        // 如果是从旧版本更新（没有调度类型选项）
        if (version_compare($current_version, '1.x.x', '<')) { // 替换为实际的版本号
            // 获取现有任务
            $tasks = get_option($this->prefix . '-tasks', []);
            
            // 为每个任务添加调度类型
            foreach ($tasks as &$task) {
                if (!isset($task['task-schedule-type'])) {
                    $task['task-schedule-type'] = 'frequency';
                }
            }
            
            // 保存更新后的任务
            update_option($this->prefix . '-tasks', $tasks);
            
            // 记录迁移日志
            error_log("AI Post: 更新完成，已为现有任务设置默认调度类型为'按频率'");
        }
        
        // 更新版本号
        update_option($this->prefix . '-version', $plugin_version);
    }

    /**
     * 获取 WebP 支持状态的 HTML 提示
     * @return string
     */
    private function get_webp_support_status_html(): string
    {
        $gd_ok = extension_loaded('gd') && function_exists('imagewebp');
        $imagick_ok = extension_loaded('imagick');
        if ($gd_ok || $imagick_ok) {
            $support_details = [];
            if ($gd_ok) $support_details[] = 'GD (支持 WebP)';
            if ($imagick_ok) $support_details[] = 'Imagick';
            return '<span style="color: #46b450; margin-left: 10px; font-weight: bold;">(服务器支持: ' . implode(' / ', $support_details) . ')</span>';
        } else {
            return '<span style="color: #dc3232; margin-left: 10px; font-weight: bold;">(服务器不支持: 未启用 GD[WebP]/Imagick)</span>';
        }
    }

    // 日志表格渲染方法已迁移至 TraitRunLogPanel
    /**
     * 只读日志回显：当保存 ai-post-tasks 时，把本次即将入库的任务中与“配图方式三（文生图）”相关的关键字段打印到 debug.log。
     * 注意：不修改 $new_value，仅用于可观测性，便于判断运行时是否命中方式三。
     *
     * @param mixed  $new_value
     * @param mixed  $old_value
     * @param string $option  预期为 'ai-post-tasks'
     * @return mixed 原样返回 $new_value
     */
    // （方法已迁移至 TraitTasksRouteAndValidate）

    // （方法已迁移至 TraitTasksRouteAndValidate）

    // 顶部提示已取消：不再渲染“任务已保存到独立选项（ai-post-tasks）...”的管理提示。
    public function maybe_show_tasks_routed_notice(): void
    {
        return; // no-op
    }

    private function get_license_info(array $opts): array
    {
        $cardNum = isset($opts['cardNum']) ? trim((string)$opts['cardNum']) : '';
        $cardPwd = isset($opts['cardPwd']) ? trim((string)$opts['cardPwd']) : '';
        if ($cardNum === '' || $cardPwd === '') {
            return ['ok' => false, 'message' => '请先填写卡号与卡密', 'data' => null];
        }

        $base = 'http://api.suqianweb.cn/prod-api/plugin/auth/getAuthInfo/';
        $url = $base . rawurlencode($cardNum) . '/' . rawurlencode($cardPwd);

        $res = \wp_remote_get($url, [
            'timeout' => 12,
            'redirection' => 2,
        ]);

        if (\is_wp_error($res)) {
            return ['ok' => false, 'message' => '请求失败：' . $res->get_error_message(), 'data' => null];
        }

        $code = (int) \wp_remote_retrieve_response_code($res);
        $body = (string) \wp_remote_retrieve_body($res);
        $json = json_decode($body, true);
        if (!is_array($json)) {
            return ['ok' => false, 'message' => '响应解析失败（HTTP ' . $code . '）', 'data' => null];
        }

        $apiCode = isset($json['code']) ? (int)$json['code'] : 0;
        $msg = isset($json['msg']) ? (string)$json['msg'] : '';
        $data = (isset($json['data']) && is_array($json['data'])) ? $json['data'] : null;

        if ($apiCode === 500) {
            return ['ok' => false, 'message' => ($msg !== '' ? $msg : '校验失败'), 'data' => $data];
        }

        if ($apiCode !== 200 || !is_array($data)) {
            return ['ok' => false, 'message' => ($msg !== '' ? $msg : '校验失败'), 'data' => $data];
        }

        // 授权状态判定：
        // - 未激活卡密：允许通过（便于保存后在本域激活/使用），但标记为 unactivated
        // - 已激活卡密：必须具备可解析的激活/到期字段；跨域绑定由 model-selection 预检兜底
        $category = $this->pick_first_string($data, ['category', 'cardType', 'type']);
        if ($category === '') {
            $reason = '授权信息异常：未返回卡密类型';
            $plainMsg = trim((string)$msg);
            if ($plainMsg !== '' && !preg_match('/^操作成功$/u', $plainMsg)) {
                $reason = $plainMsg;
            }
            return ['ok' => false, 'message' => $reason, 'data' => $data];
        }

        $createTimeRaw = $this->pick_first_string($data, ['createTime', 'startTime', 'activeTime', 'activationTime', 'beginTime']);
        $endTimeRaw = $this->pick_first_string($data, ['endTime', 'expireTime', 'expirationTime', 'expiryTime', 'dueTime']);
        $createTime = $this->normalize_time_string($createTimeRaw);
        $endTime = $this->normalize_time_string($endTimeRaw);
        $createTs = $createTime !== '' ? strtotime($createTime) : false;
        $endTs = $endTime !== '' ? strtotime($endTime) : false;

        // 未激活：通常没有激活/到期时间
        if ($createTs === false || $endTs === false || $endTs <= 0) {
            $data['__aipost_status'] = 'unactivated';
            return ['ok' => true, 'message' => $msg, 'data' => $data];
        }

        $data['__aipost_status'] = 'activated';

        return ['ok' => true, 'message' => $msg, 'data' => $data];
    }

    private function verify_license_binding(string $cardNum, string $cardPwd): array
    {
        $cardNum = trim($cardNum);
        $cardPwd = trim($cardPwd);
        if ($cardNum === '' || $cardPwd === '') {
            return ['ok' => false, 'message' => '请先填写卡号与卡密'];
        }

        $hostname = isset($_SERVER['SERVER_NAME']) ? trim((string)$_SERVER['SERVER_NAME']) : '';
        if ($hostname === '') {
            $h = parse_url((string)get_option('home'), PHP_URL_HOST);
            $hostname = is_string($h) ? trim($h) : '';
        }
        if ($hostname === '') {
            $hostname = 'localhost';
        }
        $serverIp = @gethostbyname($hostname);
        if (!is_string($serverIp) || $serverIp === '') {
            $serverIp = '127.0.0.1';
        }

        $base = 'http://api.suqianweb.cn/prod-api/plugin/auth/';
        $url = $base . rawurlencode($cardNum) . '/' . rawurlencode($cardPwd);

        $res = \wp_remote_get($url, [
            'timeout' => 12,
            'redirection' => 2,
            'headers' => [
                'X-Forwarded-For' => $serverIp,
                'Host-Name' => $hostname,
            ],
        ]);
        if (\is_wp_error($res)) {
            return ['ok' => false, 'message' => '绑定校验请求失败：' . $res->get_error_message()];
        }

        $code = (int) \wp_remote_retrieve_response_code($res);
        $body = (string) \wp_remote_retrieve_body($res);
        $json = json_decode($body, true);
        if (!is_array($json)) {
            return ['ok' => false, 'message' => '绑定校验响应解析失败（HTTP ' . $code . '）'];
        }
        $apiCode = isset($json['code']) ? (int)$json['code'] : 0;
        $msg = isset($json['msg']) ? (string)$json['msg'] : '';
        if ($apiCode === 500) {
            if ($msg === '') { $msg = '设备认证失败：该卡密已被其他站点绑定或校验不通过'; }
            return ['ok' => false, 'message' => $msg];
        }
        if ($apiCode !== 200) {
            if ($msg === '') { $msg = '绑定校验失败'; }
            return ['ok' => false, 'message' => $msg];
        }
        return ['ok' => true, 'message' => $msg];
    }

    private function pick_first_string(array $arr, array $keys): string
    {
        foreach ($keys as $k) {
            if (isset($arr[$k]) && $arr[$k] !== null && $arr[$k] !== '') {
                return (string)$arr[$k];
            }
        }
        return '';
    }

    private function normalize_time_string(string $raw): string
    {
        $raw = trim($raw);
        if ($raw === '') { return ''; }
        if (preg_match('/^\d+$/', $raw)) {
            $n = (int)$raw;
            if ($n > 1000000000000) {
                $n = (int)floor($n / 1000);
            }
            if ($n > 0) {
                $ts = $n;
                $fmt = function_exists('wp_date') ? wp_date('Y-m-d H:i:s', $ts) : date('Y-m-d H:i:s', $ts);
                return (string)$fmt;
            }
        }

        $ts = strtotime($raw);
        if ($ts !== false) {
            $fmt = function_exists('wp_date') ? wp_date('Y-m-d H:i:s', $ts) : date('Y-m-d H:i:s', $ts);
            return (string)$fmt;
        }
        return $raw;
    }

    private function normalize_host(string $host): string
    {
        $host = strtolower(trim($host));
        $host = preg_replace('/^www\./', '', $host);
        return (string)$host;
    }

    private function extract_bound_host(array $data): string
    {
        $raw = $this->pick_first_string($data, [
            'bindDomain', 'bindHost', 'bindUrl', 'bindSite', 'bindWebsite',
            'domain', 'host', 'site', 'siteUrl', 'website', 'url',
            'authDomain', 'authHost', 'authUrl', 'authSite',
        ]);
        $raw = trim($raw);
        if ($raw === '') { return ''; }
        if (strpos($raw, '://') !== false) {
            $u = @parse_url($raw);
            if (is_array($u) && !empty($u['host'])) {
                return (string)$u['host'];
            }
        }
        $raw = preg_replace('/^https?:\/\//i', '', $raw);
        $raw = preg_replace('/\/.*$/', '', $raw);
        return (string)$raw;
    }

    private function render_license_info_html(array $opts): string
    {
        $info = $this->get_license_info($opts);
        if (empty($info['ok'])) {
            $m = isset($info['message']) ? (string)$info['message'] : '校验失败';
            return '<div style="max-width:300px;"><span class="button button-primary" style="width:200px;height:30px;line-height:30px;font-size:22px;text-align:center;">' . esc_html($m) . '</span></div>';
        }

        $data = is_array($info['data']) ? $info['data'] : [];
        if (isset($data['__aipost_status']) && $data['__aipost_status'] === 'unactivated') {
            return '<div style="max-width:640px;"><a class="button" style="width:60%;height:30px;line-height:30px;font-size:13px;margin-bottom:5px">卡密未激活：已校验通过，可保存后在本域使用时自动激活</a></div>';
        }
        $category = $this->pick_first_string($data, ['category', 'cardType', 'type']);
        $createTimeRaw = $this->pick_first_string($data, ['createTime', 'startTime', 'activeTime', 'activationTime', 'beginTime']);
        $endTimeRaw = $this->pick_first_string($data, ['endTime', 'expireTime', 'expirationTime', 'expiryTime', 'dueTime']);
        $createTime = $this->normalize_time_string($createTimeRaw);
        $endTime = $this->normalize_time_string($endTimeRaw);

        $html = '';
        $html .= '<div style="max-width:640px;">';
        $html .= '<span style="width:30%;height:30px;line-height:30px;font-size:15px;">卡密类型 -&gt; </span>';
        $html .= '<a class="button" style="width:30%;height:30px;line-height:30px;font-size:13px;margin-bottom:5px">' . esc_html($category) . '</a>';
        $html .= '<br/>';
        $html .= '<span style="width:30%;height:30px;line-height:30px;font-size:15px;">激活时间 -&gt; </span>';
        $html .= '<a class="button" style="width:30%;height:30px;line-height:30px;font-size:13px;margin-bottom:5px">' . esc_html($createTime) . '</a>';
        $html .= '<br/>';
        $html .= '<span style="width:30%;height:30px;line-height:30px;font-size:15px;">到期时间 -&gt; </span>';
        $html .= '<a class="button" style="width:30%;height:30px;line-height:30px;font-size:13px;margin-bottom:5px">' . esc_html($endTime) . '</a>';
        $html .= '</div>';
        return $html;
    }

    // 渲染：授权操作（即时校验）
    public function render_license_block(): void
    {
        $nonce = \wp_create_nonce('ai_post_check_license');
        $adminAjax = \admin_url('admin-ajax.php');
        // 初始渲染：预填当前授权状态（如可用）
        $initialHtml = '';
        $saved = \get_option('ai-post', []);
        if (!is_array($saved)) { $saved = []; }
        if (!empty($saved['cardNum']) && !empty($saved['cardPwd'])) {
            $initialHtml = $this->render_license_info_html($saved);
        }
        ?>
        <div class="ai-post-license-panel" style="background:#f8f9fa;border:1px solid #e5e7eb;border-radius:6px;padding:12px;">
            <div style="display:flex;gap:8px;align-items:center;margin-bottom:8px;">
                <button type="button" class="button button-primary" id="ai-post-validate-license">校验授权</button>
                <span style="color:#666;">保存并校验当前输入的卡号/卡密</span>
            </div>
            <div id="ai-post-live-auth" style="padding:8px;border-radius:4px;background:#fff;border:1px solid #e5e7eb;"><?php echo $initialHtml; ?></div>
        </div>
        <script>
        (function($){
            function findField(names, suffixSelector){
                for(var i=0;i<names.length;i++){
                    var $el = $('input[name="'+names[i]+'"]');
                    if($el.length){ return $el; }
                }
                var $suffix = $(suffixSelector);
                if($suffix.length){ return $suffix.first(); }
                return $();
            }

            $('#ai-post-validate-license').on('click', function(){
                var $btn = $(this);
                // cgps-framework/不同表单可能导致字段 name 不同，做兼容查找
                var $num = findField(['ai-post[cardNum]','aipost[cardNum]','cardNum'], 'input[name$="[cardNum]"],input[name$="cardNum"]');
                var $pwd = findField(['ai-post[cardPwd]','aipost[cardPwd]','cardPwd'], 'input[name$="[cardPwd]"],input[name$="cardPwd"]');
                var num = ($num.val() || '') + '';
                var pwd = ($pwd.val() || '') + '';
                $btn.prop('disabled', true).text('正在校验...');
                $.post('<?php echo esc_js($adminAjax); ?>', {
                    action: 'ai_post_check_license',
                    _ajax_nonce: '<?php echo esc_js($nonce); ?>',
                    cardNum: num,
                    cardPwd: pwd
                }).done(function(res){
                    var $live = $('#ai-post-live-auth');
                    if(res && res.success){
                        $live.html((res.data && res.data.html) ? res.data.html : '已保存并校验');
                    } else {
                        $live.html((res && res.data && res.data.message) ? res.data.message : '校验失败');
                    }
                    $live.show();
                }).fail(function(){
                    var $live = $('#ai-post-live-auth');
                    $live.html('请求失败');
                    $live.show();
                }).always(function(){
                    $btn.prop('disabled', false).text('校验授权');
                });
            });
        })(jQuery);
        </script>
        <?php
    }

    // AJAX：保存并即时校验授权
    public function ajax_check_license(): void
    {
        \check_ajax_referer('ai_post_check_license');
        if (!\current_user_can('manage_options')) {
            \wp_send_json_error(['message' => '权限不足'], 403);
        }
        @error_log('[ai-post][license] ajax_check_license entry');
        $cardNum = isset($_POST['cardNum']) ? trim((string) $_POST['cardNum']) : '';
        $cardPwd = isset($_POST['cardPwd']) ? trim((string) $_POST['cardPwd']) : '';

        // 授权调试日志：记录当前环境与入参（敏感字段做哈希脱敏）
        try {
            $logDir = (defined('WP_CONTENT_DIR') ? rtrim(WP_CONTENT_DIR, '/\\') : dirname(__DIR__, 3) . '/wp-content') . '/uploads/ai-post/logs';
            if (!@is_dir($logDir)) { @wp_mkdir_p($logDir); }
            if (!@is_dir($logDir)) { @mkdir($logDir, 0775, true); }
            $logFile = $logDir . '/license-debug.log';
            $meta = [
                'ts' => date('Y-m-d H:i:s'),
                'stage' => 'before_save',
                'plugin' => 'ai-post',
                'siteurl' => get_option('siteurl'),
                'home' => get_option('home'),
                'http_host' => $_SERVER['HTTP_HOST'] ?? null,
                'server_name' => $_SERVER['SERVER_NAME'] ?? null,
                'server_addr' => $_SERVER['SERVER_ADDR'] ?? null,
                'remote_addr' => $_SERVER['REMOTE_ADDR'] ?? null,
                'https' => isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : null,
                'x_forwarded_host' => $_SERVER['HTTP_X_FORWARDED_HOST'] ?? null,
                'x_forwarded_proto' => $_SERVER['HTTP_X_FORWARDED_PROTO'] ?? null,
                'request_uri' => $_SERVER['REQUEST_URI'] ?? null,
                'wp_is_ssl' => function_exists('is_ssl') ? is_ssl() : null,
                'multisite' => function_exists('is_multisite') ? is_multisite() : null,
                'cardNum_hash' => $cardNum !== '' ? substr(sha1($cardNum), 0, 12) : null,
                'cardPwd_hash' => $cardPwd !== '' ? substr(sha1($cardPwd), 0, 12) : null,
                'user' => wp_get_current_user() ? (wp_get_current_user()->user_login ?? null) : null,
            ];
            if (@file_put_contents($logFile, json_encode($meta, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) . "\n", FILE_APPEND) === false) {
                @error_log('[ai-post][license] write before_save failed: ' . $logFile);
            }
            @error_log('[ai-post][license] wrote before_save to: ' . $logFile);
        } catch (\Throwable $e) {
            // 忽略日志错误
            @error_log('[ai-post][license] before_save exception: ' . $e->getMessage());
        }

        // 暂不保存：先校验，再决定是否写入
        $pendingOpts = \get_option('ai-post', []);
        if (!is_array($pendingOpts)) { $pendingOpts = []; }
        $pendingOpts['cardNum'] = $cardNum;
        $pendingOpts['cardPwd'] = $cardPwd;

        $info = $this->get_license_info($pendingOpts);
        if (empty($info['ok'])) {
            $msg = isset($info['message']) ? (string)$info['message'] : '校验失败';
            \wp_send_json_error(['message' => $msg, 'expired' => false]);
        }

        $data = (isset($info['data']) && is_array($info['data'])) ? $info['data'] : [];
        $status = isset($data['__aipost_status']) ? (string)$data['__aipost_status'] : '';

        // 若上游返回了绑定域名/URL 信息，则直接比对当前站点
        $boundHost = $this->extract_bound_host($data);
        if ($status === 'activated' && $boundHost !== '') {
            $current = parse_url((string)get_option('home'), PHP_URL_HOST);
            $currentHost = $this->normalize_host((string)$current);
            $bindHost = $this->normalize_host((string)$boundHost);
            if ($currentHost !== '' && $bindHost !== '' && $currentHost !== $bindHost) {
                \wp_send_json_error(['message' => '设备认证失败：该卡密已绑定到其他站点（' . $bindHost . '）', 'expired' => false]);
            }
        }

        // 执行设备/域名绑定校验（迁移自 2.8.8 的 verify）：
        // 请求 /plugin/auth/{cardNum}/{cardPwd} 并携带 X-Forwarded-For + Host-Name 触发授权端绑定/激活
        $old = \get_option('ai-post', []);
        if (!is_array($old)) { $old = []; }
        \update_option('ai-post', $pendingOpts);
        $bind = $this->verify_license_binding($cardNum, $cardPwd);
        if (empty($bind['ok'])) {
            \update_option('ai-post', $old);
            $m = isset($bind['message']) ? (string)$bind['message'] : '设备认证失败：该卡密已被其他站点绑定或校验不通过';
            \wp_send_json_error(['message' => $m, 'expired' => false]);
        }

        // 预检通过后再拉一次，尽量拿到激活/到期时间用于回显
        $info = $this->get_license_info($pendingOpts);
        $data = (isset($info['data']) && is_array($info['data'])) ? $info['data'] : [];
        $status = isset($data['__aipost_status']) ? (string)$data['__aipost_status'] : $status;

        // 复用现有授权状态渲染（如存在）
        $html = $this->render_license_info_html($pendingOpts);

        // 授权调试日志：记录渲染结果片段
        try {
            $logDir = (defined('WP_CONTENT_DIR') ? rtrim(WP_CONTENT_DIR, '/\\') : dirname(__DIR__, 3) . '/wp-content') . '/uploads/ai-post/logs';
            if (!@is_dir($logDir)) { @wp_mkdir_p($logDir); }
            if (!@is_dir($logDir)) { @mkdir($logDir, 0775, true); }
            $logFile = $logDir . '/license-debug.log';
            $snippet = is_string($html) ? mb_substr(strip_tags($html), 0, 200, 'UTF-8') : '';
            $meta = [
                'ts' => date('Y-m-d H:i:s'),
                'stage' => 'after_render',
                'snippet' => $snippet,
            ];
            if (@file_put_contents($logFile, json_encode($meta, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) . "\n", FILE_APPEND) === false) {
                @error_log('[ai-post][license] write after_render failed: ' . $logFile);
            }
            @error_log('[ai-post][license] wrote after_render to: ' . $logFile);
        } catch (\Throwable $e) {
            // 忽略日志错误
            @error_log('[ai-post][license] after_render exception: ' . $e->getMessage());
        }

        $expired = false;
        $deviceFail = false;
        $invalid = false;
        $data2 = is_array($info['data']) ? $info['data'] : [];
        $status2 = isset($data2['__aipost_status']) ? (string)$data2['__aipost_status'] : '';
        if ($status2 === 'activated') {
            $endTimeRaw = $this->pick_first_string($data2, ['endTime', 'expireTime', 'expirationTime', 'expiryTime', 'dueTime']);
            $endTime = $this->normalize_time_string($endTimeRaw);
            $expTs = $endTime !== '' ? strtotime($endTime) : false;
            $nowTs = function_exists('current_time') ? current_time('timestamp') : time();
            if ($expTs !== false && $expTs < $nowTs) { $expired = true; }
        }
        
        if ($invalid || $expired || $deviceFail) {
            if ($expired) {
                @error_log('[ai-post][license] expired detected, block saving');
                \wp_send_json_error(['message' => '设备认证失败：该卡密已过期，请更换有效卡密', 'expired' => true]);
            }
            if ($deviceFail) {
                @error_log('[ai-post][license] device verification failed, block saving');
                \wp_send_json_error(['message' => '设备认证失败：该卡密已被其他域名绑定或校验不通过', 'expired' => false]);
            }
            $msg = isset($info['message']) ? (string)$info['message'] : '';
            if ($msg === '') { $msg = '授权码为空或无效'; }
            @error_log('[ai-post][license] invalid license, block saving: ' . $msg);
            \wp_send_json_error(['message' => $msg, 'expired' => false]);
        }

        // 校验通过才写入：此时 option 已是 pendingOpts（并已通过预检），无需重复写入

        \wp_send_json_success(['html' => $html, 'log_path' => isset($logFile) ? $logFile : null, 'expired' => false]);
    }

    // 服务器端兜底：保存前阻止过期卡密入库
    public function guard_expired_on_save($new_value, $old_value, $option)
    {
        try {
            // 仅针对 ai-post 主选项
            if (!is_array($new_value)) { return $new_value; }

            // 仅在“用户发起的设置保存”时才执行拦截：后台、存在 POST 提交
            if (!is_admin()) { return $new_value; }
            if (empty($_POST)) { return $new_value; }
            // AJAX 情况：仅当为 cgps-import（CGPS 配置保存）时才拦截，其它 AJAX 直接放行
            if (function_exists('wp_doing_ajax') && wp_doing_ajax()) {
                $act = isset($_POST['action']) ? (string)$_POST['action'] : '';
                if ($act !== 'cgps-import') { return $new_value; }
            }

            // 只要 POST 中提交了卡号/卡密，就执行检测
            $cardNum = isset($new_value['cardNum']) ? (string)$new_value['cardNum'] : '';
            $cardPwd = isset($new_value['cardPwd']) ? (string)$new_value['cardPwd'] : '';
            if ($cardNum === '' || $cardPwd === '') {
                \update_option('ai_post_expired_notice', '授权码为空或无效，请填写正确的卡号与卡密后再保存。');
                return $old_value;
            }

            // 临时注入待保存值，调用授权接口获取到期时间
            $pendingOpts = $new_value;
            $html = '';
            // 写入 guard 日志
            try {
                $logDir = (defined('WP_CONTENT_DIR') ? rtrim(WP_CONTENT_DIR, '/\\') : dirname(__DIR__, 3) . '/wp-content') . '/uploads/ai-post/logs';
                if (!@is_dir($logDir)) { @wp_mkdir_p($logDir); }
                if (!@is_dir($logDir)) { @mkdir($logDir, 0775, true); }
                $logFile = $logDir . '/license-debug.log';
                @file_put_contents($logFile, json_encode([
                    'ts' => date('Y-m-d H:i:s'),
                    'stage' => 'pre_update_guard',
                    'cardNum_hash' => $cardNum !== '' ? substr(sha1($cardNum),0,12) : null,
                    'cardPwd_hash' => $cardPwd !== '' ? substr(sha1($cardPwd),0,12) : null,
                ], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) . "\n", FILE_APPEND);
            } catch (\Throwable $e) {}

            $html = $this->render_license_info_html($pendingOpts);
            $info = $this->get_license_info($pendingOpts);
            $expired = false;
            $deviceFail = false;
            $invalid = false;
            if (empty($info['ok'])) {
                $invalid = true;
                $plain = isset($info['message']) ? (string)$info['message'] : '';
                if ($plain !== '' && preg_match('/设备认证失败|其他域名绑定|已被其他域名绑定|校验不通过/u', $plain)) {
                    $deviceFail = true;
                }
            } else {
                $data = is_array($info['data']) ? $info['data'] : [];
                $endTimeRaw = $this->pick_first_string($data, ['endTime', 'expireTime', 'expirationTime', 'expiryTime', 'dueTime']);
                $endTime = $this->normalize_time_string($endTimeRaw);
                $expTs = $endTime !== '' ? strtotime($endTime) : false;
                $nowTs = function_exists('current_time') ? current_time('timestamp') : time();
                if ($expTs !== false && $expTs < $nowTs) { $expired = true; }
            }
            if ($invalid || $expired || $deviceFail) {
                if ($expired) {
                    @error_log('[ai-post][license] guard_expired_on_save blocked: expired');
                    \update_option('ai_post_expired_notice', '卡密已过期，如需继续使用，请联系客服续期。');
                } elseif ($deviceFail) {
                    @error_log('[ai-post][license] guard_expired_on_save blocked: device verification failed');
                    \update_option('ai_post_expired_notice', '设备认证失败：该卡密已被其他域名绑定或校验不通过');
                } else {
                    $msg = isset($info['message']) ? (string)$info['message'] : '';
                    if ($msg === '') { $msg = '授权码为空或无效'; }
                    @error_log('[ai-post][license] guard_expired_on_save blocked: invalid - ' . $msg);
                    \update_option('ai_post_expired_notice', $msg);
                }
                return $old_value; // 阻止保存
            }
        } catch (\Throwable $e) {
            // 安全失败：不中断正常保存
            @error_log('[ai-post][license] guard_expired_on_save exception: ' . $e->getMessage());
        }
        return $new_value;
    }

    public function maybe_show_expired_notice(): void
    {
        $msg = \get_option('ai_post_expired_notice');
        if ($msg) {
            echo '<div class="notice notice-error is-dismissible"><p>' . esc_html($msg) . '</p></div>';
            \delete_option('ai_post_expired_notice');
        }
    }

    // 在设置页注入前端脚本：授权过期则禁用保存按钮
    public function inject_license_expire_guard_js(): void
    {
        if (!is_admin()) { return; }
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if (!$screen || strpos((string)$screen->id, 'ai-post') === false) { return; }
        $nonce = function_exists('wp_create_nonce') ? wp_create_nonce('ai_post_check_license') : '';
        ?>
        <script>
        (function($){
          var AIPO_NC = <?php echo json_encode($nonce); ?>;
          function markExpired(msg){
            // 顶部保存按钮
            var $btnTop = $('.cgps-header-right .cgps-buttons .cgps-top-save.cgps-save-ajax');
            if($btnTop.length){
              $btnTop.prop('disabled', true).addClass('button-disabled');
            }
            // 底部保存按钮
            var $btnBottom = $(".cgps-buttons input[name='cgps_transient[save]'].cgps-save-ajax");
            if($btnBottom.length){
              $btnBottom.prop('disabled', true).addClass('button-disabled');
            }
            // 顶部统一提示
            if($('.notice.aipost-expired-notice').length===0){
              var tip = msg && (msg+'').trim()!=='' ? msg+'' : '卡密已过期，如需继续使用，请联系客服续期。';
              var $notice = $('<div class="notice notice-error aipost-expired-notice"><p></p></div>');
              $notice.find('p').text(tip);
              $('#wpbody-content').find('.wrap').first().prepend($notice);
            } else {
              // 更新已有提示文案
              var tip = msg && (msg+'').trim()!=='' ? msg+'' : '卡密已过期，如需继续使用，请联系客服续期。';
              $('.notice.aipost-expired-notice').find('p').text(tip);
            }
          }

          // 修复：当用户输入新的未过期卡密并校验通过后，需要恢复保存按钮可用状态并移除过期提示
          function unmarkExpired(){
            // 顶部保存按钮
            var $btnTop = $('.cgps-header-right .cgps-buttons .cgps-top-save.cgps-save-ajax');
            if($btnTop.length){
              $btnTop.prop('disabled', false).removeClass('button-disabled');
            }
            // 底部保存按钮
            var $btnBottom = $(".cgps-buttons input[name='cgps_transient[save]'].cgps-save-ajax");
            if($btnBottom.length){
              $btnBottom.prop('disabled', false).removeClass('button-disabled');
            }
            // 移除顶部过期提示
            $('.notice.aipost-expired-notice').remove();
          }

          function findField(names){
            for(var i=0;i<names.length;i++){
              var sel = 'input[name="'+names[i]+'"]';
              var $el = $(sel);
              if($el.length && $.trim($el.val())!==''){ return $el; }
            }
            // 兜底：猜测以 [cardNum]/[cardPwd] 结尾
            var $guess = $('input[name$="[cardNum]"],input[name$="[cardPwd]"]');
            if($guess.length){ return $guess; }
            return $();
          }

          function autoCheck(){
            // 尝试多种常见命名
            var $num = findField(['ai-post[cardNum]','aipost[cardNum]','cardNum']);
            var $pwd = findField(['ai-post[cardPwd]','aipost[cardPwd]','cardPwd']);
            var num = $.trim($num.val()||'');
            var pwd = $.trim($pwd.val()||'');
            if(!num || !pwd){ markExpired('授权码为空或无效，请填写正确的卡号与卡密后再保存。'); return; }
            $.post(ajaxurl, {
              action: 'ai_post_check_license',
              _ajax_nonce: AIPO_NC,
              cardNum: num,
              cardPwd: pwd
            }).done(function(res){
              try{
                if(typeof res === 'string') res = JSON.parse(res);
              }catch(e){}
              if(res && res.success===false){
                var msg = res.data && res.data.message ? (res.data.message+'') : '';
                markExpired(msg);
              } else if(res && res.success===true){
                // 成功则恢复可保存状态
                var notExpired = !(res.data && res.data.expired===true);
                if(notExpired){ unmarkExpired(); }
              }
            });
          }

          // 代理全局 AJAX：专门识别 ai_post_check_license 的返回
          $(document).ajaxSuccess(function(e, xhr, settings){
            try{
              if(!settings || !settings.data) return;
              if(typeof settings.data === 'string' && settings.data.indexOf('action=ai_post_check_license') !== -1){
                var res = {};
                try{ res = JSON.parse(xhr.responseText || '{}'); }catch(ex){}
                if(res && res.success===false){
                  markExpired(res && res.data && res.data.message ? res.data.message+'' : '');
                }
                else if(res && res.success===true){ unmarkExpired(); }
              }
            }catch(ex){}
          });

          // 页面加载后自动校验一次
          $(function(){ autoCheck(); });
        })(jQuery);
        </script>
        <?php
    }
}
