<?php

namespace XZD\AI\V5\REST\Controllers;

use XZD\AI\V5\REST\BaseController;
use XZD\AI\V5\Core\Config;
use WP_REST_Request;

/**
 * 设置 REST 端点
 *
 * GET  /settings              — 获取所有设置
 * POST /settings              — 保存设置
 * POST /settings/reset/{section} — 重置某模块
 * POST /settings/export        — 导出设置 JSON
 * POST /settings/import        — 导入设置 JSON
 */
class SettingsController extends BaseController
{
    public function registerRoutes(): void
    {
        $this->registerGet('/settings', [$this, 'index'], 'manage_options');
        $this->registerPost('/settings', [$this, 'save'], 'manage_options');
        $this->registerPost('/settings/reset/(?P<section>[a-zA-Z0-9_.]+)', [$this, 'reset'], 'manage_options');
        $this->registerPost('/settings/export', [$this, 'export'], 'manage_options');
        $this->registerPost('/settings/import', [$this, 'import'], 'manage_options');
    }

    public function index(WP_REST_Request $request): \WP_REST_Response
    {
        if ($err = $this->guardLicense('free')) return $err;
        $config = Config::instance();
        return $this->success($config->all());
    }

    public function save(WP_REST_Request $request): \WP_REST_Response
    {
        if ($err = $this->guardLicense('free')) return $err;
        // Nonce 容错：部分服务器 CDN/反向代理 可能剥离 Cookie 导致登录态丢失
        // 此时 current_user_can 已在 permission_callback 返回 403，
        // 能走到这里说明已通过权限检查，正常保存即可
        $data = $this->getBodyParams($request);
        if (empty($data) || !is_array($data)) {
            return $this->error('请求体不能为空', 'invalid_body');
        }

        $config = Config::instance();

        // 处理敏感字段加密
        $data = $this->encryptSensitiveFields($data);
        $config->merge($data);
        $saved = $config->save();

        if (!$saved) {
            // update_option 返回 false 可能只是因为值未变化（MySQL 0行影响）
            // 刷新缓存确保内存与 DB 一致，然后返回成功
            $config->refresh();
        }

        // ★ 从流水线阶段参数中提取 autolink 配置到全局键
        if (isset($data['pipeline']['stages'])) {
            foreach ($data['pipeline']['stages'] as $stage) {
                if (($stage['id'] ?? '') === 'build_autolink' && !empty($stage['params'])) {
                    $params = $stage['params'];
                    if (isset($params['link_color'])) $data['autolink_link_color'] = $params['link_color'];
                    if (isset($params['link_weight'])) $data['autolink_link_weight'] = $params['link_weight'];
                    if (isset($params['text_decoration'])) $data['autolink_text_decoration'] = $params['text_decoration'];
                }
            }
        }

        // V7：如果修改了学习时间，自动重调度 Cron
        if (isset($data['learning']['schedule_hour'])) {
            $newHour = (int) $data['learning']['schedule_hour'];
            if ($newHour >= 0 && $newHour <= 23) {
                \XZD\AI\V5\Core\Plugin::rescheduleLearningCron($newHour);
            }
        }

        // V7：如果修改了扫描间隔，自动重调度扫描 Cron
        if (isset($data['pipeline']['scan_interval'])) {
            $newInterval = (int) $data['pipeline']['scan_interval'];
            $triggers = $data['pipeline']['triggers'] ?? $config->get('pipeline.triggers', []);
            if ($newInterval >= 1 && $newInterval <= 60 && in_array('schedule', $triggers, true)) {
                \XZD\AI\V5\Core\Plugin::rescheduleScanCron($newInterval);
            }
        }

        // ★ 当定时扫描trigger被关闭时清除cron事件
        if (isset($data['pipeline']['triggers'])) {
            $triggers = $data['pipeline']['triggers'];
            if (!in_array('schedule', $triggers, true)) {
                $ts = wp_next_scheduled('xzd_ai_schedule_scan');
                if ($ts) {
                    wp_unschedule_event($ts, 'xzd_ai_schedule_scan');
                }
            }
        }

        // V7：如果修改了友链监控时间，自动重调度
        if (isset($data['friend_link']['monitor_hour']) || isset($data['friend_link']['monitor_enabled'])) {
            $enabled = $data['friend_link']['monitor_enabled'] ?? $config->bool('friend_link.monitor_enabled', false);
            $newHour = (int)($data['friend_link']['monitor_hour'] ?? $config->int('friend_link.monitor_hour', 2));
            $hasCron = (bool)wp_next_scheduled('xzd_ai_friend_link_monitor');
            if ($enabled && $newHour >= 0 && $newHour <= 23) {
                if ($hasCron) wp_unschedule_event(wp_next_scheduled('xzd_ai_friend_link_monitor'), 'xzd_ai_friend_link_monitor');
                \XZD\AI\V5\Core\Plugin::rescheduleFriendLinkMonitorCron($newHour);
            } elseif (!$enabled && $hasCron) {
                $ts = wp_next_scheduled('xzd_ai_friend_link_monitor');
                if ($ts) wp_unschedule_event($ts, 'xzd_ai_friend_link_monitor');
            }
        }

        // V7：如果修改了清理时间，自动重调度
        if (isset($data['cleanup']['hour'])) {
            $newHour = (int) $data['cleanup']['hour'];
            if ($newHour >= 0 && $newHour <= 23) {
                \XZD\AI\V5\Core\Plugin::rescheduleCleanupCron($newHour);
            }
        }

        return $this->success(null, '设置已保存');
    }

