<?php

namespace XZD\AI\V5\Tools;

use XZD\AI\V5\AI\Client;
use XZD\AI\V5\AI\Types;
use XZD\AI\V5\Core\Logger;

/**
 * AI 评论审核工具 — 自动审核评论质量
 *
 * 审核流程: 快速规则检查(不消耗AI) -> AI深度判断 -> 执行操作 -> 记录元数据
 */
class CommentModerator
{
    /**
     * 简单任务调用选项 — 路由到便宜模型并关闭 thinking 省 token
     */
    private static function simpleTaskOptions(int $maxTokens = 200): array
    {
        $opts = ['max_tokens' => $maxTokens, 'disable_thinking' => true];
        $model = \XZD\AI\V5\Core\Config::instance()->get('simple_task_model', 'deepseek-v4-flash');
        if (!empty($model)) {
            $opts['model'] = $model;
        }
        return $opts;
    }

    /**
     * 审核评论
     *
     * @param array $params 工具参数（comment_id, auto_moderate, strictness, min_words, block_urls, sensitive_words）
     * @param int   $userId 操作者ID
     */
    public static function moderate(array $params, int $userId): ToolResult
    {
        $commentId     = (int) ($params['comment_id'] ?? 0);
        $autoModerate  = $params['auto_moderate'] ?? true;
        $strictness    = $params['strictness'] ?? 'medium';
        $minWords      = (int) ($params['min_words'] ?? 2);
        $blockUrls     = $params['block_urls'] ?? true;
        $sensitiveWords = $params['sensitive_words'] ?? '';

        if (!$commentId) {
            return ToolResult::error('缺少评论ID', 'invalid_params');
        }

        $comment = get_comment($commentId);
        if (!$comment) {
            return ToolResult::error('评论不存在', 'not_found');
        }

        // 已审核过的跳过
        $existing = get_comment_meta($commentId, '_xzd_ai_moderation', true);
        if (!empty($existing)) {
            return ToolResult::success([
                'comment_id' => $commentId,
                'verdict'    => $existing['verdict'] ?? 'unknown',
                'skipped'    => true,
            ], '该评论已被AI审核过，跳过');
        }

        $content    = strip_tags($comment->comment_content);
        $authorName = $comment->comment_author;
        $authorEmail = $comment->comment_author_email;

        // 阶段1：快速规则检查（不消耗AI）

        // 字数检查
        $wordCount = mb_strlen(preg_replace('/\s+/', '', $content));
        if ($wordCount < $minWords) {
            return self::recordVerdict($commentId, 'pending', 'quick_rule:word_count', [
                'word_count' => $wordCount,
                'min_words'  => $minWords,
            ], '字数不足，待人工审核');
        }

        // URL检查
        if ($blockUrls && preg_match('/https?:\/\/\S+/i', $content)) {
            // 检查是否是白名单域名
            $whitelist = ['zblog.xzdbk.com', 'xzdbk.com', home_url()];
            $hasWhitelisted = false;
            foreach ($whitelist as $domain) {
                if (stripos($content, $domain) !== false) {
                    $hasWhitelisted = true;
                    break;
                }
            }
            if (!$hasWhitelisted) {
                return self::recordVerdict($commentId, 'pending', 'quick_rule:url_blocked', [
                    'has_url' => true,
                ], '包含外部链接，待人工审核');
            }
        }

        // 敏感词检查
        if (!empty($sensitiveWords)) {
            $words = array_map('trim', explode(',', $sensitiveWords));
            $words = array_filter($words, fn($w) => !empty($w));
            $matched = [];
            foreach ($words as $word) {
                if (mb_stripos($content, $word) !== false) {
                    $matched[] = $word;
                }
            }
            if (!empty($matched)) {
                wp_spam_comment($commentId);
                return self::recordVerdict($commentId, 'spam', 'quick_rule:sensitive_words', [
                    'matched_words' => $matched,
                ], '命中敏感词：' . implode(', ', $matched));
            }
        }

        // 阶段2：AI 深度判断
        if (!$autoModerate) {
            // 不启用AI审核 -> 默认通过
            wp_set_comment_status($commentId, 'approve');
            return self::recordVerdict($commentId, 'approve', 'auto_moderate_disabled', [], 'AI审核已关闭，默认通过');
        }

        try {
            $verdict = self::aiJudge($comment, $strictness);
        } catch (\Throwable $e) {
            Logger::error('comment_moderate', 'AI审核调用失败: ' . $e->getMessage());
            // AI不可用时保持pending，标记失败
            return self::recordVerdict($commentId, 'pending', 'ai_error', [
                'error' => $e->getMessage(),
            ], 'AI服务不可用，保持待审');
        }

        // 阶段3：执行操作
        return self::executeVerdict($commentId, $verdict);
    }

