<?php

namespace XZD\AI\V5\REST\Controllers;

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

/**
 * 设置 REST 端点
 */
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;
        $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 可能只是因为值未变化，刷新缓存确保一致
            $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'];
                    if (isset($params['count'])) $data['autolink_max_total'] = (int) $params['count'];
                    if (isset($params['mode'])) $data['autolink_mode'] = $params['mode'];
                }
            }
        }

        // 二次持久化 — 将提取的 autolink flat keys 写回 DB
        if (isset($data['autolink_link_color']) || isset($data['autolink_max_total']) || isset($data['autolink_mode'])) {
            $config->merge($data);
            $config->save();
            $config->refresh();
        }

        // 如果修改了学习时间，自动重调度 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);
            }
        }

        // 如果修改了扫描间隔，自动重调度扫描 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);
            }
        }

        // 扫描范围变更时重置扫描游标状态，让新范围立即生效
        if (isset($data['pipeline']['scan_range'])) {
            delete_option('xzd_scan_state');
        }

        // 当定时扫描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');
                }
            }
        }

        // 如果修改了友链监控时间，自动重调度
        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');
            }
        }

        // 如果修改了清理时间，自动重调度
        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 → 字段缺失
                        //   或传回脱敏占位符 → 需从现有配置恢复
                        $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;
    }
}
