<?php

/**
 * AI 互动助手核心类
 */

namespace XHTheme\AIToolbox;

defined('ABSPATH') || exit;

class XHInteract extends XHTool
{

    private static $instance = null;
    private static $settings_cache = null;
    const OPTION_NAME = 'xhtheme_ai_toolbox_interact';
    const TABLE_NAME = 'xhaitoolbox_interact_log';

    const CACHE_GROUP = 'xhinteract';

    public static function getInstance()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct()
    {
        $this->init_hooks();
    }

    private function init_hooks()
    {
        $this->create_table();

        add_action('comment_post', [$this, 'on_comment_post'], 10, 1);
        add_filter('manage_edit-comments_columns', [$this, 'add_comment_columns']);
        add_action('manage_comments_custom_column', [$this, 'render_comment_column'], 10, 2);
        add_filter('xhaitoolbox_cronitem_interact', [$this, 'process_interact_task'], 10, 3);
        add_action('wp_ajax_xhinteract_save_settings', [$this, 'ajax_save_settings']);
        add_action('wp_ajax_xhinteract_get_users', [$this, 'ajax_get_users']);
        add_action('wp_ajax_xhinteract_get_logs', [$this, 'ajax_get_logs']);
        add_action('wp_ajax_xhinteract_get_stats', [$this, 'ajax_get_stats']);
        add_action('wp_ajax_xhinteract_batch_action', [$this, 'ajax_batch_action']);
        add_action('wp_ajax_xhinteract_export_logs', [$this, 'ajax_export_logs']);
        add_action('wp_ajax_xhinteract_get_categories', [$this, 'ajax_get_categories']);
        add_action('wp_ajax_xhinteract_cleanup_logs', [$this, 'ajax_cleanup_logs']);
        add_action('wp_ajax_xhinteract_create_ai_user', [$this, 'ajax_create_ai_user']);
        add_action('wp_ajax_xhinteract_upload_ai_avatar', [$this, 'ajax_upload_ai_avatar']);
        add_action('xhaitoolbox_minute_cron', [$this, 'process_randcomment'], 7);

        // 前端评论内容高亮召唤词
        add_filter('get_comment_text', [$this, 'highlight_comment_summon_words'], 20, 3);
    }

