<?php
/*
Plugin Name: 消息群发助手
Description: 消息群发管理，只适用于子比主题。
Author: Custom
Version: 1.0
*/

// 1. 初始化
add_action('admin_menu', 'zms_add_admin_menu');
add_action('wp_ajax_zms_handle_request', 'zms_handle_ajax_request');

function zms_add_admin_menu() {
    add_menu_page('消息助手', '消息助手', 'manage_options', 'zib-msg-sender', 'zms_render_page', 'dashicons-email-alt', 99);
}

// 2. 辅助函数：SVG 智能转 Base64 (核心修复点)
function zms_convert_svg_to_datauri($input) {
    // 1. 关键修复：去除反斜杠 (解决 WordPress 自动转义问题)
    $input = stripslashes(trim($input));
    
    // 判断是否为 SVG 代码
    if (strpos($input, '<svg') !== false) {
        // 2. 压缩代码：去除换行符和多余空格，防止 Base64 字符串过长
        $input = preg_replace('/\s+/', ' ', $input);

        // 3. 关键修复：补全 xmlns 命名空间 (Data URI 必须项)
        if (strpos($input, 'xmlns=') === false) {
            $input = str_replace('<svg', '<svg xmlns="http://www.w3.org/2000/svg"', $input);
        }

        // 转码
        $encoded = base64_encode($input);
        return 'data:image/svg+xml;base64,' . $encoded;
    }
    return $input;
}