    public function reset(WP_REST_Request $request): \WP_REST_Response
    {
        if ($err = $this->guardLicense('free')) return $err;
        $section = $request->get_param('section');
        $config = Config::instance();
        $config->reset($section);

        return $this->success(null, "{$section} 已重置");
    }

    public function export(WP_REST_Request $request): \WP_REST_Response
    {
        if ($err = $this->guardLicense('free')) return $err;
        $config = Config::instance();
        return $this->success([
            'json'       => $config->export(),
            'exported_at' => current_time('mysql'),
        ]);
    }

    public function import(WP_REST_Request $request): \WP_REST_Response
    {
        if ($err = $this->guardLicense('free')) return $err;
        $json = $request->get_param('json');
        if (empty($json)) {
            return $this->error('请提供 JSON 数据', 'missing_json');
        }

        $config = Config::instance();
        if (!$config->import($json)) {
            return $this->error('JSON 格式无效', 'invalid_json');
        }

        return $this->success(null, '设置已导入');
    }

    // ===== 内部 =====

    /**
     * 对传入数据中的敏感字段进行加密
     */
    private function encryptSensitiveFields(array $data): array
    {
        $sensitiveKeys = ['api_key', 'pexels_key', 'unsplash_key', 'pixabay_key'];
        $config = Config::instance();

        // 遍历 connections.text 和 connections.image
        foreach (['text', 'image'] as $type) {
            if (isset($data['connections'][$type]) && is_array($data['connections'][$type])) {
                foreach ($data['connections'][$type] as $i => $conn) {
                    foreach ($sensitiveKeys as $key) {
                        // ★ 修复多模型密钥丢失：
                        //    前端对脱敏密钥执行 delete c.api_key → 字段缺失
                        //    或传回脱敏占位符 → 字段为 '••••••••（已加密）'
                        //    两种情况都需从现有配置恢复
                        //    **关键**: Config::get() 自动解密返回明文，直接判空即可
                        $isMissing  = !isset($conn[$key]);
                        $isMasked   = !$isMissing && strlen($conn[$key] ?? '') >= 4
                                      && preg_match('/^[•\*\●\×\·]{3,}/u', $conn[$key]);

                        if ($isMissing || $isMasked) {
                            $plaintext = $config->get("connections.{$type}.{$i}.{$key}", '');
                            if (!empty($plaintext)) {
                                // get() 返回明文 → 重新加密后存入 data
                                $data['connections'][$type][$i][$key] = $config->encrypt($plaintext);
                            } elseif ($isMasked) {
                                // 脱敏但DB无值 → 移除字段，不保存假值
                                unset($data['connections'][$type][$i][$key]);
                            }
                            // 字段缺失 + DB也无值 → 不处理（新连接无密钥）
                            continue;
                        }

                        if (str_starts_with($conn[$key], XZD_AI_ENC_PREFIX)) {
                            continue; // 已是加密值，跳过
                        }

                        // 明文密钥 → 加密
                        if (!empty($conn[$key])) {
                            $data['connections'][$type][$i][$key] = $config->encrypt($conn[$key]);
                        }
                    }
                }
            }
        }

        // 免费图库密钥 — 同样逻辑
        foreach (['pexels_key', 'unsplash_key', 'pixabay_key'] as $key) {
            $isMissing = !isset($data[$key]);
            $isMasked  = !$isMissing && strlen($data[$key] ?? '') >= 4
                         && preg_match('/^[•\*\●\×\·]{3,}/u', $data[$key]);

            if ($isMissing || $isMasked) {
                $plaintext = $config->get($key, '');
                if (!empty($plaintext)) {
                    $data[$key] = $config->encrypt($plaintext);
                } elseif ($isMasked) {
                    unset($data[$key]);
                }
                continue;
            }

            if (str_starts_with($data[$key], XZD_AI_ENC_PREFIX)) {
                continue;
            }

            if (!empty($data[$key])) {
                $data[$key] = $config->encrypt($data[$key]);
            }
        }

        return $data;
    }
}