    /**
     * 创建记录表
     */
    private function create_table()
    {
        if (get_option('xhtheme_ai_toolbox_interact_dbver') == XHTHEME_AI_TOOLBOX_VERSION) {
            return;
        }

        global $wpdb;
        $table_name = $wpdb->prefix . self::TABLE_NAME;
        $charset_collate = $wpdb->get_charset_collate();

        // type: audit/reply/moderator
        // result: approved/rejected/replied/skipped/error
        $sql = "CREATE TABLE $table_name (
            id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
            commentid BIGINT UNSIGNED NOT NULL COMMENT '原评论',
            postid BIGINT UNSIGNED NOT NULL COMMENT '文章',
            type VARCHAR(20) NOT NULL COMMENT '类型',
            result VARCHAR(20) NOT NULL COMMENT '结果',
            keyword VARCHAR(100) COMMENT '关键词',
            replier BIGINT UNSIGNED COMMENT '回复者',
            replyid BIGINT UNSIGNED COMMENT '回复ID',
            reason VARCHAR(255) COMMENT '原因',
            extra VARCHAR(255) COMMENT '备用',
            createdat DATETIME NOT NULL COMMENT '时间',
            PRIMARY KEY  (id),
            KEY idx_commentid (commentid),
            KEY idx_postid (postid),
            KEY idx_type (type),
            KEY idx_createdat (createdat)
        ) $charset_collate;";

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        dbDelta($sql);

        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name variable is safe
        $query = $wpdb->prepare("SHOW TABLES LIKE %s", $table_name);
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- Checking table existence
        if ($wpdb->get_var($query) == $table_name) {
            update_option('xhtheme_ai_toolbox_interact_dbver', XHTHEME_AI_TOOLBOX_VERSION);
        }
    }

    /**
     * 获取默认配置
     */
    public static function get_default_settings()
    {
        return [
            'enabled' => false,

            'audit' => [
                'enabled' => false,
                'presets' => ['ads_content', 'spam', 'malicious_links', 'sensitive_words'],
                'fail_action' => 'auto', // auto | pending | spam
                'delay_minutes' => 0 // 延迟审核时间（分钟），0 表示立即审核
            ],

            'auto_reply' => [
                'enabled' => false,

                'trigger_mode' => 'ai', // ai | keywords
                'keywords' => ['请问', '吗', '？'],
                'enthusiasm' => 'medium', // low | medium | high (克制/适中/热情)
                'delay_min' => 5,
                'delay_max' => 30,

                'author_reply' => true,
                'author_reply_mode' => 'all', // all | specified (托管所有作者 | 托管指定作者)
                'author_reply_users' => [], // [{id, name}]

                'smart_reply' => true,
                'smart_reply_mode' => 'random_ai', // random_ai | specified
                'smart_reply_aicount' => 100,
                'smart_reply_users' => [],
                'smart_reply_styles' => ['friendly', 'professional', 'humorous', 'concise', 'enthusiastic', 'incisive'],

                'exclude_admin' => false,
                'exclude_author' => false,
                'exclude_has_reply' => true,
                'exclude_short' => true,

                'rate_limit_enabled' => false,
                'max_per_post' => 10,
                'max_per_day' => 200,
            ],

            'moderator' => [
                'enabled' => false,
                'role_style' => 'auto', // auto | tech | acg | entertainment | resource
                'bindings' => []  // [{ keyword: '@豆包', user_id: 123, user_name: '豆包AI' }]
            ],

            'email_notify' => [
                'enabled' => false,
                'recipient' => 'admin', // admin | custom
                'custom_email' => '',
                'notify_audit_rejected' => true,
                'notify_audit_approved' => true,
                'notify_reply_sent' => true
            ],

            'rand_comment' => [
                'enabled' => false,

                // 文章类型
                'post_types' => ['post'],             // 评论的文章类型
                // 频率限制
                'interval_minutes' => 5,           // 间隔分钟（3-10）
                'max_per_post' => 5,               // 每篇最多评论（1-20）
                'max_per_day' => 50,               // 每天最多评论（10-200）
                'blackout_start' => 1,             // 禁止时段开始（0-24）
                'blackout_end' => 9,               // 禁止时段结束（0-24）

                // 动作设置
                'trigger_smart_reply' => true,    // 是否触发智能回复
                'smart_reply_probability' => 50,   // 触发概率（10-100）
                'trigger_moderator' => true,      // 是否触发AI评论官回复
                'moderator_probability' => 5,      // 触发概率 1-20%
                'moderator_max_daily' => 10,       // 每日最大次数 2-20
                'moderator_max_per_post' => 2,     // 单篇最多触发 1-10

                // 评论身份
                'identity_mode' => 'ai_user',      // visitor | ai_user
                'ai_user_limit' => 100            // AI用户生成上限
            ]
        ];
    }
    /**
     * 获取配置
     */
    public function get_settings($key = null, $default = null)
    {
        if (self::$settings_cache === null) {
            $settings = get_option(self::OPTION_NAME, []);
            self::$settings_cache = wp_parse_args($settings, self::get_default_settings());
        }

        if ($key === null) {
            return self::$settings_cache;
        }

        $keys = explode('.', $key);
        $value = self::$settings_cache;
        foreach ($keys as $k) {
            if (!isset($value[$k])) {
                return $default;
            }
            $value = $value[$k];
        }
        return $value;
    }

    /**
     * 验证 AJAX 管理员请求
     * 统一检查 nonce 和权限，减少代码重复
     * 
     * @return void 验证失败时终止请求并返回错误响应
     */
    private function verify_ajax_admin_request()
    {
        check_ajax_referer('xhinteract_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => 'Permission denied']);
        }
    }

    /**
     * 清理缓存
     */
    public function clear_cache($type = null, $post_id = null)
    {
        $today = current_time('Y-m-d');

        switch ($type) {
            case 'post':
                if ($post_id) {
                    wp_cache_delete($post_id, self::CACHE_GROUP);
                }
                break;

            case 'day':
                wp_cache_delete($today, self::CACHE_GROUP);
                break;

            case 'stats_audit':
                wp_cache_delete('stats_audit', self::CACHE_GROUP);
                break;

            case 'stats_reply':
                wp_cache_delete('stats_reply', self::CACHE_GROUP);
                break;

            case 'all':
                if ($post_id) {
                    wp_cache_delete($post_id, self::CACHE_GROUP);
                }
                wp_cache_delete($today, self::CACHE_GROUP);
                wp_cache_delete('stats_audit', self::CACHE_GROUP);
                wp_cache_delete('stats_reply', self::CACHE_GROUP);
                break;

            default:
                if ($post_id) {
                    wp_cache_delete($post_id, self::CACHE_GROUP);
                }
                wp_cache_delete($today, self::CACHE_GROUP);
                break;
        }
    }

    /**
     * 高亮评论内容中的召唤词
     */
    public function highlight_comment_summon_words($comment_text, $comment = null, $args = [])
    {
        $summon_map = xh_get_aiwords();
        if (empty($summon_map)) {
            return $comment_text;
        }

        $keywords = array_keys($summon_map);
        usort($keywords, function ($a, $b) {
            return strlen($b) - strlen($a);
        });

        foreach ($keywords as $keyword) {
            $escaped = preg_quote($keyword, '/');
            $replacement = '<span class="xh-summon-word">' . esc_html($keyword) . '</span>';
            $comment_text = preg_replace('/' . $escaped . '/u', $replacement, $comment_text);
        }

        return $comment_text;
    }

    /**
     * 补全设置中的用户信息
     */
    public function enrich_settings_for_admin($settings)
    {

        if (!empty($settings['auto_reply']['author_reply_users'])) {
            $settings['auto_reply']['author_reply_users'] = $this->enrich_user_array(
                $settings['auto_reply']['author_reply_users']
            );
        }

        if (!empty($settings['auto_reply']['smart_reply_users'])) {
            $settings['auto_reply']['smart_reply_users'] = $this->enrich_user_array(
                $settings['auto_reply']['smart_reply_users']
            );
        }

        if (!empty($settings['moderator']['bindings'])) {
            $settings['moderator']['bindings'] = $this->enrich_bindings_array(
                $settings['moderator']['bindings']
            );
        }

        return $settings;
    }

    /**
     * 补全用户数组的详细信息
     */
    private function enrich_user_array($users)
    {
        foreach ($users as &$user) {
            if (!empty($user['id'])) {
                $wp_user = get_userdata($user['id']);
                if ($wp_user) {
                    $user['display_name'] = $wp_user->display_name;
                    $user['avatar_url'] = get_avatar_url($user['id'], ['size' => 32]);
                } else {
                    $user['display_name'] = $user['name'] ?? esc_html__('Deleted User', 'xhtheme-ai-toolbox');
                    $user['avatar_url'] = '';
                }
            }
        }
        return $users;
    }

    /**
     * 保存配置（同时清除缓存）
     */
    public function save_settings($settings)
    {
        self::$settings_cache = null;
        return update_option(self::OPTION_NAME, $settings);
    }


    /**
     * AJAX: 保存设置
     */
    public function ajax_save_settings()
    {
        $this->verify_ajax_admin_request();

        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- JSON string, sanitized after decode
        $raw_settings = isset($_POST['settings']) ? wp_unslash($_POST['settings']) : '{}';
        $input = json_decode($raw_settings, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            wp_send_json_error(['message' => 'Invalid JSON']);
        }

        $settings = $this->sanitize_by_schema($input, self::get_default_settings());

        $settings['enabled'] = !empty($settings['audit']['enabled'])
            || !empty($settings['auto_reply']['author_reply'])
            || !empty($settings['auto_reply']['smart_reply'])
            || !empty($settings['moderator']['enabled']);

        if (
            !empty($settings['auto_reply']['enabled'])
            && empty($settings['auto_reply']['author_reply'])
            && empty($settings['auto_reply']['smart_reply'])
        ) {
            $settings['auto_reply']['enabled'] = false;
        }

        if (
            !empty($settings['auto_reply']['author_reply'])
            && ($settings['auto_reply']['author_reply_mode'] ?? 'all') === 'specified'
            && empty($settings['auto_reply']['author_reply_users'])
        ) {
            $settings['auto_reply']['author_reply_mode'] = 'all';
        }

        $required_presets = ['spam', 'malicious_links'];
        $current_presets = $settings['audit']['presets'] ?? [];
        $settings['audit']['presets'] = array_values(array_unique(array_merge($required_presets, $current_presets)));

        $this->save_settings($settings);
        xh_clear_aiwords_cache();

        wp_send_json_success(['message' => 'Settings saved']);
    }

    /**
     * 基于默认值结构自动清理输入
     */
    private function sanitize_by_schema($input, $defaults, $path = '')
    {
        $clean = [];

        foreach ($defaults as $key => $default) {
            $value = $input[$key] ?? null;

            if (is_bool($default)) {
                $clean[$key] = !empty($value);
                continue;
            }

            if (is_int($default)) {
                $clean[$key] = absint($value ?? $default);
                continue;
            }

            // 随手一评配置使用专用清理方法
            if ($key === 'rand_comment' && is_array($default)) {
                $clean[$key] = $this->sanitize_rand_comment($value ?? [], $default);
                continue;
            }

            // 邮件通知配置使用专用清理方法
            if ($key === 'email_notify' && is_array($default)) {
                $clean[$key] = $this->sanitize_email_notify($value ?? [], $default);
                continue;
            }

            if (is_array($default) && !empty($default) && !$this->is_indexed_array($default)) {
                $clean[$key] = $this->sanitize_nested_config($value ?? [], $default);
                continue;
            }

            if (is_array($default) && $this->is_indexed_array($default)) {
                $clean[$key] = is_array($value)
                    ? array_values(array_filter(array_map('sanitize_text_field', $value)))
                    : $default;
                continue;
            }

            $clean[$key] = sanitize_text_field($value ?? $default);
        }

        if (isset($clean['auto_reply']['delay_min'], $clean['auto_reply']['delay_max'])) {
            if ($clean['auto_reply']['delay_max'] < $clean['auto_reply']['delay_min']) {
                $clean['auto_reply']['delay_max'] = $clean['auto_reply']['delay_min'];
            }
        }

        return $clean;
    }

    /**
     * 清理二级配置
     */
    private function sanitize_nested_config($input, $defaults)
    {
        $clean = [];

        foreach ($defaults as $key => $default) {
            $value = $input[$key] ?? null;

            if ($key === 'smart_reply_users') {
                $clean[$key] = $this->sanitize_scoped_users($value ?? []);
                continue;
            }

            if ($key === 'bindings') {
                $clean[$key] = $this->sanitize_bindings($value ?? []);
                continue;
            }

            if ($key === 'author_reply_users') {
                $clean[$key] = $this->sanitize_simple_users($value ?? []);
                continue;
            }

            if (is_bool($default)) {
                $clean[$key] = !empty($value);
                continue;
            }

            if (is_int($default)) {
                $clean[$key] = absint($value ?? $default);
                continue;
            }

            if (is_array($default) && $this->is_indexed_array($default)) {
                $clean[$key] = is_array($value)
                    ? array_values(array_filter(array_map('sanitize_text_field', $value)))
                    : $default;
                continue;
            }

            $clean[$key] = sanitize_text_field($value ?? $default);
        }

        return $clean;
    }

    /**
     * 清理随手一评配置
     */
    private function sanitize_rand_comment($input, $defaults)
    {
        // 清理 post_types
        $post_types = $defaults['post_types'];
        if (!empty($input['post_types']) && is_array($input['post_types'])) {
            $post_types = array_map('sanitize_key', $input['post_types']);
            $post_types = array_filter($post_types);
        }
        if (empty($post_types)) {
            $post_types = ['post'];
        }

        return [
            'enabled' => !empty($input['enabled']),

            'post_types' => array_values($post_types),

            'interval_minutes' => max(3, min(10, absint($input['interval_minutes'] ?? $defaults['interval_minutes']))),
            'max_per_post' => max(1, min(20, absint($input['max_per_post'] ?? $defaults['max_per_post']))),
            'max_per_day' => max(10, min(200, absint($input['max_per_day'] ?? $defaults['max_per_day']))),
            'blackout_start' => max(0, min(24, absint($input['blackout_start'] ?? $defaults['blackout_start']))),
            'blackout_end' => max(0, min(24, absint($input['blackout_end'] ?? $defaults['blackout_end']))),

            'trigger_smart_reply' => !empty($input['trigger_smart_reply']),
            'smart_reply_probability' => max(10, min(100, absint($input['smart_reply_probability'] ?? $defaults['smart_reply_probability']))),
            'trigger_moderator' => !empty($input['trigger_moderator']),
            'moderator_probability' => max(1, min(20, absint($input['moderator_probability'] ?? $defaults['moderator_probability']))),
            'moderator_max_daily' => max(2, min(20, absint($input['moderator_max_daily'] ?? $defaults['moderator_max_daily']))),
            'moderator_max_per_post' => max(1, min(10, absint($input['moderator_max_per_post'] ?? $defaults['moderator_max_per_post']))),

            'identity_mode' => in_array($input['identity_mode'] ?? '', ['visitor', 'ai_user'], true)
                ? $input['identity_mode']
                : $defaults['identity_mode'],
            'ai_user_limit' => max(10, min(500, absint($input['ai_user_limit'] ?? $defaults['ai_user_limit'])))
        ];
    }

    /**
     * 清理邮件通知配置
     */
    private function sanitize_email_notify($input, $defaults)
    {
        return [
            'enabled' => !empty($input['enabled']),
            'recipient' => sanitize_text_field($input['recipient'] ?? $defaults['recipient']),
            'custom_email' => sanitize_email($input['custom_email'] ?? ''),
            'notify_audit_rejected' => !empty($input['notify_audit_rejected']),
            'notify_audit_approved' => !empty($input['notify_audit_approved']),
            'notify_reply_sent' => !empty($input['notify_reply_sent']),
        ];
    }

    /**
     * 清理简单用户数组
     */
    private function sanitize_simple_users($users)
    {
        $clean = [];
        foreach ((array) $users as $user) {
            if (empty($user['id']) || !is_numeric($user['id'])) {
                continue;
            }
            $clean[] = [
                'id' => absint($user['id']),
                'name' => sanitize_text_field($user['name'] ?? '')
            ];
        }
        return $clean;
    }

    /**
     * 清理评论官绑定数组（支持 keywords 数组格式）
     */
    private function sanitize_bindings($bindings)
    {
        $clean = [];
        foreach ((array) $bindings as $binding) {
            if (empty($binding['user_id'])) {
                continue;
            }

            $keywords = [];
            if (!empty($binding['keywords']) && is_array($binding['keywords'])) {
                $keywords = array_values(array_filter(array_map('sanitize_text_field', $binding['keywords'])));
            } elseif (!empty($binding['keyword'])) {
                $keywords = [sanitize_text_field($binding['keyword'])];
            }

            if (empty($keywords)) {
                continue;
            }

            $clean[] = [
                'keywords' => $keywords,
                'user_id' => absint($binding['user_id']),
                'user_name' => sanitize_text_field($binding['user_name'] ?? '')
            ];
        }
        return $clean;
    }

    /**
     * 补全绑定数组的用户详细信息
     */
    private function enrich_bindings_array($bindings)
    {
        foreach ($bindings as &$binding) {
            if (!empty($binding['user_id'])) {
                $wp_user = get_userdata($binding['user_id']);
                if ($wp_user) {
                    $binding['user_name'] = $wp_user->display_name;
                    $binding['avatar_url'] = get_avatar_url($binding['user_id'], ['size' => 32]);
                } else {
                    $binding['user_name'] = $binding['user_name'] ?? esc_html__('Deleted User', 'xhtheme-ai-toolbox');
                    $binding['avatar_url'] = '';
                }
            }
        }
        return $bindings;
    }


    /**
     * 清理带范围的用户数组
     */
    private function sanitize_scoped_users($users)
    {
        $clean = [];
        foreach ((array) $users as $user) {
            if (empty($user['id']) || !is_numeric($user['id'])) {
                continue;
            }

            $item = [
                'id' => absint($user['id']),
                'name' => sanitize_text_field($user['name'] ?? ''),
                'scope' => 'global'
            ];

            if (isset($user['scope']) && is_array($user['scope'])) {
                $item['scope'] = [
                    'post_types' => array_values(array_filter(array_map('sanitize_key', (array) ($user['scope']['post_types'] ?? [])))),
                    'categories' => []
                ];

                if (!empty($user['scope']['categories']) && is_array($user['scope']['categories'])) {
                    foreach ($user['scope']['categories'] as $pt => $cats) {
                        $pt_clean = sanitize_key($pt);
                        $item['scope']['categories'][$pt_clean] = array_values(array_filter(array_map('absint', (array) $cats)));
                    }
                }
            }

            $clean[] = $item;
        }
        return $clean;
    }

    /**
     * AJAX: 搜索用户
     */
    public function ajax_get_users()
    {
        $this->verify_ajax_admin_request();

        $search = isset($_GET['search']) ? sanitize_text_field(wp_unslash($_GET['search'])) : '';

        $users = get_users([
            'search' => '*' . $search . '*',
            'search_columns' => ['user_login', 'user_email', 'display_name'],
            'number' => 20
        ]);

        $result = [];
        foreach ($users as $user) {
            $result[] = [
                'id' => $user->ID,
                'name' => $user->display_name,
                'email' => $user->user_email,
                'role' => implode(', ', $user->roles),
                'avatar' => get_avatar_url($user->ID, ['size' => 32])
            ];
        }

        wp_send_json_success($result);
    }

    /**
     * AJAX: 获取分类列表
     */
    public function ajax_get_categories()
    {
        $this->verify_ajax_admin_request();

        $result = [];
        $post_types = get_post_types([
            'public' => true,
        ], 'objects');

        foreach ($post_types as $post_type) {
            if ($post_type->name === 'attachment') {
                continue;
            }

            $pt_data = [
                'name' => $post_type->name,
                'label' => $post_type->label,
                'has_categories' => false,
                'categories' => []
            ];

            $taxonomies = get_object_taxonomies($post_type->name, 'objects');

            foreach ($taxonomies as $taxonomy) {
                if (!$taxonomy->hierarchical || !$taxonomy->public) {
                    continue;
                }

                $terms = get_terms([
                    'taxonomy' => $taxonomy->name,
                    'hide_empty' => false,
                    'orderby' => 'name',
                    'order' => 'ASC'
                ]);

                if (!is_wp_error($terms) && !empty($terms)) {
                    $pt_data['has_categories'] = true;

                    foreach ($terms as $term) {
                        $pt_data['categories'][] = [
                            'id' => $term->term_id,
                            'name' => $term->name,
                            'slug' => $term->slug,
                            'taxonomy' => $taxonomy->name,
                            'taxonomy_label' => $taxonomy->label
                        ];
                    }
                }
            }

            $result[] = $pt_data;
        }

        wp_send_json_success($result);
    }

    /**
     * AJAX: 创建 AI 用户
     */
    public function ajax_create_ai_user()
    {
        $this->verify_ajax_admin_request();

        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized below
        $nickname = isset($_POST['nickname']) ? sanitize_text_field(wp_unslash($_POST['nickname'])) : '';
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized below
        $email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : '';
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized below
        $avatar_url = isset($_POST['avatar_url']) ? esc_url_raw(wp_unslash($_POST['avatar_url'])) : '';
        if (empty($nickname)) {
            wp_send_json_error(__('Please enter a nickname', 'xhtheme-ai-toolbox'));
        }

        if (empty($email) || !is_email($email)) {
            wp_send_json_error(__('Invalid email format', 'xhtheme-ai-toolbox'));
        }
        while (email_exists($email)) {
            $email = $this->generateRandomEmail('custom_');
        }
        $email_prefix = substr($email, 0, strpos($email, '@'));
        $user_login = $email_prefix;
        if (username_exists($user_login)) {
            $user_login = $user_login . '_' . wp_rand(100, 999);
        }

        $userdata = [
            'user_login' => $user_login,
            'user_email' => $email,
            'user_pass' => wp_generate_password(12, false),
            'display_name' => $nickname,
            'nickname' => $nickname,
            'role' => 'author'
        ];

        $user_id = wp_insert_user($userdata);

        if (is_wp_error($user_id)) {
            wp_send_json_error($user_id->get_error_message());
        }

        if (!empty($avatar_url)) {
            update_user_meta($user_id, '_ai_avatar', $avatar_url);
            update_user_meta($user_id, '_xhai_role', 'xhaiuser');
        }

        wp_send_json_success([
            'id' => $user_id,
            'name' => $nickname,
            'email' => $email,
            'avatar' => !empty($avatar_url) ? $avatar_url : get_avatar_url($user_id, ['size' => 32])
        ]);
    }

    /**
     * AJAX: 上传 AI 头像
     */
    public function ajax_upload_ai_avatar()
    {
        $this->verify_ajax_admin_request();

        if (empty($_FILES['avatar']) || !is_array($_FILES['avatar'])) {
            wp_send_json_error(__('Please select a file to upload', 'xhtheme-ai-toolbox'));
        }

        // 确保 XH_AvatarLocal 类已加载
        if (!class_exists(__NAMESPACE__ . '\\XH_AvatarLocal')) {
            require_once plugin_dir_path(__FILE__) . 'class-xhtheme-avatarlocal.php';
        }

        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Uploaded file array is validated by XH_AvatarLocal::upload_avatar().
        $avatar_file = $_FILES['avatar'];
        $result = XH_AvatarLocal::upload_avatar($avatar_file);
        if (is_wp_error($result)) {
            wp_send_json_error($result->get_error_message());
        }

        wp_send_json_success($result);
    }

    /**
     * 评论发布拦截
     */
    public function on_comment_post($comment_id)
    {
        if (!$this->get_settings('enabled')) {
            return;
        }

        $comment = get_comment($comment_id);
        if (!$comment) {
            return;
        }

        if (get_comment_meta($comment->comment_ID, '_ai_task_status', true)) {
            return;
        }

        $interact_type = get_comment_meta($comment->comment_ID, '_ai_interact_type', true);
        if ($interact_type && $interact_type !== 'randcomment') {
            return;
        }
        if ($interact_type === 'randcomment') {
            $rand_settings = $this->get_settings('rand_comment');
            if (empty($rand_settings['enabled']) || (empty($rand_settings['trigger_smart_reply']) && empty($rand_settings['trigger_moderator']))) {
                return;
            }
        }

        // 计算延迟时间
        $scheduled = null;
        if ($interact_type !== 'randcomment') {
            $audit_settings = $this->get_settings('audit');
            if (!empty($audit_settings['enabled']) && !empty($audit_settings['delay_minutes'])) {
                $delay_minutes = absint($audit_settings['delay_minutes']);
                if ($delay_minutes > 0) {
                    // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
                    $scheduled = date('Y-m-d H:i:s', strtotime(current_time('mysql')) + ($delay_minutes * 60));
                }
            }
        }

        if (xh_cron_insert($comment->comment_ID, 'interact', [], 0, 'hold', $scheduled)) {
            update_comment_meta($comment->comment_ID, '_ai_task_status', 'pending');
        }
    }

    /**
     * 判断是否需要审核
     */
    private function check_audit($comment)
    {
        $audit = $this->get_settings('audit');
        if (empty($audit['enabled'])) {
            return false;
        }

        if ($comment->comment_approved === '1') {
            return false;
        }

        return true;
    }

    /**
     * 检查评论官呼叫关键词，返回匹配的 binding
     */
    private function check_moderator($comment)
    {
        $moderator = $this->get_settings('moderator');
        if (empty($moderator['enabled'])) {
            return false;
        }

        $summon_map = xh_get_aiwords();
        if (empty($summon_map)) {
            return false;
        }

        $content = $comment->comment_content;

        foreach ($summon_map as $keyword => $user_id) {
            if (strpos($content, $keyword) !== false) {
                $user = get_userdata($user_id);
                return [
                    'keyword' => $keyword,
                    'user_id' => $user_id,
                    'user_name' => $user ? $user->display_name : ''
                ];
            }
        }

        if ($comment->comment_parent > 0) {
            $parent_comment = get_comment($comment->comment_parent);
            if ($parent_comment) {
                $parent_type = get_comment_meta($parent_comment->comment_ID, '_ai_interact_type', true);
                if ($parent_type === 'moderator' && $parent_comment->user_id) {
                    return [
                        'keyword' => '[follow-up]',
                        'user_id' => $parent_comment->user_id,
                        'user_name' => $parent_comment->comment_author
                    ];
                }
            }
        }

        return false;
    }

    /**
     * 通用排除检查
     */
    private function check_common_excludes($comment, $config)
    {
        $content = $comment->comment_content;

        if (!empty($config['exclude_admin']) && $comment->user_id) {
            $user = get_userdata($comment->user_id);
            if ($user && in_array('administrator', $user->roles)) {
                return false;
            }
        }

        if (!empty($config['exclude_author']) && $comment->user_id) {
            $post = get_post($comment->comment_post_ID);
            if ($post && $post->post_author == $comment->user_id) {
                return false;
            }
        }

        if (!empty($config['exclude_has_reply'])) {
            $replies = get_comments([
                'parent' => $comment->comment_ID,
                'count' => true
            ]);
            if ($replies > 0) {
                return false;
            }
        }

        if (!empty($config['exclude_short']) && mb_strlen($content) < 5) {
            return false;
        }

        return true;
    }



    /**
     * 检查频率限制（带缓存）
     */
    private function check_rate_limit($comment, $config)
    {
        $post_id = $comment->comment_post_ID;

        $max_per_post = $config['max_per_post'] ?? 10;
        $post_count = wp_cache_get($post_id, self::CACHE_GROUP);

        if ($post_count === false) {
            global $wpdb;
            $table = $wpdb->prefix . self::TABLE_NAME;
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $post_count = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$table} 
                 WHERE postid = %d AND type = 'reply' AND result = 'replied'",
                $post_id
            ));
            wp_cache_set($post_id, $post_count, self::CACHE_GROUP, DAY_IN_SECONDS);
        }

        if ($post_count >= $max_per_post) {
            return false;
        }

        $max_per_day = $config['max_per_day'] ?? 200;
        $today_date = current_time('Y-m-d');
        $day_count = wp_cache_get($today_date, self::CACHE_GROUP);

        if ($day_count === false) {
            global $wpdb;
            $table = $wpdb->prefix . self::TABLE_NAME;
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $day_count = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$table} 
                 WHERE type = 'reply' AND result = 'replied' 
                 AND createdat >= %s",
                $today_date . ' 00:00:00'
            ));
            wp_cache_set($today_date, $day_count, self::CACHE_GROUP, DAY_IN_SECONDS);
        }

        if ($day_count >= $max_per_day) {
            return false;
        }

        return true;
    }



    /**
     * 获取评论者身份类型
     */
    private function get_comment_user_type($comment)
    {
        $ai_type = get_comment_meta($comment->comment_ID, '_ai_interact_type', true);
        if ($ai_type === 'moderator') {
            return 'moderator';
        }
        if ($ai_type === 'reply' || $comment->comment_type === 'ai_comment') {
            return 'aiuser';
        }

        if ($comment->user_id) {
            $user = get_userdata($comment->user_id);
            if ($user) {
                $post = get_post($comment->comment_post_ID);
                if ($post && $post->post_author == $comment->user_id) {
                    return 'author';
                }

                if (in_array('administrator', $user->roles)) {
                    return 'admin';
                }
            }
        }

        return 'user';
    }

    /**
     * 构建多轮对话上下文
     */
    private function build_conversation_context($comment)
    {
        $context = [];
        $current = $comment;
        $max_depth = 10;
        $depth = 0;

        while ($current && $current->comment_parent > 0 && $depth < $max_depth) {
            $parent = get_comment($current->comment_parent);
            if (!$parent) break;

            $user_type = $this->get_comment_user_type($parent);
            array_unshift($context, [
                'user_type' => $user_type,  // 详细身份：user|author|admin|ai|moderator
                'author' => $parent->comment_author,
                'approved' => $parent->comment_approved === '1',
                'time' => $parent->comment_date,
                'content' => $parent->comment_content
            ]);

            $current = $parent;
            $depth++;
        }

        $context[] = [
            'user_type' => $this->get_comment_user_type($comment),
            'author' => $comment->comment_author,
            'approved' => $comment->comment_approved === '1',
            'time' => $comment->comment_date,
            'content' => $comment->comment_content,
            'agent' => $comment->comment_agent ?? ''
        ];

        return $context;
    }

    /**
     * 构建 API 请求的 args 参数
     */
    private function build_api_args($comment, $actions)
    {
        $args = [
            'comment_text' => $this->build_conversation_context($comment)
        ];

        if (!empty($actions['audit'])) {
            $args['audit'] = [
                'enabled' => true,
                'presets' => $actions['audit']['presets'] ?? [],
                'site_domain' => wp_parse_url(home_url(), PHP_URL_HOST)
            ];
        }

        if (!empty($actions['moderator'])) {
            $args['moderator'] = [
                'enabled' => true,
                'keyword' => $actions['moderator']['keyword'] ?? '',
                'user' => $actions['moderator']['user'] ?? null,
                'role_style' => $this->get_settings('moderator.role_style') ?: 'auto'
            ];
        }

        if (!empty($actions['autoreply'])) {
            $autoreply_args = [
                'enabled' => true,
                'type' => $actions['autoreply']['type'],
                'mode' => $actions['autoreply']['mode'] ?? 'ai',
                'enthusiasm' => $actions['autoreply']['enthusiasm'] ?? 'medium',
                'keyword' => $actions['autoreply']['keyword'] ?? ''
            ];

            if (strpos($actions['autoreply']['type'], 'smart_reply') !== false) {
                $autoreply_args['styles'] = $actions['autoreply']['styles'] ?? [];
                $autoreply_args['replier'] = $actions['autoreply']['replier'] ?? 'random_ai';
                $autoreply_args['addaiuser'] = $actions['autoreply']['addaiuser'] ?? 0;
            }

            $args['autoreply'] = $autoreply_args;
        }

        return $args;
    }

    /**
     * 处理审核结果
     */
    private function handle_audit_result($comment, $result, $actions)
    {
        $audit = $result['audit'] ?? null;
        if (!$audit) {
            return;
        }

        $comment_id = $comment->comment_ID;
        $level = $audit['level'] ?? 'pass';   // spam | pending | pass
        $reason = $audit['reason'] ?? '';

        $fail_action = $this->get_settings('audit.fail_action') ?: 'auto';

        if ($level !== 'pass') {
            if ($fail_action === 'auto') {
                $status = ($level === 'spam') ? 'spam' : 'hold';
            } else {
                $status = ($fail_action === 'spam') ? 'spam' : 'hold';
            }

            wp_set_comment_status($comment_id, $status);
            update_comment_meta($comment_id, '_ai_interact_type', 'rejected');
            update_comment_meta($comment_id, '_ai_interact_reason', $reason);

            $this->addlog([
                'commentid' => $comment_id,
                'postid' => $comment->comment_post_ID,
                'type' => 'audit',
                'result' => 'rejected',
                'reason' => $reason
            ]);
        } else {
            if ($comment->comment_approved == '0') {
                wp_set_comment_status($comment_id, 'approve');
            }
            update_comment_meta($comment_id, '_ai_interact_type', 'approved');

            $this->addlog([
                'commentid' => $comment_id,
                'postid' => $comment->comment_post_ID,
                'type' => 'audit',
                'result' => 'approved'
            ]);
        }

        $this->clear_cache('stats_audit');
    }

    /**
     * 获取匹配范围的用户
     */
    private function get_matched_scope_user($comment, $users)
    {
        if (empty($users)) {
            return null;
        }

        if (count($users) === 1) {
            $user_id = $users[0]['id'] ?? null;
            return $user_id ? get_userdata($user_id) : null;
        }

        shuffle($users);

        $global_user_id = null;
        $scoped_users = [];

        foreach ($users as $user_data) {
            $user_id = $user_data['id'] ?? null;
            if (!$user_id) {
                continue;
            }

            $scope = $user_data['scope'] ?? 'global';
            $is_global = ($scope === 'global' || empty($scope) || (is_array($scope) && empty($scope['post_types'])));

            if ($is_global) {
                if ($global_user_id === null) {
                    $global_user_id = $user_id;
                }
            } else {
                $scoped_users[] = $user_data;
            }
        }

        if (empty($scoped_users)) {
            return $global_user_id ? get_userdata($global_user_id) : null;
        }

        $post = get_post($comment->comment_post_ID);
        if (!$post) {
            return $global_user_id ? get_userdata($global_user_id) : null;
        }

        $post_type = $post->post_type;
        $post_categories = null;
        $matched_specific = [];

        foreach ($scoped_users as $user_data) {
            $scope = $user_data['scope'];
            $user_id = $user_data['id'];

            if (!in_array($post_type, $scope['post_types'])) {
                continue;
            }

            $scope_cats = $scope['categories'][$post_type] ?? [];
            if (!empty($scope_cats)) {
                if ($post_categories === null) {
                    $post_categories = wp_get_post_categories($comment->comment_post_ID, ['fields' => 'ids']);
                }
                if (empty(array_intersect($post_categories, $scope_cats))) {
                    continue;
                }
            }

            $matched_specific[] = $user_id;
        }

        if (!empty($matched_specific)) {
            return get_userdata($matched_specific[array_rand($matched_specific)]);
        }

        return $global_user_id ? get_userdata($global_user_id) : null;
    }



    /**
     * 处理评论官结果
     */
    private function handle_moderator_result($comment, $result, $actions)
    {
        $logdata = [
            'commentid' => $comment->comment_ID,
            'postid' => $comment->comment_post_ID,
            'type' => 'moderator',
            'result' => 'error'
        ];

        $moderator = $result['moderator'] ?? null;
        if (!$moderator || empty($moderator['content'])) {
            $logdata['reason'] = esc_html__('No reply from API', 'xhtheme-ai-toolbox');
            $this->addlog($logdata);
            return;
        }

        $reply_content = $moderator['content'];

        $replier = $actions['moderator']['user_obj'] ?? null;
        if (!$replier) {
            $logdata['reason'] = esc_html__('Cannot match moderator', 'xhtheme-ai-toolbox');
            $this->addlog($logdata);
            return;
        }

        $reply_id = wp_insert_comment([
            'comment_post_ID' => $comment->comment_post_ID,
            'comment_author' => $replier->display_name,
            'comment_author_email' => $replier->user_email,
            'comment_content' => $reply_content,
            'comment_type' => 'comment',
            'comment_parent' => $comment->comment_ID,
            'user_id' => $replier->ID,
            'comment_approved' => 1,
            'comment_author_IP' => $this->getUserIP($replier->ID),
            'comment_agent' => $this->getUserAgent($replier->ID),
            'comment_meta' => [
                '_ai_interact_type' => 'moderator'
            ]
        ]);

        if (!$reply_id) {
            $logdata['reason'] = esc_html__('Comment insert failed', 'xhtheme-ai-toolbox');
            $this->addlog($logdata);
            return;
        }

        $logdata['result'] = 'replied';
        $logdata['keyword'] = $actions['moderator']['keyword'] ?? null;
        $logdata['replier'] = $replier->ID;
        $logdata['replyid'] = $reply_id;
        $this->addlog($logdata);

        $this->clear_cache('stats_reply');
    }

    /**
     * 处理智能回评结果
     */
    private function handle_autoreply_result($comment, $result, $actions)
    {
        $autoreply = $result['autoreply'] ?? null;
        $reply_config = $this->get_settings('auto_reply');
        $reply_type = 'reply';
        $logdata = [
            'commentid' => $comment->comment_ID,
            'postid' => $comment->comment_post_ID,
            'type' => 'reply',
            'result' => 'error'
        ];

        if (!$autoreply || empty($autoreply['need_reply'])) {
            $skip_reason = $autoreply['skip_reason'] ?? esc_html__('AI: No reply needed', 'xhtheme-ai-toolbox');
            $logdata['result'] = 'skipped';
            $logdata['reason'] = $skip_reason;
            $this->addlog($logdata);
            return;
        }

        $reply_content = $autoreply['content'] ?? '';
        if (empty($reply_content)) {
            $logdata['reason'] = esc_html__('Model returned no reply!', 'xhtheme-ai-toolbox');
            $this->addlog($logdata);
            return;
        }

        $replier = null;
        $parent_replier = null;

        if ($comment->comment_parent > 0) {
            $parent_comment = get_comment($comment->comment_parent);

            if ($parent_comment) {
                $parent_type = get_comment_meta($parent_comment->comment_ID, '_ai_interact_type', true);
                if ($parent_comment->comment_type == 'ai_comment' || $parent_type == 'reply') {
                    if ($parent_comment->user_id > 0) {
                        $replier = get_userdata($parent_comment->user_id);
                    } else {
                        $parent_replier = $parent_comment;
                    }
                }
            }
        }

        if (!$replier && !$parent_replier) {
            $reply_type = $autoreply['reply_type'] ?? 'smart_reply';
            if ($reply_type == 'author_reply') {
                $post = get_post($comment->comment_post_ID);
                if ($post && $post->post_author) {
                    $replier = get_userdata($post->post_author);
                }
                if (!$replier) {
                    $logdata['reason'] = __('Cannot get author info', 'xhtheme-ai-toolbox');
                    $this->addlog($logdata);
                    return;
                }
            } else {
                $replier_mode = $reply_config['smart_reply_mode'] ?? 'random_ai';
                if ($replier_mode === 'specified' && !empty($reply_config['smart_reply_users'])) {
                    $replier = $this->get_matched_scope_user($comment, $reply_config['smart_reply_users']);
                } else {
                    $ai_user = $autoreply['ai_user'] ?? null;
                    if ($ai_user && !empty($ai_user['name'])) {
                        $replier = $this->create_ai_user($ai_user);
                        if ($replier && !empty($ai_user['ip'])) {
                            $replier->_apiip = $ai_user['ip'];
                        }
                    }
                    if (!$replier) {
                        $replier = $this->get_random_aiuser($comment->comment_post_ID);
                    }
                }

                if (!$replier) {
                    $logdata['reason'] = __('No valid replier, check config!', 'xhtheme-ai-toolbox');
                    $this->addlog($logdata);
                    return;
                }
            }
        }

        if (!$replier && !$parent_replier) {
            $logdata['reason'] = __('No valid replier info', 'xhtheme-ai-toolbox');
            $this->addlog($logdata);
            return;
        }

        $delay_min = (int) ($reply_config['delay_min'] ?? 5);
        $delay_max = (int) ($reply_config['delay_max'] ?? 30);
        $delay = ($delay_min === $delay_max) ? $delay_min : wp_rand($delay_min, $delay_max);
        $scheduled_time = time() + ($delay * 60);

        $comment_data = [
            'comment_post_ID' => $comment->comment_post_ID,
            'comment_content' => $reply_content,
            'comment_type' => 'comment',
            'comment_parent' => $comment->comment_ID,
            'comment_approved' => ($delay > 0) ? 0 : 1,
            'comment_date' => wp_date('Y-m-d H:i:s', $scheduled_time),
            'comment_date_gmt' => gmdate('Y-m-d H:i:s', $scheduled_time),
            'comment_meta' => [
                '_ai_interact_type' => 'reply'
            ]
        ];

        if ($replier) {
            $comment_data['comment_author'] = $replier->display_name;
            $comment_data['comment_author_email'] = $replier->user_email;
            $comment_data['user_id'] = $replier->ID;
            $comment_data['comment_author_IP'] = $replier->_apiip ?? $this->getUserIP($replier->ID);
            $comment_data['comment_agent'] = $this->getUserAgent($replier->ID);
        } else {
            $comment_data['comment_author'] = $parent_replier->comment_author;
            $comment_data['comment_author_email'] = $parent_replier->comment_author_email;
            $comment_data['user_id'] = 0;
            $comment_data['comment_author_IP'] = $parent_replier->comment_author_IP ?: $this->getRandomIP();
            $comment_data['comment_agent'] = $parent_replier->comment_agent ?: $this->getAgents();
            if ($parent_replier->comment_type == 'ai_comment') {
                $avatar = get_comment_meta($parent_replier->comment_ID, '_ai_avatar', true);
                if ($avatar) {
                    $comment_data['comment_meta']['_ai_avatar'] = $avatar;
                }
            }
        }

        $reply_id = wp_insert_comment($comment_data);

        if (!$reply_id) {
            $logdata['reason'] = __('Comment insert failed', 'xhtheme-ai-toolbox');
            $this->addlog($logdata);
            return;
        }

        $logdata['type'] = $reply_type;
        $logdata['result'] = 'replied';
        $logdata['replier'] = $replier ? $replier->ID : 0;
        $logdata['replyid'] = $reply_id;
        $this->addlog($logdata);

        $this->clear_cache(null, $comment->comment_post_ID);
        $this->clear_cache('stats_reply');
    }

    /**
     * 构建自动回复 action
     */
    private function build_autoreply_action($comment)
    {
        $config = $this->get_settings('auto_reply');

        $author_reply_enabled = !empty($config['author_reply']);
        $smart_reply_enabled = !empty($config['smart_reply']);

        if (!$author_reply_enabled && !$smart_reply_enabled) {
            return null;
        }

        $trigger_mode = $config['trigger_mode'] ?? 'ai';
        $matched_keyword = '';
        $addaiuser = true;
        if ($trigger_mode === 'keywords') {
            $keywords = $config['keywords'] ?? [];
            if (empty($keywords)) {
                return null;
            }
            $content = $comment->comment_content;
            foreach ($keywords as $keyword) {
                if (strpos($content, $keyword) !== false) {
                    $matched_keyword = $keyword;
                    break;
                }
            }
            if (empty($matched_keyword)) {
                return null;
            }
        }

        if (!$this->check_common_excludes($comment, $config)) {
            return null;
        }

        if ($comment->comment_parent > 0) {
            $parent_comment = get_comment($comment->comment_parent);
            if (!$parent_comment) {
                return null;
            }
            $parent_ai_type = get_comment_meta($parent_comment->comment_ID, '_ai_interact_type', true);
            if ($parent_comment->comment_type !== 'ai_comment' && !$parent_ai_type) {
                return null;
            }
            $addaiuser = false;
        }

        $post = get_post($comment->comment_post_ID);

        if ($author_reply_enabled) {
            $mode = $config['author_reply_mode'] ?? 'all';
            if ($mode === 'specified') {
                $author_users = $config['author_reply_users'] ?? [];
                if (!empty($author_users) && $post) {
                    $author_ids = array_column($author_users, 'id');
                    if (!in_array((int)$post->post_author, $author_ids, true)) {
                        $author_reply_enabled = false;
                    }
                }
            }
        }

        if ($smart_reply_enabled) {
            $replier_mode = $config['smart_reply_mode'] ?? 'random_ai';
            if ($replier_mode === 'specified' && empty($config['smart_reply_users'])) {
                $smart_reply_enabled = false;
            }
        }

        if (!$author_reply_enabled && !$smart_reply_enabled) {
            return null;
        }

        $autoreply_types = [];
        $autoreply_data = [
            'mode' => $trigger_mode,
            'enthusiasm' => $config['enthusiasm'] ?? 'medium',
            'keyword' => $matched_keyword
        ];

        if ($author_reply_enabled) {
            $autoreply_types[] = 'author_reply';
        }

        if ($smart_reply_enabled) {
            $replier_mode = $config['smart_reply_mode'] ?? 'random_ai';
            $autoreply_types[] = 'smart_reply';
            $autoreply_data['styles'] = $config['smart_reply_styles'] ?? [];
            $autoreply_data['replier'] = $replier_mode;
            if ($replier_mode === 'random_ai' && $addaiuser) {
                $ai_user_limit = (int) xh_option('aiUserLimit', 200);
                $current_count = $this->get_ai_user_count();
                $autoreply_data['addaiuser'] = ($current_count < $ai_user_limit) ? 1 : 0;
            }
        }
        if (!empty($config['rate_limit_enabled'])) {
            if (!$this->check_rate_limit($comment, $config)) {
                return null;
            }
        }

        $autoreply_data['type'] = implode('|', $autoreply_types);
        return $autoreply_data;
    }

    /**
     * 处理队列任务
     */
    public function process_interact_task($cronArr, $itemType, $comment_id)
    {
        $comment = get_comment($comment_id);
        if (!$comment) {
            $cronArr['status'] = 'success';
            delete_comment_meta($comment_id, '_ai_task_status');
            return $cronArr;
        }

        $post = get_post($comment->comment_post_ID);
        if (!$post || $post->post_status === 'trash') {
            $cronArr['status'] = 'success';
            delete_comment_meta($comment_id, '_ai_task_status');
            return $cronArr;
        }

        if (!$this->get_settings('enabled')) {
            $cronArr['status'] = 'success';
            delete_comment_meta($comment_id, '_ai_task_status');
            return $cronArr;
        }

        $interact_type = get_comment_meta($comment_id, '_ai_interact_type', true);
        $is_randcomment = ($interact_type === 'randcomment');
        $randcomment_should_process = false;
        $randcomment_probability_hit = false;
        if ($is_randcomment) {
            $rand_settings = $this->get_settings('rand_comment');

            if (!empty($rand_settings['trigger_smart_reply'])) {
                $probability = $rand_settings['smart_reply_probability'] ?? 50;
                $randNumber = wp_rand(1, 100);
                if ($randNumber <= $probability) {
                    $randcomment_probability_hit = true;
                    $randcomment_should_process = true;
                }
            }

            if (!empty($rand_settings['trigger_moderator'])) {
                $randcomment_should_process = true;
            }

            if (!$randcomment_should_process) {
                $cronArr['status'] = 'success';
                delete_comment_meta($comment_id, '_ai_task_status');
                return $cronArr;
            }
        }

        $actions = [];

        if (!$is_randcomment && $this->check_audit($comment)) {
            $actions['audit'] = [
                'presets' => $this->get_settings('audit.presets') ?: [],
            ];
        }

        $moderator_binding = $this->check_moderator($comment);
        if ($moderator_binding !== false && !empty($moderator_binding['user_id'])) {
            $moderator_user = get_userdata($moderator_binding['user_id']);
            if ($moderator_user) {
                $actions['moderator'] = [
                    'keyword' => $moderator_binding['keyword'] ?? '',
                    'user' => $moderator_user->display_name,
                    'user_obj' => $moderator_user
                ];
            }
        }

        if (!isset($actions['moderator']) && (!$is_randcomment || $randcomment_probability_hit)) {
            $autoreply_action = $this->build_autoreply_action($comment);
            if ($autoreply_action) {
                $actions['autoreply'] = $autoreply_action;
            }
        }

        if (empty($actions)) {
            $cronArr['status'] = 'success';
            delete_comment_meta($comment_id, '_ai_task_status');
            return $cronArr;
        }

        $args = $this->build_api_args($comment, $actions);
        $result = xh_api_request('comment-interact', ['args' => $args], get_post($comment->comment_post_ID));

        if (is_wp_error($result)) {
            $cronArr = xh_api_handle_error($result, $cronArr, '[XHInteract]');
            if (isset($cronArr['status']) && $cronArr['status'] === 'error') {
                delete_comment_meta($comment_id, '_ai_task_status');
            }
            return $cronArr;
        }

        $audit_passed = true;
        /**
         * 用户邮件发送
         */
        $email_data = ['comment' => $comment];

        if (!empty($actions['audit'])) {
            $audit_level = $result['audit']['level'] ?? 'pass';
            $audit_passed = ($audit_level === 'pass');
            $this->handle_audit_result($comment, $result, $actions);

            $email_data['audit_passed'] = $audit_passed;
            if (!$audit_passed) {
                $email_data['audit_reason'] = $result['audit']['reason'] ?? '';
            }
        }

        if (!$audit_passed) {
            $this->send_combined_notify_email($email_data);
            $cronArr['status'] = 'success';
            delete_comment_meta($comment_id, '_ai_task_status');
            return $cronArr;
        }

        if (!empty($actions['moderator'])) {
            $this->handle_moderator_result($comment, $result, $actions);
            $email_data['reply_type'] = 'moderator';
            $email_data['replier_name'] = $actions['moderator']['user'] ?? '';
            $email_data['reply_content'] = $result['moderator']['content'] ?? '';
        }

        if (!empty($actions['autoreply'])) {
            $this->handle_autoreply_result($comment, $result, $actions);
            $autoreply = $result['autoreply'] ?? [];
            $email_data['reply_type'] = $autoreply['reply_type'] ?? 'smart_reply';
            $email_data['replier_name'] = $autoreply['replier_name'] ?? '';
            $email_data['reply_content'] = $autoreply['content'] ?? '';
        }

        $this->send_combined_notify_email($email_data);

        $cronArr['status'] = 'success';
        delete_comment_meta($comment_id, '_ai_task_status');
        return $cronArr;
    }

    /**
     * 添加评论列表列
     */
    public function add_comment_columns($columns)
    {
        if (!$this->get_settings('enabled')) {
            return $columns;
        }
        $columns['ai_interact'] = __('AI Label', 'xhtheme-ai-toolbox');
        return $columns;
    }

    /**
     * 渲染评论列表列
     */
    public function render_comment_column($column, $comment_id)
    {
        if ($column !== 'ai_interact') {
            return;
        }

        $type = get_comment_meta($comment_id, '_ai_interact_type', true);
        if (!$type) {
            echo '-';
            return;
        }

        $icons = [
            'approved' => esc_html__('AI Approved', 'xhtheme-ai-toolbox'),
            'rejected' => esc_html__('AI Rejected', 'xhtheme-ai-toolbox'),
            'reply' => esc_html__('AI Reply', 'xhtheme-ai-toolbox'),
            'moderator' => esc_html__('Moderator', 'xhtheme-ai-toolbox'),
            'randcomment' => esc_html__('Random Comment', 'xhtheme-ai-toolbox')
        ];

        $label = isset($icons[$type]) ? $icons[$type] : $type;
        $reason = get_comment_meta($comment_id, '_ai_interact_reason', true);
        echo esc_html($label);
        if ($reason) {
            echo '<br><small>(' . esc_html($reason) . ')</small>';
        }
    }

    /**
     * 记录 AI 处理日志
     */
    public function addlog($data)
    {
        global $wpdb;
        $table_name = $wpdb->prefix . self::TABLE_NAME;

        $result = $wpdb->insert($table_name, [
            'commentid' => $data['commentid'],
            'postid' => $data['postid'],
            'type' => $data['type'],
            'result' => $data['result'],
            'keyword' => $data['keyword'] ?? null,
            'replier' => $data['replier'] ?? null,
            'replyid' => $data['replyid'] ?? null,
            'reason' => $data['reason'] ?? null,
            'createdat' => current_time('mysql'),
        ]);

        return $result;
    }

    /**
     * 发送合并邮件通知（每条评论只发一封）
     */
    private function send_combined_notify_email($data)
    {
        $config = $this->get_settings('email_notify', []);
        if (empty($config['enabled'])) {
            return;
        }

        $comment = $data['comment'] ?? null;
        if (!$comment) {
            return;
        }

        $audit_passed = $data['audit_passed'] ?? null;
        $has_reply = !empty($data['reply_type']);

        $notify_rejected = ($audit_passed === false) && !empty($config['notify_audit_rejected']);
        $notify_approved = ($audit_passed === true) && !empty($config['notify_audit_approved']);
        $notify_reply = $has_reply && !empty($config['notify_reply_sent']);

        if (!$notify_rejected && !$notify_approved && !$notify_reply) {
            return;
        }

        $recipient = ($config['recipient'] === 'custom' && !empty($config['custom_email']))
            ? sanitize_email($config['custom_email'])
            : get_option('admin_email');

        if (!is_email($recipient)) {
            return;
        }

        $site_name = get_bloginfo('name');
        $post = get_post($comment->comment_post_ID);
        $sections = [];

        if ($notify_rejected) {
            /* translators: %s: site name. */
            $subject = sprintf(__('[%s] AI blocked a comment', 'xhtheme-ai-toolbox'), $site_name);
            $sections[] = sprintf(
                /* translators: %s: reason why the comment failed AI review. */
                __("❌ AI review result: failed\nReason: %s\nAction: marked as pending review or spam", 'xhtheme-ai-toolbox'),
                $data['audit_reason'] ?? __('Violation content', 'xhtheme-ai-toolbox')
            );
        } else {
            /* translators: %s: site name. */
            $subject = sprintf(__('[%s] Comment processed by AI', 'xhtheme-ai-toolbox'), $site_name);

            if ($notify_approved) {
                $sections[] = __("✅ AI review result: passed\nComment has been published automatically", 'xhtheme-ai-toolbox');
            }

            if ($notify_reply) {
                $reply_type_map = [
                    'moderator' => __('AI Moderator', 'xhtheme-ai-toolbox'),
                    'author_reply' => __('Author Reply', 'xhtheme-ai-toolbox'),
                    'smart_reply' => __('Smart Reply', 'xhtheme-ai-toolbox')
                ];
                $reply_type_label = $reply_type_map[$data['reply_type']] ?? __('Smart Reply', 'xhtheme-ai-toolbox');
                $sections[] = sprintf(
                    /* translators: 1: reply type label, 2: reply account name, 3: generated reply content. */
                    __("💬 AI has replied automatically\nReply type: %1\$s\nReply account: %2\$s\nReply content: %3\$s", 'xhtheme-ai-toolbox'),
                    $reply_type_label,
                    $data['replier_name'] ?? __('Unknown', 'xhtheme-ai-toolbox'),
                    mb_substr($data['reply_content'] ?? '', 0, 200)
                );
            }
        }

        $action_detail = implode("\n\n", $sections);

        $message = sprintf(
            /* translators: 1: commenter name, 2: post title, 3: comment content excerpt, 4: comment date, 5: AI action details, 6: comment URL, 7: admin comments URL, 8: site name. */
            __("📌 Comment processing notification\n\nOriginal comment:\n━━━━━━━━━━━━━━━━━━━━━━━━━━\nCommenter: %1\$s\nPost: %2\$s\nContent: %3\$s\nTime: %4\$s\n━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n%5\$s\n\n---\n🔗 View comment: %6\$s\n⚙️ Admin panel: %7\$s\n\nThis email was sent automatically by %8\$s Smart Comment Assistant.", 'xhtheme-ai-toolbox'),
            $comment->comment_author,
            $post ? $post->post_title : __('Unknown post', 'xhtheme-ai-toolbox'),
            mb_substr($comment->comment_content, 0, 300),
            $comment->comment_date,
            $action_detail,
            get_comment_link($comment),
            admin_url('edit-comments.php'),
            $site_name
        );

        $sent = wp_mail($recipient, $subject, $message);
        if (!$sent) {
            error_log('[XHInteract] 邮件发送失败 - 收件人: ' . $recipient . ', 评论ID: ' . $comment->comment_ID);
        }
    }

    /**
     * 获取统计数据（最近30天）
     */
    public function get_stats()
    {
        global $wpdb;
        $table_name = $wpdb->prefix . self::TABLE_NAME;

        $stats = [
            'audit_approved' => 0,
            'audit_rejected' => 0,
            'reply' => 0,
            'moderator' => 0
        ];

        $audit_cache_key = 'stats_audit';
        $audit_stats = wp_cache_get($audit_cache_key, self::CACHE_GROUP);

        if ($audit_stats === false) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $month_audit = $wpdb->get_row(
                "SELECT SUM(CASE WHEN result = 'approved' THEN 1 ELSE 0 END) as approved,
                        SUM(CASE WHEN result = 'rejected' THEN 1 ELSE 0 END) as rejected
                 FROM $table_name 
                 WHERE type = 'audit' AND createdat >= DATE_SUB(NOW(), INTERVAL 30 DAY)"
            );

            $audit_stats = [
                'approved' => $month_audit ? (int) $month_audit->approved : 0,
                'rejected' => $month_audit ? (int) $month_audit->rejected : 0,
            ];

            wp_cache_set($audit_cache_key, $audit_stats, self::CACHE_GROUP, HOUR_IN_SECONDS);
        }

        $stats['audit_approved'] = $audit_stats['approved'];
        $stats['audit_rejected'] = $audit_stats['rejected'];

        $reply_cache_key = 'stats_reply';
        $reply_stats = wp_cache_get($reply_cache_key, self::CACHE_GROUP);

        if ($reply_stats === false) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $month_reply = $wpdb->get_row(
                "SELECT SUM(CASE WHEN type IN ('reply', 'smart_reply','author_reply') THEN 1 ELSE 0 END) as reply_count,
                        SUM(CASE WHEN type = 'moderator' THEN 1 ELSE 0 END) as moderator_count
                 FROM $table_name 
                 WHERE type IN ('reply', 'smart_reply', 'moderator','author_reply') AND result = 'replied' AND createdat >= DATE_SUB(NOW(), INTERVAL 30 DAY)"
            );

            $reply_stats = [
                'reply' => $month_reply ? (int) $month_reply->reply_count : 0,
                'moderator' => $month_reply ? (int) $month_reply->moderator_count : 0,
            ];

            wp_cache_set($reply_cache_key, $reply_stats, self::CACHE_GROUP, HOUR_IN_SECONDS);
        }

        $stats['reply'] = $reply_stats['reply'];
        $stats['moderator'] = $reply_stats['moderator'];

        $randcomment_cache_key = 'stats_randcomment';
        $randcomment_count = wp_cache_get($randcomment_cache_key, self::CACHE_GROUP);

        if ($randcomment_count === false) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $randcomment_count = (int) $wpdb->get_var(
                "SELECT COUNT(*) FROM $table_name 
                 WHERE type = 'randcomment' AND result = 'posted' 
                 AND createdat >= DATE_SUB(NOW(), INTERVAL 30 DAY)"
            );

            wp_cache_set($randcomment_cache_key, $randcomment_count, self::CACHE_GROUP, HOUR_IN_SECONDS);
        }

        $stats['randcomment'] = $randcomment_count;

        return $stats;
    }



    /**
     * AJAX: 获取日志
     */
    public function ajax_get_logs()
    {
        $this->verify_ajax_admin_request();

        global $wpdb;
        $table_name = $wpdb->prefix . self::TABLE_NAME;

        $page = isset($_GET['page']) ? absint(wp_unslash($_GET['page'])) : 1;
        $per_page = isset($_GET['per_page']) ? absint(wp_unslash($_GET['per_page'])) : 20;
        $action_type = isset($_GET['action_type']) ? sanitize_text_field(wp_unslash($_GET['action_type'])) : '';

        $offset = ($page - 1) * $per_page;
        $where = '1=1';
        $params = [];

        if ($action_type) {
            $types = array_map('trim', explode(',', $action_type));
            if (count($types) === 1) {
                $where .= ' AND type = %s';
                $params[] = $types[0];
            } else {
                $placeholders = implode(',', array_fill(0, count($types), '%s'));
                $where .= " AND type IN ($placeholders)";
                $params = array_merge($params, $types);
            }
        }
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $total = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM $table_name WHERE $where",
            ...$params
        ));

        $params[] = $per_page;
        $params[] = $offset;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $logs = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table_name WHERE $where ORDER BY createdat DESC, id DESC LIMIT %d OFFSET %d",
            ...$params
        ));

        foreach ($logs as &$log) {
            $comment = get_comment($log->commentid);
            $log->comment_content = $comment ? $this->highlight_comment_summon_words($comment->comment_content) : '';
            $log->comment_author = $comment ? $comment->comment_author : '';

            if ($comment) {
                $log->comment_view_link = get_comment_link($comment);
                $log->comment_edit_link = admin_url(sprintf(
                    'comment.php?action=editcomment&c=%d&_wpnonce=%s',
                    $log->commentid,
                    wp_create_nonce('edit-comment_' . $log->commentid)
                ));
            } else {
                $log->comment_view_link = '';
                $log->comment_edit_link = '';
            }

            $post = get_post($log->postid);
            $log->post_title = $post ? $post->post_title : '';

            if ($log->replyid) {
                $reply_comment = get_comment($log->replyid);
                $log->reply_content = $reply_comment ? $this->highlight_comment_summon_words($reply_comment->comment_content) : '';

                if ($reply_comment) {
                    $log->reply_view_link = get_comment_link($reply_comment);
                    $log->reply_edit_link = admin_url(sprintf(
                        'comment.php?action=editcomment&c=%d&_wpnonce=%s',
                        $log->replyid,
                        wp_create_nonce('edit-comment_' . $log->replyid)
                    ));
                } else {
                    $log->reply_view_link = '';
                    $log->reply_edit_link = '';
                }

                if ($log->replier) {
                    $replier = get_userdata($log->replier);
                    $log->replier_name = $replier ? $replier->display_name : '';
                } else {
                    $log->replier_name = $reply_comment ? $reply_comment->comment_author : '';
                }
            } elseif ($log->replier) {
                $replier = get_userdata($log->replier);
                $log->replier_name = $replier ? $replier->display_name : '';
            }

            if ($log->type === 'randcomment') {
                $log->reply_content = $log->comment_content;
                $log->comment_content = '';
                $log->replier_name = $log->comment_author;
                $log->comment_author = '';

                $log->reply_view_link = $log->comment_view_link;
                $log->reply_edit_link = $log->comment_edit_link;

                $log->comment_view_link = '';
                $log->comment_edit_link = '';
            }
        }

        wp_send_json_success([
            'logs' => $logs,
            'total' => (int) $total,
            'page' => $page,
            'per_page' => $per_page,
            'total_pages' => ceil($total / $per_page)
        ]);
    }

    /**
     * AJAX: 获取统计
     */
    public function ajax_get_stats()
    {
        $this->verify_ajax_admin_request();

        wp_send_json_success($this->get_stats());
    }

    /**
     * AJAX: 批量操作
     */
    public function ajax_batch_action()
    {
        $this->verify_ajax_admin_request();

        $action = isset($_POST['batch_action']) ? sanitize_text_field(wp_unslash($_POST['batch_action'])) : '';
        $ids = isset($_POST['ids']) ? array_map('absint', (array) wp_unslash($_POST['ids'])) : [];

        if (empty($ids)) {
            wp_send_json_error(['message' => 'No items selected']);
        }

        $count = 0;
        foreach ($ids as $log_id) {
            global $wpdb;
            $table_name = $wpdb->prefix . self::TABLE_NAME;

            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $log = $wpdb->get_row($wpdb->prepare(
                "SELECT * FROM $table_name WHERE id = %d",
                $log_id
            ));

            if (!$log) {
                continue;
            }

            switch ($action) {
                case 'approve':
                    wp_set_comment_status($log->commentid, 'approve');
                    $count++;
                    break;
                case 'reject':
                    wp_set_comment_status($log->commentid, 'spam');
                    $count++;
                    break;
            }
        }

        wp_send_json_success(['message' => sprintf('%d items processed', $count)]);
    }

    /**
     * AJAX: 导出日志
     */
    public function ajax_export_logs()
    {
        check_ajax_referer('xhinteract_nonce', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_die('Permission denied');
        }

        global $wpdb;
        $table_name = $wpdb->prefix . self::TABLE_NAME;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $logs = $wpdb->get_results("SELECT * FROM $table_name ORDER BY createdat DESC LIMIT 1000");

        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename=ai_interact_logs_' . wp_date('Y-m-d') . '.csv');

        $output = fopen('php://output', 'w');
        fprintf($output, chr(0xEF) . chr(0xBB) . chr(0xBF));

        // 国际化的表头
        fputcsv($output, [
            __('No.', 'xhtheme-ai-toolbox'),
            __('Time', 'xhtheme-ai-toolbox'),
            __('Post Title', 'xhtheme-ai-toolbox'),
            __('Type', 'xhtheme-ai-toolbox'),
            __('Result', 'xhtheme-ai-toolbox'),
            __('Commenter', 'xhtheme-ai-toolbox'),
            __('Comment Content', 'xhtheme-ai-toolbox'),
            __('Replier', 'xhtheme-ai-toolbox'),
            __('Reply Content', 'xhtheme-ai-toolbox'),
            __('Summon Word', 'xhtheme-ai-toolbox'),
            __('Reason/Note', 'xhtheme-ai-toolbox')
        ]);

        // 类型映射
        $type_map = [
            'audit' => __('Audit', 'xhtheme-ai-toolbox'),
            'reply' => __('Smart Reply', 'xhtheme-ai-toolbox'),
            'smart_reply' => __('Smart Reply', 'xhtheme-ai-toolbox'),
            'author_reply' => __('Author Reply', 'xhtheme-ai-toolbox'),
            'moderator' => __('Moderator', 'xhtheme-ai-toolbox'),
            'randcomment' => __('Rand Comment', 'xhtheme-ai-toolbox')
        ];

        // 结果映射
        $result_map = [
            'approved' => __('Approved', 'xhtheme-ai-toolbox'),
            'rejected' => __('Rejected', 'xhtheme-ai-toolbox'),
            'pending' => __('Pending', 'xhtheme-ai-toolbox'),
            'replied' => __('Replied', 'xhtheme-ai-toolbox'),
            'skipped' => __('Skipped', 'xhtheme-ai-toolbox'),
            'posted' => __('Posted', 'xhtheme-ai-toolbox'),
            'error' => __('Error', 'xhtheme-ai-toolbox')
        ];

        foreach ($logs as $log) {
            $post = get_post($log->postid);
            $post_title = $post ? $post->post_title : __('(Post deleted)', 'xhtheme-ai-toolbox');

            $comment = get_comment($log->commentid);
            $comment_author = '';
            $comment_content = '';
            $reply_content = '';
            $replier_name = '';

            if ($comment) {
                $comment_author = $comment->comment_author;
                $comment_content = wp_strip_all_tags($comment->comment_content);
            } elseif ($log->commentid > 0) {
                $comment_author = __('(Comment deleted)', 'xhtheme-ai-toolbox');
            }

            if ($log->replyid) {
                $reply_comment = get_comment($log->replyid);
                if ($reply_comment) {
                    $reply_content = wp_strip_all_tags($reply_comment->comment_content);
                    $replier_name = $reply_comment->comment_author;
                }
            }

            if ($log->replier && empty($replier_name)) {
                $replier = get_userdata($log->replier);
                $replier_name = $replier ? $replier->display_name : '';
            }

            if ($log->type === 'randcomment') {
                $reply_content = $comment_content;
                $replier_name = $comment_author;
                $comment_content = '';
                $comment_author = '';
            }

            $type_label = $type_map[$log->type] ?? $log->type;
            $result_label = $result_map[$log->result] ?? $log->result;

            fputcsv($output, [
                $log->id,
                $log->createdat,
                $post_title,
                $type_label,
                $result_label,
                $comment_author,
                $comment_content,
                $replier_name,
                $reply_content,
                $log->keyword ?: '',
                $log->reason ?: ''
            ]);
        }

        fclose($output);
        exit;
    }

    /**
     * AJAX: 清理指定时间之前的日志
     */
    public function ajax_cleanup_logs()
    {
        $this->verify_ajax_admin_request();

        $period = isset($_POST['period']) ? sanitize_text_field(wp_unslash($_POST['period'])) : '';

        $valid_periods = ['1month', '6months', '1year'];
        if (!in_array($period, $valid_periods)) {
            wp_send_json_error(['message' => 'Invalid period']);
        }

        $date_map = [
            '1month' => '-1 month',
            '6months' => '-6 months',
            '1year' => '-1 year'
        ];

        $before_date = wp_date('Y-m-d H:i:s', strtotime($date_map[$period]));

        global $wpdb;
        $table_name = $wpdb->prefix . self::TABLE_NAME;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $deleted = $wpdb->query($wpdb->prepare(
            "DELETE FROM $table_name WHERE createdat < %s",
            $before_date
        ));

        wp_send_json_success([
            'deleted' => $deleted,
            /* translators: %d: number of deleted comment assistant logs. */
            'message' => sprintf(__('Cleared %d logs', 'xhtheme-ai-toolbox'), $deleted)
        ]);
    }

    /**
     * 随手一评功能模块
     */
    public function process_randcomment()
    {
        $settings = $this->get_settings('rand_comment');
        if (empty($settings['enabled'])) {
            return;
        }

        $interval = ($settings['interval_minutes'] ?? 5) * 60;
        if (get_transient('xhtheme_randcomment_cooldown')) {
            return;
        }

        if ($this->is_in_blackout_period(
            (int) current_time('G'),
            $settings['blackout_start'] ?? 0,
            $settings['blackout_end'] ?? 6
        )) {
            return;
        }

        if (!$this->check_randcomment_daily_limit($settings)) {
            return;
        }

        $post = $this->find_suitable_post_for_randcomment($settings);
        if (!$post) {
            return;
        }

        $exist_comments = $this->get_post_comments_for_api($post->ID);
        $ai_user_limit = (int) xh_option('aiUserLimit', 200);
        $need_ai_user = $settings['identity_mode'] == 'visitor' || ($this->get_ai_user_count() < $ai_user_limit);

        $api_args = [
            'exist' => $exist_comments,
            'addaiuser' => (int)$need_ai_user
        ];

        if (!empty($settings['trigger_moderator']) && $this->get_settings('moderator.enabled')) {
            $probability = $settings['moderator_probability'] ?? 5;
            $max_daily = $settings['moderator_max_daily'] ?? 10;
            $max_per_post = $settings['moderator_max_per_post'] ?? 2;
            if (wp_rand(1, 100) <= $probability) {
                $daily_count = $this->get_moderator_daily_count();
                if ($daily_count < $max_daily) {
                    $post_count = $this->get_moderator_postcount($post->ID);
                    if ($post_count < $max_per_post) {
                        $bindings = $this->get_settings('moderator.bindings') ?? [];
                        if (!empty($bindings)) {
                            $random_binding = $bindings[array_rand($bindings)];
                            $keywords = $random_binding['keywords'] ?? [];
                            if (!empty($keywords)) {
                                $api_args['moderator_keyword'] = $keywords[array_rand($keywords)];
                            }
                        }
                    }
                }
            }
        }

        $result = xh_api_request('rand-comment', [
            'args' => $api_args
        ], $post);

        if (is_wp_error($result)) {
            $this->addlog([
                'commentid' => 0,
                'postid' => $post->ID,
                'type' => 'randcomment',
                'result' => 'error',
                'reason' => $result->get_error_message()
            ]);
            return;
        }

        if (empty($result['content'])) {
            $this->addlog([
                'commentid' => 0,
                'postid' => $post->ID,
                'type' => 'randcomment',
                'result' => 'error',
                'reason' => __('API response is empty', 'xhtheme-ai-toolbox')
            ]);
            return;
        }

        $commenter = $this->get_randcomment_identity($settings, $post->ID, $result);
        if (empty($commenter['name'])) {
            $this->addlog([
                'commentid' => 0,
                'postid' => $post->ID,
                'type' => 'randcomment',
                'result' => 'error',
                'reason' => __('Cannot get commenter identity', 'xhtheme-ai-toolbox')
            ]);
            return;
        }

        $comment_meta = [
            '_ai_interact_type' => 'randcomment'
        ];
        if (!empty($commenter['avatar'])) {
            $comment_meta['_ai_avatar'] = $commenter['avatar'];
        }

        $comment_id = wp_insert_comment([
            'comment_post_ID' => $post->ID,
            'comment_author' => $commenter['name'],
            'comment_author_email' => $commenter['email'],
            'comment_content' => $result['content'],
            'comment_type' => 'comment',
            'comment_parent' => 0,
            'user_id' => $commenter['user_id'] ?? 0,
            'comment_approved' => 1,
            'comment_author_IP' => $commenter['ip'],
            'comment_agent' => $commenter['agent'],
            'comment_meta' => $comment_meta
        ]);

        if ($comment_id) {
            set_transient('xhtheme_randcomment_cooldown', 1, $interval);

            $is_moderator = ($result['type'] ?? '') === 'moderator';
            if ($is_moderator) {
                $this->get_moderator_daily_count(true);
            }

            $this->addlog([
                'commentid' => $comment_id,
                'postid' => $post->ID,
                'type' => 'randcomment',
                'result' => 'posted',
                'keyword' => $is_moderator ? ($api_args['moderator_keyword'] ?? null) : null
            ]);
            $this->on_comment_post($comment_id);
        } else {
            $this->addlog([
                'commentid' => 0,
                'postid' => $post->ID,
                'type' => 'randcomment',
                'result' => 'error',
                'reason' => __('Comment insert failed', 'xhtheme-ai-toolbox')
            ]);
        }
    }

    /**
     * 检查是否在禁止时段
     */
    private function is_in_blackout_period($hour, $start, $end)
    {
        if ($start == $end) {
            return false;
        }
        if ($start < $end) {
            return $hour >= $start && $hour < $end;
        }
        return $hour >= $start || $hour < $end;
    }

    /**
     * 检查每日随手一评限制
     */
    private function check_randcomment_daily_limit($settings)
    {
        global $wpdb;
        $table = $wpdb->prefix . self::TABLE_NAME;
        $today_start = wp_date('Y-m-d') . ' 00:00:00';

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $count = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$table} 
             WHERE type = 'randcomment' AND result = 'posted' 
             AND createdat >= %s",
            $today_start
        ));

        return $count < ($settings['max_per_day'] ?? 50);
    }


    /**
     * 获取随机文章用于随手一评（使用缓存池策略）
     */
    private function find_suitable_post_for_randcomment($settings, $depth = 0)
    {
        $cache_key = 'xhai_randcomment_pool';
        $pool = get_transient($cache_key);

        if ($depth > 2) {
            return null;
        }

        if (empty($pool)) {
            $pool = $this->refresh_randcomment_pool($settings);
            if (empty($pool)) {
                return null;
            }
        }

        $found_post = null;
        $max_attempts = min(count($pool), 10);

        for ($i = 0; $i < $max_attempts; $i++) {
            $post_id = array_shift($pool);
            if (empty($post_id)) {
                break;
            }

            $post = get_post($post_id);
            if ($post && $post->post_status === 'publish' && $post->comment_status === 'open') {
                $found_post = $post;
                break;
            }
        }

        if (!empty($pool) && count($pool) > 3) {
            set_transient($cache_key, $pool, DAY_IN_SECONDS);
        } else {
            delete_transient($cache_key);
        }

        if ($found_post) {
            return $found_post;
        }

        $pool = $this->refresh_randcomment_pool($settings);
        if (!empty($pool)) {
            set_transient($cache_key, $pool, DAY_IN_SECONDS);
            return $this->find_suitable_post_for_randcomment($settings, $depth + 1);
        }

        return null;
    }

    /**
     * 刷新随手一评候选文章缓存池
     */
    private function refresh_randcomment_pool($settings)
    {
        global $wpdb;
        $max_per_post = $settings['max_per_post'] ?? 5;
        $max_comments = 100;

        $post_types = $settings['post_types'] ?? ['post'];
        if (empty($post_types) || !is_array($post_types)) {
            $post_types = ['post'];
        }
        $placeholders = implode(', ', array_fill(0, count($post_types), '%s'));

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
        $total = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->posts}
             WHERE post_status = 'publish' 
             AND post_type IN ($placeholders)
             AND comment_status = 'open'
             AND comment_count < %d",
            ...array_merge($post_types, [$max_comments])
        ));

        if ($total === 0) {
            return [];
        }

        $fetch_count = 100;
        $offset = $total > $fetch_count ? wp_rand(0, $total - $fetch_count) : 0;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
        $posts = $wpdb->get_results($wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts}
             WHERE post_status = 'publish' 
             AND post_type IN ($placeholders)
             AND comment_status = 'open'
             AND comment_count < %d
             LIMIT %d, %d",
            ...array_merge($post_types, [$max_comments, $offset, $fetch_count])
        ));

        if (empty($posts)) {
            return [];
        }

        $post_ids = array_map(function ($p) {
            return (int) $p->ID;
        }, $posts);
        $id_placeholders = implode(', ', array_fill(0, count($post_ids), '%d'));

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
        $counts_raw = $wpdb->get_results($wpdb->prepare(
            "SELECT c.comment_post_ID, COUNT(*) as cnt 
             FROM {$wpdb->comments} c
             INNER JOIN {$wpdb->commentmeta} m ON c.comment_ID = m.comment_id
             WHERE c.comment_post_ID IN ($id_placeholders)
             AND m.meta_key = '_ai_interact_type' 
             AND m.meta_value = 'randcomment'
             GROUP BY c.comment_post_ID",
            ...$post_ids
        ), ARRAY_A);
        $counts = [];
        if (!empty($counts_raw)) {
            foreach ($counts_raw as $row) {
                $counts[(int) $row['comment_post_ID']] = (int) $row['cnt'];
            }
        }
        $eligible = [];
        foreach ($post_ids as $pid) {
            $count = $counts[$pid] ?? 0;
            if ($count < $max_per_post) {
                $eligible[] = $pid;
            }
        }
        shuffle($eligible);
        return $eligible;
    }

    /**
     * 获取文章历史评论用于API上下文
     */
    private function get_post_comments_for_api($post_id)
    {
        $comments = get_comments([
            'post_id' => $post_id,
            'status' => 'approve',
            'parent' => 0,
            'number' => 100,
            'orderby' => 'comment_date',
            'order' => 'DESC'
        ]);

        return array_map(function ($c) {
            return [
                'content' => $c->comment_content,
                'author' => $c->comment_author
            ];
        }, $comments);
    }

    /**
     * 获取随手一评的评论身份
     */
    private function get_randcomment_identity($settings, $post_id, $api_result)
    {
        $ai_user_data = $api_result['ai_user'] ?? null;
        $ai_nickname = $ai_user_data['name'] ?? '';
        $ai_avatar = $ai_user_data['avatar'] ?? '';
        $ai_ip = $ai_user_data['ip'] ?? '';

        if ($settings['identity_mode'] === 'visitor') {
            if (!empty($ai_nickname)) {
                $name = $ai_nickname;
                $email = $this->generateRandomEmail();
                $agent = $this->getAgents();
            } else {
                $filtered = $this->filterCommentNickname($post_id);
                $name = $filtered['name'];
                $email = $filtered['email'];
                $agent = $filtered['agent'];
            }

            return [
                'name' => $name,
                'email' => $email,
                'user_id' => 0,
                'ip' => $ai_ip ?: $this->getRandomIP(),
                'agent' => $agent,
                'avatar' => $ai_avatar
            ];
        }

        global $wpdb;
        $ai_user = null;
        $ai_user_limit = (int) xh_option('aiUserLimit', 200);
        $current_ai_user_count = $this->get_ai_user_count();
        $can_create_user = $current_ai_user_count < $ai_user_limit;

        if (!empty($ai_nickname)) {
            $existing_user = get_users([
                'role' => 'xhaiuser',
                'search' => $ai_nickname,
                'search_columns' => ['display_name'],
                'number' => 1,
                'cache_results' => false
            ]);

            if (empty($existing_user)) {
                if ($can_create_user) {
                    $ai_user = $this->create_ai_user($ai_user_data);
                }
            } else {
                $user = $existing_user[0];
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $commented = $wpdb->get_var($wpdb->prepare(
                    "SELECT comment_ID FROM {$wpdb->comments} 
                     WHERE comment_post_ID = %d AND user_id = %d LIMIT 1",
                    $post_id,
                    $user->ID
                ));

                if (!$commented) {
                    $ai_user = $user;
                }
            }
        }

        if (!$ai_user) {
            $ai_user = $this->get_random_aiuser($post_id);
        }

        if (!$ai_user) {
            return [];
        }

        return [
            'name' => $ai_user->display_name,
            'email' => $ai_user->user_email,
            'user_id' => $ai_user->ID,
            'ip' => $this->getUserLastComment($ai_user->ID) ? $this->getUserIP($ai_user->ID) : ($ai_ip ?: $this->getRandomIP()),
            'agent' => $this->getUserAgent($ai_user->ID)
        ];
    }

    /**
     * 获取/增加今日评论官触发计数
     */
    private function get_moderator_daily_count($increment = false)
    {
        $cache_key = 'xhtheme_moderator_daily_' . wp_date('Y-m-d');
        $count = get_transient($cache_key);

        if ($count === false) {
            $count = 0;
        }

        if ($increment) {
            $count++;
        }

        if ($increment || $count === 0) {
            set_transient($cache_key, $count, DAY_IN_SECONDS);
        }

        return (int) $count;
    }

    /**
     * 获取指定文章的评论官回复总次数
     */
    private function get_moderator_postcount($post_id)
    {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        return (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->comments} c
             INNER JOIN {$wpdb->commentmeta} m ON c.comment_ID = m.comment_id
             WHERE c.comment_post_ID = %d 
             AND m.meta_key = '_ai_interact_type' 
             AND m.meta_value = 'moderator'",
            $post_id
        ));
    }
}