// 3. AJAX 处理
function zms_handle_ajax_request() {
    @ini_set('memory_limit', '512M');
    @set_time_limit(0);
    @ini_set('display_errors', 0);
    header('Content-Type: application/json; charset=utf-8');

    try {
        if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'zms_nonce')) {
            throw new Exception('令牌校验失败');
        }
        if (!current_user_can('manage_options')) throw new Exception('无权限');

        global $wpdb;
        $msg_table = $wpdb->prefix . 'zib_message';
        $action = isset($_POST['zms_sub_action']) ? $_POST['zms_sub_action'] : '';
        $response_msg = '操作成功';

        // 搜索用户
        if ($action == 'search_user') {
            $keyword = isset($_POST['keyword']) ? trim($_POST['keyword']) : '';
            if (strlen($keyword) < 1) wp_send_json_success([]);
            $args = [
                'search'         => '*' . $wpdb->esc_like($keyword) . '*',
                'search_columns' => ['ID', 'user_login', 'user_nicename', 'user_email', 'display_name'],
                'number'         => 10,
                'fields'         => ['ID', 'user_login', 'display_name', 'user_email']
            ];
            $user_query = new WP_User_Query($args);
            $results = [];
            foreach ($user_query->get_results() as $user) {
                $results[] = [
                    'id' => $user->ID,
                    'text' => $user->display_name . ' (' . $user->user_login . ')',
                    'email' => $user->user_email,
                    'avatar' => get_avatar_url($user->ID, ['size' => 48])
                ];
            }
            wp_send_json_success($results);
            exit;
        }

        // 发送消息
        if ($action == 'send') {
            if (!class_exists('ZibMsg')) throw new Exception('未找到子比主题 ZibMsg 类');

            $targets = isset($_POST['targets']) ? $_POST['targets'] : [];
            $specific_id = isset($_POST['specific_user_id']) ? intval($_POST['specific_user_id']) : 0;
            $title = sanitize_text_field($_POST['msg_title']);
            // 内容处理
            $content = wp_kses_post(stripslashes($_POST['msg_content']));
            
            // 图标处理 (传入前不做 stripslashes，在函数内做)
            $icon_input = isset($_POST['msg_icon']) ? $_POST['msg_icon'] : '';
            $icon_url = zms_convert_svg_to_datauri($icon_input);

            if (empty($title) || empty($content)) throw new Exception('标题或内容为空');

            $final_ids = [];
            if ($specific_id > 0) {
                $user = get_user_by('id', $specific_id);
                if ($user) $final_ids[] = $user->ID;
            } elseif (!empty($targets)) {
                $users = get_users(['fields' => 'ID']); 
                if (empty($users)) throw new Exception('无用户');
                foreach ($users as $uid) {
                    if(!$uid || !is_numeric($uid)) continue;
                    $vip = zib_get_user_vip_level($uid);
                    $add = false;
                    if (in_array('non_vip', $targets) && empty($vip)) $add = true;
                    if (in_array('vip_1', $targets) && $vip == 1) $add = true;
                    if (in_array('vip_2', $targets) && $vip == 2) $add = true;
                    if ($add) $final_ids[] = $uid;
                }
            }

            if (empty($final_ids)) throw new Exception('无有效发送目标');

            $count = 0;
            foreach ($final_ids as $uid) {
                $args = [
                    'send_user'    => 'admin',
                    'receive_user' => $uid,
                    'type'         => 'system',
                    'title'        => $title,
                    'content'      => $content,
                ];
                if ($icon_url) $args['meta'] = ['customize_icon' => $icon_url];
                ZibMsg::add($args);
                $count++;
            }

            $log = [
                'id'       => uniqid(),
                'time'     => current_time('m-d H:i'),
                'targets'  => $targets,
                'specific' => $specific_id ? get_userdata($specific_id)->display_name : '',
                'title'    => $title,
                'content'  => $content,
                'icon'     => $icon_input, // 存原始代码方便回填
                'count'    => $count,
                'status'   => 'sent'
            ];
            $history = get_option('zms_send_history', []);
            if (!is_array($history)) $history = [];
            array_unshift($history, $log);
            if (count($history) > 50) array_pop($history);
            update_option('zms_send_history', $history);
            
            $response_msg = "成功发送给 {$count} 位用户";
        }

        // 撤回/删除/清空
        elseif ($action == 'recall') {
            $title = stripslashes($_POST['log_title']);
            $log_id = $_POST['log_id'];
            if ($title) $wpdb->query("DELETE FROM $msg_table WHERE title = '" . esc_sql($title) . "'");
            $history = get_option('zms_send_history', []);
            foreach ($history as &$item) {
                if (isset($item['id']) && $item['id'] == $log_id) {
                    $item['status'] = 'recalled';
                    break;
                }
            }
            update_option('zms_send_history', $history);
            $response_msg = "已撤回";
        }
        elseif ($action == 'delete_log') {
            $log_id = $_POST['log_id'];
            $history = get_option('zms_send_history', []);
            foreach ($history as $k => $item) {
                if (isset($item['id']) && $item['id'] == $log_id) { unset($history[$k]); break; }
            }
            update_option('zms_send_history', array_values($history));
        }
        elseif ($action == 'clear_all') {
            delete_option('zms_send_history');
        }

        ob_start();
        zms_render_history_list();
        $html = ob_get_clean();
        wp_send_json_success(['html' => $html, 'msg' => $response_msg]);

    } catch (Throwable $e) {
        wp_send_json_error(['msg' => $e->getMessage()]);
    }
    wp_die();
}