    /**
     * AI 深度审核判断
     */
    private static function aiJudge(\WP_Comment $comment, string $strictness): array
    {
        $content = strip_tags($comment->comment_content);

        // 获取文章内容（前2000字）
        $postContext = '';
        if ($comment->comment_post_ID) {
            $post = get_post($comment->comment_post_ID);
            if ($post) {
                $postContent = strip_tags($post->post_content);
                $postContext = mb_substr($postContent, 0, 2000);
            }
        }

        // 评论者历史
        $historyCount = (int) get_comments([
            'author_email' => $comment->comment_author_email,
            'count'        => true,
            'status'       => 'all',
        ]);
        $approvedCount = (int) get_comments([
            'author_email' => $comment->comment_author_email,
            'count'        => true,
            'status'       => 'approve',
        ]);

        $systemPrompt = <<<EOT
你是专业的网站评论审核员。你需要根据以下标准判断评论状态：

## 审核标准
1. **approve（通过）**: 正常交流、提问、感谢、补充信息、建设性意见
2. **pending（待审）**: 内容简短模糊、语义不清、无法确定意图
3. **spam（垃圾）**: 广告推广、无关链接、重复灌水、明显垃圾信息
4. **trash（删除）**: 人身攻击、违法内容、恶意代码、纯符号/乱码

## 审核严格度说明
- low: 仅拦截明显垃圾和违法内容
- medium: 标准审核
- high: 严格模式，简短/模糊评论也拦截

（当前采用哪种严格度见用户消息）
EOT;

        // 当前严格度移到 user 消息（system 保持纯静态以命中前缀缓存）
        $userPrompt = "## 当前审核严格度: {$strictness}\n\n"
            . "## 评论信息\n"
            . "- 作者: {$comment->comment_author}\n"
            . "- 邮箱: {$comment->comment_author_email}\n"
            . "- 历史评论数: {$historyCount}（其中{$approvedCount}条已通过）\n"
            . "- 评论内容: {$content}\n";

        if ($postContext) {
            $userPrompt .= "\n## 文章内容（前2000字）\n{$postContext}\n";
        }

        $userPrompt .= "\n请判断此评论应如何处理。返回JSON：{\"verdict\":\"approve|pending|spam|trash\",\"reason\":\"简短理由\"}";

        $result = Client::instance()->chatStructured(
            [Types::system($systemPrompt), Types::user($userPrompt)],
            [
                'type'       => 'object',
                'properties' => [
                    'verdict' => ['type' => 'string', 'enum' => ['approve', 'pending', 'spam', 'trash']],
                    'reason'  => ['type' => 'string'],
                ],
                'required' => ['verdict', 'reason'],
            ],
            self::simpleTaskOptions(200)
        );

        if (isset($result['error']) || empty($result['content'])) {
            throw new \RuntimeException($result['error'] ?? 'AI未返回结果');
        }

        return $result['content'];
    }

    /**
     * 执行审核判定
     *
     * 先写元数据再改状态，防止 transition_comment_status 钩子在元数据写入前触发，
     * 导致 handleCommentApproved 重复调度回复。
     */
    private static function executeVerdict(int $commentId, array $verdict): ToolResult
    {
        $action = $verdict['verdict'] ?? 'pending';
        $reason = $verdict['reason'] ?? '';

        // 先记录元数据（在改状态之前），防止竞态导致重复回复
        $meta = [
            'verdict'      => $action,
            'method'       => 'ai_judge',
            'details'      => [
                'ai_reason'  => $reason,
                'strictness' => $GLOBALS['_xzd_moderation_strictness'] ?? 'medium',
            ],
            'moderated_at' => current_time('mysql'),
            'moderated_by' => 'ai',
        ];
        update_comment_meta($commentId, '_xzd_ai_moderation', $meta);

        // 记录到操作日志
        Logger::info('comment_moderation', "comment #{$commentId} verdict: {$action} (ai_judge)", [
            'comment_id' => $commentId,
            'verdict'    => $action,
            'method'     => 'ai_judge',
        ]);

        // 再执行状态变更（此时元数据已就位，handleCommentApproved 可正确跳过）
        switch ($action) {
            case 'approve':
                wp_set_comment_status($commentId, 'approve');
                break;
            case 'spam':
                wp_spam_comment($commentId);
                break;
            case 'trash':
                wp_trash_comment($commentId);
                break;
            case 'pending':
            default:
                $action = 'pending';
                break;
        }

        return ToolResult::success([
            'comment_id' => $commentId,
            'verdict'    => $action,
            'method'     => 'ai_judge',
            'details'    => $meta['details'],
        ], $reason ?: "AI verdict: {$action}");
    }

    /**
     * 记录审核元数据
     */
    private static function recordVerdict(int $commentId, string $verdict, string $method, array $details, string $message): ToolResult
    {
        $meta = [
            'verdict'    => $verdict,
            'method'     => $method,
            'details'    => $details,
            'moderated_at' => current_time('mysql'),
            'moderated_by'  => 'ai',
        ];

        update_comment_meta($commentId, '_xzd_ai_moderation', $meta);

        // 记录到操作日志
        Logger::info('comment_moderation', "评论#{$commentId} 审核结果: {$verdict} ({$method})", [
            'comment_id' => $commentId,
            'verdict'    => $verdict,
            'method'     => $method,
        ]);

        return ToolResult::success([
            'comment_id' => $commentId,
            'verdict'    => $verdict,
            'method'     => $method,
            'details'    => $details,
        ], $message);
    }
}