// 4. 列表渲染
function zms_render_history_list() {
    $history = get_option('zms_send_history', []);
    $svg_recall = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 2v6h6"></path><path d="M2.66 15.57a10 10 0 1 0 .57-8.38"></path></svg>';
    $svg_trash = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>';
    $svg_resend = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>';

    if (empty($history)): ?>
        <div style="text-align:center; padding: 40px; color:#ccc;">暂无消息记录</div>
    <?php else: foreach ($history as $log): 
        $is_recalled = isset($log['status']) && $log['status'] == 'recalled';
        $icon_data = isset($log['icon']) ? $log['icon'] : '';
    ?>
        <div class="zms-bubble <?php echo $is_recalled ? 'recalled' : ''; ?>">
            <div class="zms-meta">
                <span class="dot <?php echo $is_recalled ? 'dot-red' : 'dot-green'; ?>"></span>
                <?php echo esc_html($log['time']); ?>
                <span>•</span>
                <?php if($is_recalled): ?>
                    <span style="color:#d63638">已撤回</span>
                <?php else: ?>
                    <span><?php echo !empty($log['specific']) ? '仅发给: ' . esc_html($log['specific']) : '群发 ' . intval($log['count']) . ' 人'; ?></span>
                <?php endif; ?>
            </div>
            <div class="zms-bubble-title"><?php echo esc_html($log['title']); ?></div>
            <div class="zms-bubble-content"><?php echo wp_kses_post($log['content']); ?></div>
            <textarea style="display:none" id="raw-content-<?php echo $log['id']; ?>"><?php echo esc_textarea($log['content']); ?></textarea>
            <textarea style="display:none" id="raw-icon-<?php echo $log['id']; ?>"><?php echo esc_textarea($icon_data); ?></textarea>
            <div class="zms-actions">
                <button type="button" class="zms-act-btn" title="再次发送" onclick="resendMsg('<?php echo esc_js($log['title']); ?>', '<?php echo $log['id']; ?>')"><?php echo $svg_resend; ?></button>
                <?php if(!$is_recalled): ?>
                    <button type="button" class="zms-act-btn btn-recall" title="撤回消息" onclick="doAjaxAction('recall', {log_id: '<?php echo $log['id']; ?>', log_title: '<?php echo esc_js($log['title']); ?>'})"><?php echo $svg_recall; ?></button>
                <?php else: ?>
                    <button type="button" class="zms-act-btn" title="删除记录" onclick="doAjaxAction('delete_log', {log_id: '<?php echo $log['id']; ?>'})"><?php echo $svg_trash; ?></button>
                <?php endif; ?>
            </div>
        </div>
    <?php endforeach; endif;
}

// 5. 页面渲染 (保持 v3.1 优化的 UI)
function zms_render_page() {
    if (!current_user_can('manage_options')) return;
    $nonce = wp_create_nonce('zms_nonce');
    ?>
    <style>
        #wpcontent { background: #f0f2f5; }
        .zms-app { max-width: 1100px; margin: 30px auto; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif; display: grid; grid-template-columns: 420px 1fr; gap: 30px; align-items: start; }
        @media (max-width: 900px) { .zms-app { grid-template-columns: 1fr; } }
        /* 左侧 */
        .zms-editor { background: #fff; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.04); padding: 30px; position: sticky; top: 50px; border: 1px solid rgba(255,255,255,0.8); }
        .zms-head-title { font-size: 18px; font-weight: 700; color: #111; margin-bottom: 25px; display: flex; align-items: center; gap: 8px; }
        .zms-group { margin-bottom: 25px; position: relative; }
        .zms-label { font-size: 13px; font-weight: 600; color: #555; margin-bottom: 10px; display: block; }
        .zms-input, .zms-textarea { width: 100%; border: 2px solid #eef0f5; background: #f9fafb; border-radius: 12px; padding: 0 15px; font-size: 14px; transition: all 0.2s; box-sizing: border-box; outline: none; color: #333; }
        .zms-input { height: 46px; line-height: 46px; } 
        .zms-input:focus, .zms-textarea:focus { border-color: #2271b1; background: #fff; box-shadow: 0 0 0 4px rgba(34,113,177,0.1); }
        .zms-textarea { min-height: 120px; line-height: 1.6; font-family: monospace; padding-top:12px; }
        .zms-title-row { display: flex; gap: 10px; align-items: center; }
        .zms-title-row .zms-input { flex: 1; }
        .zms-icon-btn-trigger { width: 46px; height: 46px; flex-shrink: 0; border-radius: 12px; background: #f0f2f5; color: #666; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: 0.2s; border: 2px solid #eef0f5; position: relative; box-sizing: border-box; }
        .zms-icon-btn-trigger:hover { background: #fff; border-color: #2271b1; color: #2271b1; }
        .zms-icon-btn-trigger svg { width: 20px; height: 20px; }
        #icon-input-wrap { display: none; position: absolute; top: 110%; right: 0; width: 320px; background: #fff; box-shadow: 0 10px 40px rgba(0,0,0,0.15); border-radius: 12px; padding: 15px; z-index: 100; border: 1px solid #eee; }
        #icon-preview-area { margin-top: 8px; font-size: 12px; color: #666; display: flex; align-items: center; gap: 8px; background: #f0f9ff; padding: 8px 12px; border-radius: 8px; border: 1px dashed #bce3ff; }
        #icon-preview-area img { width: 20px; height: 20px; border-radius: 4px; }
        .zms-pills { display: flex; gap: 8px; flex-wrap: wrap; }
        .zms-check-hidden { display: none; }
        .zms-pill-label { padding: 8px 18px; border-radius: 50px; background: #f2f4f7; color: #666; font-size: 13px; font-weight: 600; cursor: pointer; transition: 0.2s; user-select: none; border: 1px solid transparent; }
        .zms-check-hidden:checked + .zms-pill-label { background: #2271b1; color: #fff; box-shadow: 0 4px 12px rgba(34,113,177,0.3); transform: translateY(-1px); }
        #msg_preview_box { margin-top: 10px; background: #fdfdfd; border: 1px dashed #ddd; border-radius: 12px; padding: 15px; min-height: 60px; color: #444; font-size: 14px; line-height: 1.6; word-wrap: break-word; }
        #msg_preview_box img { max-width: 100%; height: auto; border-radius: 6px; }
        
        /* 按钮与状态 */
        .zms-send-btn { width: 100%; background: #2271b1; color: #fff; border: none; padding: 14px; border-radius: 14px; font-size: 16px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; transition: all 0.2s; box-shadow: 0 4px 15px rgba(34,113,177,0.25); }
        .zms-send-btn:hover { background: #135e96; transform: translateY(-2px); box-shadow: 0 6px 20px rgba(34,113,177,0.35); }
        .zms-btn-loading { background: #78a9d1 !important; cursor: not-allowed; pointer-events: none; }
        .zms-btn-success { background: #46b450 !important; cursor: default; pointer-events: none; box-shadow: 0 4px 15px rgba(70,180,80,0.3) !important; transform: none !important; }
        .zms-btn-error { background: #d63638 !important; }
        .zms-send-btn svg { width: 20px; height: 20px; }
        .spinner-inline { width: 18px; height: 18px; border: 2px solid #fff; border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; }
        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
        #zms-error-feedback { margin-top: 10px; color: #d63638; background: #fff0f1; padding: 10px; border-radius: 8px; border: 1px solid #ffcfd1; font-size: 13px; text-align: center; display: none; }

        /* 右侧列表 */
        .zms-timeline { padding: 10px 0; }
        .zms-timeline-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding: 0 5px; }
        .zms-timeline-title { font-size: 18px; font-weight: 700; color: #333; }
        .zms-bubble { background: #fff; border-radius: 16px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.03); border: 1px solid #f0f0f1; position: relative; transition: 0.3s; }
        .zms-bubble:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0,0,0,0.06); }
        .zms-bubble.recalled { opacity: 0.7; background: #fcfcfc; border-style: dashed; }
        .zms-meta { font-size: 12px; color: #999; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }
        .dot { width: 8px; height: 8px; border-radius: 50%; }
        .dot-green { background: #46b450; box-shadow: 0 0 0 2px rgba(70,180,80,0.2); }
        .dot-red { background: #d63638; box-shadow: 0 0 0 2px rgba(214,54,56,0.2); }
        .zms-bubble-title { font-size: 16px; font-weight: 700; color: #2c3338; margin-bottom: 8px; }
        .zms-bubble-content { font-size: 14px; color: #50575e; line-height: 1.6; }
        .zms-bubble-content img { max-width: 100px; border-radius: 4px; margin-top: 5px; }
        .zms-actions { margin-top: 15px; padding-top: 15px; border-top: 1px solid #f6f7f7; display: flex; justify-content: flex-end; gap: 8px; }
        .zms-act-btn { width: 34px; height: 34px; border-radius: 8px; border: none; background: #f0f2f5; color: #555; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: 0.2s; }
        .zms-act-btn:hover { background: #e0e5ea; color: #000; }
        .zms-act-btn svg { width: 16px; height: 16px; }
        .btn-recall { background: #fff0f1; color: #d63638; }
        .btn-recall:hover { background: #fcdbdc; }

        /* 搜索 */
        .zms-search-wrap { position: relative; }
        .zms-search-results { position: absolute; top: 105%; left: 0; right: 0; background: #fff; border: 1px solid #dcdcde; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); z-index: 1000; max-height: 250px; overflow-y: auto; display: none; }
        .zms-search-item { padding: 10px 15px; cursor: pointer; display: flex; align-items: center; gap: 10px; border-bottom: 1px solid #f0f0f1; transition: 0.1s; }
        .zms-search-item:last-child { border-bottom: none; }
        .zms-search-item:hover { background: #f6f7f7; }
        .zms-search-item img { width: 24px; height: 24px; border-radius: 50%; }
        .zms-search-item-info { display: flex; flex-direction: column; }
        .zms-search-name { font-size: 13px; font-weight: 600; color: #333; }
        .zms-search-meta { font-size: 11px; color: #888; }
        .zms-selected-user { margin-top: 8px; padding: 8px 12px; background: #eef5fa; border: 1px solid #bce3ff; border-radius: 8px; display: none; align-items: center; justify-content: space-between; }
        .zms-selected-info { font-size: 13px; font-weight: 600; color: #2271b1; }
        .zms-remove-user { cursor: pointer; color: #d63638; font-size: 12px; font-weight: normal; }
        .zms-remove-user:hover { text-decoration: underline; }
        
        #zms-loading-mask { position: fixed; top:0; left:0; right:0; bottom:0; background: rgba(255,255,255,0.6); z-index: 9999; display:none; align-items:center; justify-content:center; }
        .spinner-custom { width: 40px; height: 40px; border: 4px solid #f3f3f3; border-top: 4px solid #2271b1; border-radius: 50%; animation: spin 1s linear infinite; }
    </style>

    <div id="zms-loading-mask"><div class="spinner-custom"></div></div>

    <div class="zms-app">
        <div class="zms-editor">
            <div class="zms-head-title">📩 发送新消息</div>
            <form id="zms-form">
                <input type="hidden" id="zms_security_field" name="security" value="<?php echo esc_attr($nonce); ?>">
                
                <div class="zms-group">
                    <span class="zms-label">指定发送给个人 (输入 ID / 昵称 / 邮箱搜索)</span>
                    <div class="zms-search-wrap">
                        <input type="text" id="user-search-input" class="zms-input" placeholder="输入关键词开始搜索..." autocomplete="off">
                        <input type="hidden" name="specific_user_id" id="specific_user_id">
                        <div id="search-results" class="zms-search-results"></div>
                        <div id="selected-user-display" class="zms-selected-user">
                            <span class="zms-selected-info"></span>
                            <span class="zms-remove-user" onclick="clearSelectedUser()">✕ 取消指定</span>
                        </div>
                    </div>
                </div>

                <div class="zms-group">
                    <span class="zms-label">或者：批量群发</span>
                    <div class="zms-pills">
                        <label><input type="checkbox" name="targets[]" value="non_vip" class="zms-check-hidden"><span class="zms-pill-label">普通用户</span></label>
                        <label><input type="checkbox" name="targets[]" value="vip_1" class="zms-check-hidden"><span class="zms-pill-label">一级会员</span></label>
                        <label><input type="checkbox" name="targets[]" value="vip_2" class="zms-check-hidden"><span class="zms-pill-label">二级会员</span></label>
                    </div>
                </div>

                <div class="zms-group">
                    <span class="zms-label">消息标题</span>
                    <div class="zms-title-row">
                        <input type="text" name="msg_title" id="msg_title" class="zms-input" required placeholder="建议带上日期...">
                        <div class="zms-icon-btn-trigger" id="icon-toggle" title="设置图标">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>
                            <div id="icon-input-wrap">
                                <span class="zms-label" style="margin-bottom:8px;">粘贴图片链接 或 SVG代码</span>
                                <textarea id="icon-input-area" class="zms-textarea" style="min-height:60px;font-size:12px;padding-top:8px;" placeholder="在此粘贴..."></textarea>
                                <div id="icon-preview-area" style="display:none;">
                                    <img id="icon-preview-img" src="">
                                    <span>已识别图标</span>
                                </div>
                            </div>
                        </div>
                        <input type="hidden" name="msg_icon" id="msg_icon_val">
                    </div>
                </div>

                <div class="zms-group">
                    <span class="zms-label">消息内容 (支持 HTML)</span>
                    <textarea name="msg_content" id="msg_content" class="zms-textarea" required placeholder="输入文字，下方会实时显示效果..."></textarea>
                    <div id="msg_preview_box"><span style="color:#aaa;">(预览区域)</span></div>
                </div>

                <button type="button" class="zms-send-btn" id="btn-submit-send">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg> 立即发送
                </button>
                <div id="zms-error-feedback"></div>
            </form>
        </div>
        <div class="zms-timeline">
            <div class="zms-timeline-head">
                <div class="zms-timeline-title">发送记录</div>
                <button type="button" class="zms-act-btn" title="清空全部" onclick="doAjaxAction('clear_all', {}, '确定要清空所有记录吗？')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"></path></svg></button>
            </div>
            <div id="history-container">
                <?php zms_render_history_list(); ?>
            </div>
        </div>
    </div>

    <script>
    var zms_ajax_url = "<?php echo admin_url('admin-ajax.php'); ?>";
    jQuery(document).ready(function($) {
        // 搜索
        let searchTimer;
        const searchInput = $('#user-search-input');
        const searchResults = $('#search-results');
        const hiddenId = $('#specific_user_id');
        const selectedDisplay = $('#selected-user-display');
        const selectedInfo = selectedDisplay.find('.zms-selected-info');

        searchInput.on('input', function() {
            clearTimeout(searchTimer);
            const keyword = $(this).val().trim();
            if (keyword.length < 1) { searchResults.hide().empty(); return; }
            searchTimer = setTimeout(function() {
                $.post(zms_ajax_url, {
                    action: 'zms_handle_request',
                    zms_sub_action: 'search_user',
                    keyword: keyword,
                    security: $('#zms_security_field').val()
                }, function(res) {
                    searchResults.empty();
                    if (res.success && res.data.length > 0) {
                        res.data.forEach(user => {
                            searchResults.append(`<div class="zms-search-item" onclick="selectUser('${user.id}', '${user.text.replace(/'/g, "\\'")}')"><img src="${user.avatar}"><div class="zms-search-item-info"><span class="zms-search-name">${user.text}</span><span class="zms-search-meta">ID: ${user.id} | ${user.email}</span></div></div>`);
                        });
                        searchResults.show();
                    } else { searchResults.append('<div style="padding:10px;color:#999;text-align:center">未找到匹配用户</div>').show(); }
                });
            }, 400);
        });
        $(document).click(function(e) { if (!$(e.target).closest('.zms-search-wrap').length) searchResults.hide(); });
        window.selectUser = function(id, name) { hiddenId.val(id); selectedInfo.text('已指定: ' + name); selectedDisplay.css('display', 'flex'); searchInput.val('').hide(); searchResults.hide(); };
        window.clearSelectedUser = function() { hiddenId.val(''); selectedDisplay.hide(); searchInput.show().focus(); };

        // 发送 (v3.1 UI优化)
        $('#btn-submit-send').on('click', function() {
            var $btn = $(this);
            var $errBox = $('#zms-error-feedback');
            $errBox.hide();

            var title = $('#msg_title').val();
            var content = $('#msg_content').val();
            if(!title || !content) { alert('请填写标题和内容'); return; }
            
            var hasTarget = $('input[name="targets[]"]:checked').length > 0;
            var hasSpecific = $('#specific_user_id').val() !== '';
            if(!hasTarget && !hasSpecific) { alert('请先指定一个用户，或选择群发对象'); return; }
            if(!confirm('确定要发送吗？')) return;

            var originalHtml = $btn.html();
            $btn.addClass('zms-btn-loading').html('<span class="spinner-inline"></span> 正在发送...');

            var formData = $('#zms-form').serializeArray();
            formData.push({name: 'action', value: 'zms_handle_request'}); 
            formData.push({name: 'zms_sub_action', value: 'send'}); 
            if (!formData.find(item => item.name === 'security')) formData.push({name: 'security', value: $('#zms_security_field').val()});

            $.post(zms_ajax_url, formData, function(response) {
                if (response.success) {
                    $('#history-container').html(response.data.html);
                    $btn.removeClass('zms-btn-loading').addClass('zms-btn-success').html('✅ 发送成功');
                    $('#msg_title').val(''); $('#msg_content').val('');
                    $('#msg_preview_box').html('<span style="color:#aaa;">(预览区域)</span>');
                    if(window.clearSelectedUser) window.clearSelectedUser();
                    setTimeout(function() { $btn.removeClass('zms-btn-success').html(originalHtml); }, 2000);
                } else {
                    handleError($btn, originalHtml, response.data.msg);
                }
            }).fail(function(xhr) {
                handleError($btn, originalHtml, '网络错误或服务器崩溃，请检查控制台。');
            });
        });

        function handleError($btn, originalHtml, msg) {
            $btn.removeClass('zms-btn-loading').addClass('zms-btn-error').html('❌ 发送失败');
            $('#zms-error-feedback').text('错误原因: ' + msg).show();
            setTimeout(function() { $btn.removeClass('zms-btn-error').html(originalHtml); }, 3000);
        }
    });

    // 撤回等操作
    window.doAjaxAction = function(subAction, extraData, confirmMsg) {
        if(confirmMsg && !confirm(confirmMsg)) return;
        var data = [{name: 'action', value: 'zms_handle_request'}, {name: 'zms_sub_action', value: subAction}, {name: 'security', value: jQuery('#zms_security_field').val()}];
        for (var key in extraData) { data.push({name: key, value: extraData[key]}); }
        jQuery('#zms-loading-mask').css('display', 'flex'); 
        jQuery.post(zms_ajax_url, data, function(response) {
            jQuery('#zms-loading-mask').hide(); 
            if (response.success) { jQuery('#history-container').html(response.data.html); } else { alert(response.data.msg || '操作失败'); }
        });
    }

    // 预览与图标 (优化了回填逻辑)
    const contentInput = document.getElementById('msg_content');
    const previewBox = document.getElementById('msg_preview_box');
    if(contentInput) {
        contentInput.addEventListener('input', function() {
            previewBox.innerHTML = this.value.trim() === '' ? '<span style="color:#aaa;">(预览区域)</span>' : this.value.replace(/\n/g, '<br>');
        });
    }
    const iconToggle = document.getElementById('icon-toggle');
    const iconWrap = document.getElementById('icon-input-wrap');
    const iconInput = document.getElementById('icon-input-area');
    const iconHidden = document.getElementById('msg_icon_val');
    const iconPrevArea = document.getElementById('icon-preview-area');
    const iconPrevImg = document.getElementById('icon-preview-img');
    if(iconToggle) {
        iconToggle.addEventListener('click', function(e) { e.stopPropagation(); iconWrap.style.display = iconWrap.style.display === 'block' ? 'none' : 'block'; });
        iconWrap.addEventListener('click', function(e) { e.stopPropagation(); });
        document.addEventListener('click', function() { iconWrap.style.display = 'none'; });
        iconInput.addEventListener('input', function() {
            let val = this.value.trim(); iconHidden.value = val;
            if (val) {
                iconPrevArea.style.display = 'flex';
                // 前端预览时也要支持 SVG 渲染
                if (val.startsWith('<svg')) {
                   // 简单的前端 SVG 转 Data URI 预览 (注意这里也需要补全 xmlns 才能预览成功)
                   let svgCode = val;
                   if (svgCode.indexOf('xmlns=') === -1) svgCode = svgCode.replace('<svg', '<svg xmlns="http://www.w3.org/2000/svg"');
                   iconPrevImg.src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgCode)));
                } else {
                   iconPrevImg.src = val;
                }
            } else { iconPrevArea.style.display = 'none'; }
        });
    }
    window.resendMsg = function(title, id) {
        document.getElementById('msg_title').value = title;
        document.getElementById('msg_content').value = document.getElementById('raw-content-' + id).value;
        previewBox.innerHTML = document.getElementById('msg_content').value.replace(/\n/g, '<br>');
        let iconVal = document.getElementById('raw-icon-' + id).value;
        if(iconVal) { iconInput.value = iconVal; iconInput.dispatchEvent(new Event('input')); }
        window.scrollTo({ top: 0, behavior: 'smooth' });
    }
    </script>
    <?php
}