<?php
// modules/pasarguard/widgets/psg_users.php

global $pdo;
$serversList = [];
try {
    if (isset($pdo)) {
        $serversList = $pdo->query("SELECT * FROM servers ORDER BY id ASC")->fetchAll(PDO::FETCH_ASSOC);
    }
} catch (Exception $e) {}
?>

<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<link rel="stylesheet" type="text/css" href="/vpnet-panel/assets/css/datatables.min.css">
<style>
    .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_length, .dataTables_info { display: none !important; }
    .dataTables_wrapper .dataTables_paginate { margin-top: 1.5rem !important; display: flex; justify-content: center; }
    .dataTables_wrapper .dataTables_paginate .paginate_button { border-radius: 6px !important; border: 1px solid #e2e8f0 !important; background: #fff !important; margin: 0 3px !important; padding: 4px 10px !important; font-weight: bold; font-size: 12px; cursor: pointer; color: #64748b !important; }
    html.dark .dataTables_wrapper .dataTables_paginate .paginate_button { background-color: #1e293b !important; color: #94a3b8 !important; border-color: #334155 !important; }
    .dataTables_wrapper .dataTables_paginate .paginate_button.current { background-color: #3b5998 !important; color: #fff !important; border-color: #3b5998 !important; }
    table.dataTable tbody tr { background-color: transparent !important; }
    table.dataTable.no-footer { border-bottom: none !important; }
    .tiny-scrollbar::-webkit-scrollbar { width: 4px; }
    .tiny-scrollbar::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
    html.dark .tiny-scrollbar::-webkit-scrollbar-thumb { background: #475569; }
</style>

<div class="w-full relative pb-16">
    
    <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-6 gap-4">
        <div>
            <h2 class="text-xl font-black text-gray-800 dark:text-slate-100 flex items-center gap-2">
                کاربران <span class="text-blue-500 text-sm cursor-pointer border border-blue-200 dark:border-blue-800 rounded-full w-5 h-5 flex items-center justify-center bg-blue-50 dark:bg-blue-900/30">?</span>
            </h2>
            <p class="text-[11px] font-bold text-gray-500 dark:text-gray-400 mt-1">کنترل، بروزرسانی و سازماندهی حساب‌های کاربری</p>
        </div>
        <button onclick="openUserModal('create')" class="bg-[#3b5998] hover:bg-blue-800 text-white text-xs font-bold px-4 py-2.5 rounded-lg transition flex items-center gap-2 shadow-sm">
            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path></svg>
            ایجاد کاربر
        </button>
    </div>

    <div class="mb-6 bg-gray-50 dark:bg-slate-800/50 p-5 rounded-2xl border border-gray-200 dark:border-slate-700" dir="rtl">
        <label class="block text-sm font-black text-gray-700 dark:text-gray-200 mb-3 flex items-center gap-2">
            <svg class="w-5 h-5 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2"></path></svg>
            انتخاب سرور جهت مدیریت
        </label>
        <select id="target_server_id" class="w-full md:w-1/2 border-2 border-gray-200 dark:border-slate-600 p-3 rounded-xl outline-none focus:border-blue-500 bg-white dark:bg-slate-700 dark:text-white text-sm font-bold shadow-sm transition" onchange="onServerChange()">
            <?php if(empty($serversList)): ?>
                <option value="" disabled selected>هیچ سروری تعریف نشده است!</option>
            <?php else: ?>
                <?php foreach($serversList as $index => $srv): ?>
                    <option value="<?php echo $srv['id']; ?>" <?php echo $index === 0 ? 'selected' : ''; ?>><?php echo htmlspecialchars($srv['name']); ?> (<?php echo htmlspecialchars($srv['url']); ?>)</option>
                <?php endforeach; ?>
            <?php endif; ?>
        </select>
    </div>

    <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
        <div class="bg-white dark:bg-slate-800 rounded-xl border border-gray-200 dark:border-slate-700 p-5 flex justify-between items-center shadow-sm">
            <span class="text-xs font-bold text-gray-800 dark:text-slate-200 flex items-center gap-2">
                <span class="w-2.5 h-2.5 rounded-full bg-emerald-500 shadow-[0_0_8px_rgba(16,185,129,0.6)] animate-pulse"></span> کاربران آنلاین
            </span>
            <span class="text-3xl font-black text-gray-800 dark:text-slate-100" id="sum_online">-</span>
        </div>
        <div class="bg-white dark:bg-slate-800 rounded-xl border border-gray-200 dark:border-slate-700 p-5 flex justify-between items-center shadow-sm">
            <span class="text-xs font-bold text-gray-800 dark:text-slate-200 flex items-center gap-2">
                <svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg> 
                کاربران فعال
            </span>
            <span class="text-3xl font-black text-gray-800 dark:text-slate-100" id="sum_active">-</span>
        </div>
        <div class="bg-white dark:bg-slate-800 rounded-xl border border-gray-200 dark:border-slate-700 p-5 flex justify-between items-center shadow-sm">
            <span class="text-xs font-bold text-gray-800 dark:text-slate-200 flex items-center gap-2">
                <svg class="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"></path></svg> 
                کل کاربران
            </span>
            <span class="text-3xl font-black text-gray-800 dark:text-slate-100" id="sum_total">-</span>
        </div>
    </div>

    <div class="flex flex-wrap md:flex-nowrap gap-3 mb-4 items-center">
        <div class="relative w-full md:w-[350px]">
            <svg class="absolute left-3 top-2.5 w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
            <input type="text" id="customPsgSearch" placeholder="جستجو..." class="w-full bg-gray-100 dark:bg-slate-800/50 border border-gray-200 dark:border-slate-700 text-gray-700 dark:text-gray-200 rounded-lg pl-9 pr-4 py-2 text-xs outline-none focus:ring-1 focus:ring-[#3b5998] transition">
        </div>
        
        <div class="flex gap-2">
            <button onclick="openAdvSearchModal()" class="p-2 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg text-gray-500 hover:bg-gray-50 dark:hover:bg-slate-700 transition" title="جستجوی پیشرفته">
                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"></path></svg>
            </button>
            
            <div class="relative bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg flex dropdown-wrapper">
                <button onclick="loadPsgUsers()" class="p-2 text-gray-500 hover:bg-gray-50 dark:hover:bg-slate-700 transition border-l border-gray-200 dark:border-slate-700" title="بروزرسانی">
                    <svg id="refresh_icon_svg" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path></svg>
                </button>
                <button onclick="toggleMenu('refresh_dropdown')" class="p-2 text-gray-500 hover:bg-gray-50 dark:hover:bg-slate-700 transition relative">
                    <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
                </button>
                
                <div id="refresh_dropdown" class="dropdown-menu hidden absolute top-10 right-0 w-48 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-xl shadow-xl z-50 text-[11px] font-bold py-1">
                    <div class="px-4 py-2 text-gray-400 border-b border-gray-100 dark:border-slate-700">رفرش خودکار<br><span id="current_refresh_lbl" class="font-normal text-[10px]">خاموش</span></div>
                    <button onclick="setRefresh(0)" class="w-full text-right px-4 py-2 hover:bg-gray-50 dark:hover:bg-slate-700 text-gray-700 dark:text-gray-200">فقط دستی</button>
                    <button onclick="setRefresh(5)" class="w-full text-right px-4 py-2 hover:bg-gray-50 dark:hover:bg-slate-700 text-gray-700 dark:text-gray-200">هر ۵ ثانیه</button>
                    <button onclick="setRefresh(15)" class="w-full text-right px-4 py-2 hover:bg-gray-50 dark:hover:bg-slate-700 text-gray-700 dark:text-gray-200">هر ۱۵ ثانیه</button>
                </div>
            </div>
        </div>
    </div>

    <div class="bg-white dark:bg-slate-800 rounded-xl border border-gray-200 dark:border-slate-700 overflow-visible shadow-sm">
        <div id="users_loading" class="py-16 text-center">
            <div class="inline-block animate-spin w-6 h-6 border-2 border-[#3b5998] border-t-transparent rounded-full mb-3"></div>
            <p class="text-xs font-bold text-gray-500">در حال دریافت اطلاعات سرور...</p>
        </div>

        <div id="users_error" class="hidden py-8 text-center text-rose-500 font-bold text-sm"></div>

        <div id="users_table_container" class="hidden w-full overflow-x-auto custom-scrollbar">
            <table id="psgUsersTable" class="w-full text-left" dir="ltr">
                <thead>
                    <tr class="text-[11px] text-gray-500 border-b border-gray-200 dark:border-slate-700">
                        <th class="px-4 py-3 font-normal min-w-[200px] chk-col-th"><input type="checkbox" id="selectAllCheckbox" onclick="toggleSelectAll()" class="rounded border-gray-300 mr-2 text-blue-600 focus:ring-blue-500 cursor-pointer"> Username</th>
                        <th class="px-4 py-3 font-normal">Status / Expire</th>
                        <th class="px-4 py-3 font-normal min-w-[250px]">Data Usage</th>
                        <th class="px-2 py-3 font-normal text-right min-w-[120px]"></th>
                    </tr>
                </thead>
                <tbody id="psg_users_body" class="text-sm divide-y divide-gray-100 dark:divide-slate-700/50"></tbody>
            </table>
        </div>
    </div>

    <div id="bulk_action_bar" class="fixed bottom-6 left-1/2 transform -translate-x-1/2 bg-gray-900 dark:bg-slate-800 text-white px-5 py-3 rounded-2xl shadow-[0_10px_40px_rgba(0,0,0,0.3)] flex items-center gap-4 transition-all duration-300 translate-y-24 opacity-0 z-50 border border-gray-700 dark:border-slate-600">
        <span class="text-xs font-bold bg-gray-800 dark:bg-slate-700 px-3 py-1.5 rounded-lg flex items-center gap-2">
            <span id="bulk_count" class="bg-blue-600 px-1.5 rounded text-white">0</span> انتخاب شده
        </span>
        <div class="h-6 w-px bg-gray-700 dark:bg-slate-600"></div>
        <button onclick="executeBulk('active')" class="text-xs font-bold text-gray-300 hover:text-emerald-400 transition flex items-center gap-1.5">فعال‌سازی</button>
        <button onclick="executeBulk('disabled')" class="text-xs font-bold text-gray-300 hover:text-rose-400 transition flex items-center gap-1.5">مسدود</button>
        <button onclick="executeBulk('reset')" class="text-xs font-bold text-gray-300 hover:text-amber-400 transition flex items-center gap-1.5">ریست حجم</button>
        <div class="h-6 w-px bg-gray-700 dark:bg-slate-600"></div>
        <button onclick="executeBulk('delete')" class="text-xs font-bold text-rose-500 hover:text-rose-400 transition flex items-center gap-1.5">حذف کامل</button>
    </div>
</div>

<div id="advSearchModal" class="fixed inset-0 bg-black/60 hidden items-center justify-center z-[120] p-4 backdrop-blur-sm">
    <div class="bg-white dark:bg-slate-800 rounded-2xl max-w-md w-full shadow-2xl relative flex flex-col" dir="ltr">
        <div class="p-5 border-b border-gray-100 dark:border-slate-700 flex justify-between items-center">
            <h2 class="text-base font-black text-gray-800 dark:text-slate-100 flex items-center gap-2">
                <svg class="w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
                Advanced Search
            </h2>
            <button onclick="$('#advSearchModal').removeClass('flex').addClass('hidden');" class="text-gray-400 hover:text-gray-700 dark:hover:text-white transition">
                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
            </button>
        </div>

        <div class="p-6 space-y-6 overflow-y-auto">
            <div>
                <h3 class="text-sm font-bold text-gray-800 dark:text-gray-200 mb-1">Search mode</h3>
                <p class="text-[10px] text-gray-500 mb-3">Choose how the main search field should be interpreted.</p>
                <div class="grid grid-cols-2 gap-3">
                    <label class="border border-blue-500 bg-blue-50 dark:bg-blue-900/20 p-3 rounded-xl cursor-pointer relative" id="smode_user_box">
                        <input type="radio" name="adv_search_mode" value="username" checked class="hidden" onchange="updateSearchModeUI()">
                        <div class="flex justify-between items-start mb-1">
                            <span class="text-xs font-bold text-blue-800 dark:text-blue-300">Username and Notes</span>
                            <div class="w-3 h-3 rounded-full bg-blue-600 shadow-sm" id="smode_user_dot"></div>
                        </div>
                        <p class="text-[9px] text-gray-500 dark:text-gray-400">Search usernames and notes.</p>
                    </label>
                    <label class="border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-800 p-3 rounded-xl cursor-pointer relative" id="smode_proto_box">
                        <input type="radio" name="adv_search_mode" value="protocol" class="hidden" onchange="updateSearchModeUI()">
                        <div class="flex justify-between items-start mb-1">
                            <span class="text-xs font-bold text-gray-700 dark:text-gray-300">Protocol Data</span>
                            <div class="w-3 h-3 rounded-full bg-gray-200 dark:bg-slate-600" id="smode_proto_dot"></div>
                        </div>
                        <p class="text-[9px] text-gray-500 dark:text-gray-400">Search protocol details and configuration data.</p>
                    </label>
                </div>
            </div>

            <div class="border-t border-gray-100 dark:border-slate-700 pt-5">
                <h3 class="text-sm font-bold text-gray-800 dark:text-gray-200 mb-1">Refine results</h3>
                <p class="text-[10px] text-gray-500 mb-4">Use one or more filters to narrow the list.</p>
                
                <div class="space-y-4">
                    <div>
                        <label class="block text-xs font-bold text-gray-600 dark:text-gray-400 mb-1">Status</label>
                        <select id="adv_status" class="w-full border border-gray-200 dark:border-slate-600 p-2.5 rounded-lg outline-none focus:border-blue-500 bg-gray-50 dark:bg-slate-700 dark:text-white text-xs font-bold">
                            <option value="all">All Statuses</option>
                            <option value="active">Active</option>
                            <option value="disabled">Disabled</option>
                            <option value="on_hold">On Hold</option>
                            <option value="expired">Expired</option>
                            <option value="limited">Limited</option>
                        </select>
                    </div>
                    <div>
                        <label class="block text-xs font-bold text-gray-600 dark:text-gray-400 mb-1.5">Group</label>
                        <select id="adv_group" class="w-full border border-gray-200 dark:border-slate-600 p-2.5 rounded-lg outline-none focus:border-blue-500 bg-gray-50 dark:bg-slate-700 dark:text-white text-xs font-bold">
                            <option value="all">Select Group ...</option>
                            </select>
                    </div>
                </div>
            </div>

            <div class="border-t border-gray-100 dark:border-slate-700 pt-5">
                <div class="flex justify-between items-center mb-1">
                    <h3 class="text-sm font-bold text-gray-800 dark:text-gray-200">Table display</h3>
                    <span class="bg-gray-100 dark:bg-slate-700 text-gray-500 dark:text-gray-400 text-[9px] px-2 py-0.5 rounded font-mono">UI ONLY</span>
                </div>
                
                <div class="flex justify-between items-center bg-gray-50 dark:bg-slate-700/50 p-3 rounded-lg border border-gray-100 dark:border-slate-600 mt-3">
                    <div>
                        <h4 class="text-xs font-bold text-gray-700 dark:text-gray-300">Show selection checkbox</h4>
                    </div>
                    <label class="relative inline-flex items-center cursor-pointer">
                        <input type="checkbox" id="adv_show_checkbox" class="sr-only peer" checked>
                        <div class="w-9 h-5 bg-gray-200 peer-focus:outline-none rounded-full peer dark:bg-slate-600 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-blue-600"></div>
                    </label>
                </div>
            </div>
        </div>

        <div class="p-4 border-t border-gray-100 dark:border-slate-700 flex justify-end gap-2 bg-gray-50 dark:bg-slate-800/80 rounded-b-2xl">
            <button onclick="$('#advSearchModal').removeClass('flex').addClass('hidden');" class="px-5 py-2 text-xs font-bold text-gray-600 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition">Cancel</button>
            <button onclick="applyAdvancedFilters()" class="px-6 py-2 text-xs font-bold text-white bg-[#3b5998] hover:bg-blue-800 rounded-lg transition shadow-sm">Apply</button>
        </div>
    </div>
</div>

<div id="qrModal" class="fixed inset-0 bg-black/60 hidden items-center justify-center z-[110] p-4 backdrop-blur-sm">
    <div class="bg-[#f8f9fa] dark:bg-slate-800 rounded-2xl max-w-4xl w-full shadow-2xl relative flex flex-col md:flex-row min-h-[400px] overflow-hidden">
        
        <button onclick="$('#qrModal').removeClass('flex').addClass('hidden');" class="absolute top-4 right-4 text-gray-400 hover:text-gray-700 dark:hover:text-white z-20">
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
        </button>

        <div class="w-full md:w-5/12 bg-[#f8f9fa] dark:bg-slate-800 p-8 flex flex-col items-center justify-center border-b md:border-b-0 md:border-r border-gray-200 dark:border-slate-700 relative">
            <h3 class="absolute top-6 left-6 text-sm font-bold text-gray-800 dark:text-gray-200 flex items-center gap-2" dir="ltr">
                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm14 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1z"></path></svg>
                <span id="qr_modal_title" class="truncate max-w-[200px]"></span>
            </h3>
            <div id="qrcode_wrapper" class="bg-white p-3 rounded-xl shadow-sm mt-8 flex items-center justify-center min-w-[180px] min-h-[180px]"></div>
        </div>

        <div class="w-full md:w-7/12 bg-[#f4f5f7] dark:bg-slate-900/50 p-6 flex flex-col">
            <div class="flex justify-between items-center mb-4 mt-2">
                <h4 class="text-sm font-bold text-gray-700 dark:text-gray-300" dir="ltr">Configurations</h4>
                <button onclick="copyAllConfigsModal()" class="text-xs font-bold text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition flex items-center gap-1" dir="ltr">
                    <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path></svg> Copy All
                </button>
            </div>
            
            <div id="qr_configs_list" class="flex-1 overflow-y-auto tiny-scrollbar space-y-2 pr-2" dir="ltr"></div>
            
            <div id="qr_pagination" class="hidden mt-4 pt-4 border-t border-gray-200 dark:border-slate-700 items-center justify-center gap-3">
                <button onclick="qrPrevPage()" id="qr_btn_prev" class="p-1.5 bg-white dark:bg-slate-700 border border-gray-200 dark:border-slate-600 rounded disabled:opacity-50 transition hover:bg-gray-50"><svg class="w-4 h-4 text-gray-600 dark:text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg></button>
                <span id="qr_page_info" class="text-xs font-bold text-gray-600 dark:text-gray-400 font-mono">1 / 1</span>
                <button onclick="qrNextPage()" id="qr_btn_next" class="p-1.5 bg-white dark:bg-slate-700 border border-gray-200 dark:border-slate-600 rounded disabled:opacity-50 transition hover:bg-gray-50"><svg class="w-4 h-4 text-gray-600 dark:text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg></button>
            </div>
        </div>
    </div>
</div>

<div id="userModal" class="fixed inset-0 bg-black/50 hidden items-center justify-center z-[100] p-4 backdrop-blur-sm">
    <div class="bg-white dark:bg-slate-800 rounded-2xl max-w-4xl w-full shadow-2xl relative flex flex-col max-h-[90vh]">
        <div class="p-5 border-b border-gray-100 dark:border-slate-700 flex justify-between items-center">
            <h2 class="text-base font-black text-gray-800 dark:text-slate-100 flex items-center gap-2">
                <svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path></svg>
                <span id="modal_title_text">ایجاد کاربر جدید</span>
            </h2>
            <button onclick="closeUserModal()" class="text-gray-400 hover:text-gray-700 dark:hover:text-white">
                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
            </button>
        </div>

        <div id="modal_loading_overlay" class="absolute inset-0 bg-white/80 dark:bg-slate-800/80 z-10 flex items-center justify-center hidden">
            <div class="animate-spin w-8 h-8 border-4 border-[#3b5998] border-t-transparent rounded-full"></div>
        </div>

        <div class="flex-1 overflow-y-auto p-5 grid grid-cols-1 md:grid-cols-3 gap-6" dir="rtl">
            <div class="md:col-span-2 space-y-5">
                <div class="grid grid-cols-2 gap-4">
                    <div>
                        <label class="block text-[11px] font-bold text-gray-500 dark:text-gray-400 mb-1.5">نام کاربری (Username)</label>
                        <input type="text" id="modal_username_val" dir="ltr" class="w-full bg-gray-50 dark:bg-slate-700 border border-gray-200 dark:border-slate-600 p-2.5 rounded-lg outline-none focus:border-blue-500 text-sm text-gray-800 dark:text-white font-mono">
                    </div>
                    <div>
                        <label class="block text-[11px] font-bold text-gray-500 dark:text-gray-400 mb-1.5">وضعیت اکانت (Status)</label>
                        <select id="modal_status_val" class="w-full border border-gray-200 dark:border-slate-600 p-2.5 rounded-lg outline-none focus:border-blue-500 bg-white dark:bg-slate-700 dark:text-white text-sm">
                            <option value="active">فعال (Active)</option>
                            <option value="disabled">مسدود (Disabled)</option>
                            <option value="on_hold">در انتظار (On Hold)</option>
                        </select>
                    </div>
                </div>

                <div class="grid grid-cols-3 gap-4">
                    <div>
                        <label class="block text-[11px] font-bold text-gray-500 dark:text-gray-400 mb-1.5">سقف حجم (GB)</label>
                        <input type="number" id="modal_limit_val" step="0.1" min="0" dir="ltr" class="w-full border border-gray-200 dark:border-slate-600 p-2.5 rounded-lg outline-none focus:border-blue-500 bg-gray-50 dark:bg-slate-700 dark:text-white text-sm" placeholder="0 = نامحدود">
                    </div>
                    <div>
                        <label class="block text-[11px] font-bold text-gray-500 dark:text-gray-400 mb-1.5">ریست دوره‌ای حجم</label>
                        <select id="modal_reset_strategy" class="w-full border border-gray-200 dark:border-slate-600 p-2.5 rounded-lg outline-none focus:border-blue-500 bg-white dark:bg-slate-700 dark:text-white text-sm">
                            <option value="no_reset">بدون ریست</option>
                            <option value="day">روزانه</option>
                            <option value="week">هفتگی</option>
                            <option value="month">ماهانه</option>
                            <option value="year">سالانه</option>
                        </select>
                    </div>
                    <div>
                        <label class="block text-[11px] font-bold text-gray-500 dark:text-gray-400 mb-1.5">تاریخ انقضا</label>
                        <input type="datetime-local" id="modal_expire_val" dir="ltr" class="w-full border border-gray-200 dark:border-slate-600 p-2.5 rounded-lg outline-none focus:border-blue-500 bg-gray-50 dark:bg-slate-700 dark:text-white text-[11px]">
                    </div>
                </div>

                <div>
                    <label class="block text-[11px] font-bold text-gray-500 dark:text-gray-400 mb-1.5">یادداشت</label>
                    <textarea id="modal_note_val" rows="2" class="w-full border border-gray-200 dark:border-slate-600 p-2.5 rounded-lg outline-none focus:border-blue-500 bg-gray-50 dark:bg-slate-700 dark:text-white text-sm" placeholder="یادداشت اختیاری..."></textarea>
                </div>

                <div class="border border-gray-200 dark:border-slate-600 rounded-lg">
                    <div class="px-4 py-3 bg-gray-50 dark:bg-slate-700/50 rounded-t-lg">
                        <span class="text-xs font-bold text-gray-700 dark:text-gray-200 flex items-center gap-2">🔒 تنظیمات پروتکل‌ها (Proxies)</span>
                    </div>
                    <div class="p-4 flex flex-wrap gap-3 bg-white dark:bg-slate-800" dir="ltr">
                        <label class="flex items-center gap-1.5 cursor-pointer">
                            <input type="checkbox" name="modal_proxies[]" value="vless" class="text-blue-600 rounded border-gray-300"> <span class="text-xs font-mono text-gray-600 dark:text-gray-300">VLESS</span>
                        </label>
                        <label class="flex items-center gap-1.5 cursor-pointer">
                            <input type="checkbox" name="modal_proxies[]" value="vmess" class="text-blue-600 rounded border-gray-300"> <span class="text-xs font-mono text-gray-600 dark:text-gray-300">VMESS</span>
                        </label>
                        <label class="flex items-center gap-1.5 cursor-pointer">
                            <input type="checkbox" name="modal_proxies[]" value="trojan" class="text-blue-600 rounded border-gray-300"> <span class="text-xs font-mono text-gray-600 dark:text-gray-300">TROJAN</span>
                        </label>
                        <label class="flex items-center gap-1.5 cursor-pointer">
                            <input type="checkbox" name="modal_proxies[]" value="shadowsocks" class="text-blue-600 rounded border-gray-300"> <span class="text-xs font-mono text-gray-600 dark:text-gray-300">SHADOWSOCKS</span>
                        </label>
                    </div>
                </div>
            </div>

            <div class="md:col-span-1 border-r md:border-r-0 md:border-l border-gray-100 dark:border-slate-700 md:pr-6 pr-0 h-full flex flex-col">
                <div class="flex border-b border-gray-200 dark:border-slate-700 mb-3" dir="ltr">
                    <button class="flex-1 pb-2 text-xs font-bold text-[#3b5998] border-b-2 border-[#3b5998]">Groups</button>
                    <button class="flex-1 pb-2 text-xs font-bold text-gray-400">Templates</button>
                </div>
                <div class="flex-1 overflow-y-auto tiny-scrollbar pl-1" id="modal_groups_list" dir="ltr">
                    <div class="text-center text-xs text-gray-400 mt-5">در حال دریافت گروه‌ها...</div>
                </div>
            </div>
        </div>

        <div class="p-4 border-t border-gray-100 dark:border-slate-700 flex justify-end gap-2 bg-gray-50 dark:bg-slate-800/80 rounded-b-2xl">
            <button onclick="closeUserModal()" class="px-5 py-2 text-xs font-bold text-gray-600 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition">انصراف</button>
            <button onclick="submitUserModal()" id="btn_save_modal" class="px-6 py-2 text-xs font-bold text-white bg-[#3b5998] hover:bg-blue-800 rounded-lg transition shadow-sm">ذخیره اطلاعات</button>
        </div>
    </div>
</div>

<script src="/vpnet-panel/assets/js/jquery-3.7.0.min.js"></script>
<script src="/vpnet-panel/assets/js/jquery.dataTables.min.js"></script>

<script>
    let dtPsgUsers = null;
    let masterUserList = []; 
    let selectedUsers = [];
    let autoRefreshTimer = null;
    let allPsgGroups = [];
    let currentModalMode = 'create'; 
    
    let activeQrLinks = []; 
    let currentQrPage = 1;
    const QR_PER_PAGE = 5;

    function getSelectedServerId() {
        return document.getElementById('target_server_id') ? document.getElementById('target_server_id').value : '';
    }

    function onServerChange() {
        loadPsgUsers();
    }

    function formatBytesToGB(bytes) { return bytes ? (bytes / (1024 * 1024 * 1024)).toFixed(2) : 0; }
    function formatBytesExact(bytes) {
        if (!+bytes || bytes <= 0) return '0 B';
        const k = 1024, dm = 2, sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
    }

    function getStatusBadge(status) {
        let icon = `<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"></path></svg>`;
        if (status === 'active') return `<span class="inline-flex items-center gap-1 bg-[#d1fae5] dark:bg-emerald-900/40 text-[#047857] dark:text-emerald-400 px-2 py-0.5 rounded-full text-[10px] font-bold border border-[#a7f3d0] dark:border-emerald-800">${icon} Active</span>`;
        if (status === 'disabled') return `<span class="inline-flex items-center gap-1 bg-gray-100 dark:bg-slate-700 text-gray-500 px-2 py-0.5 rounded-full text-[10px] font-bold border border-gray-200 dark:border-slate-600">Disabled</span>`;
        if (status === 'on_hold') return `<span class="inline-flex items-center gap-1 bg-[#e0e7ff] text-[#1d4ed8] px-2 py-0.5 rounded-full text-[10px] font-bold border border-[#bfdbfe]">On Hold</span>`;
        if (status === 'expired' || status === 'limited') return `<span class="inline-flex items-center gap-1 bg-[#fee2e2] text-[#be123c] px-2 py-0.5 rounded-full text-[10px] font-bold border border-[#fecaca]">${status === 'expired' ? 'Expired' : 'Limited'}</span>`;
        return `<span class="inline-flex items-center gap-1 bg-gray-50 text-gray-600 px-2 py-0.5 rounded-full text-[10px] font-bold border border-gray-200">${status}</span>`;
    }

    // --- مدیریت دراپ‌داون‌ها (بسته شدن هوشمند) ---
    function toggleMenu(id) {
        $('.dropdown-menu').not('#' + id).addClass('hidden'); 
        $('#' + id).toggleClass('hidden');
    }
    
    $(document).on('click', function(e) {
        let $target = $(e.target);
        if (!$target.closest('.dropdown-menu').length && !$target.closest('button[onclick^="toggleMenu"]').length) {
            $('.dropdown-menu').addClass('hidden');
        }
    });

    function setRefresh(seconds) {
        $('#refresh_dropdown').addClass('hidden');
        clearInterval(autoRefreshTimer);
        if (seconds > 0) {
            $('#current_refresh_lbl').text(`هر ${seconds} ثانیه`);
            autoRefreshTimer = setInterval(loadPsgUsers, seconds * 1000);
        } else { $('#current_refresh_lbl').text('خاموش'); }
    }

    // --- واکشی اطلاعات پنهان کاربران با ارسال server_id ---
    function fetchUserConfigs(username, callback) {
        let sId = getSelectedServerId();
        if(!sId) return;

        $.get('pasarguard_api.php?ajax_call=get_user', {username: username, server_id: sId}, function(res) {
            if(res && res.code === 200 && res.data) {
                let u = res.data;
                let linksArr = u.links || u.configs || [];
                let subUrl = u.subscription_url || u.sub_url || '';
                
                if (linksArr.length === 0 && subUrl) {
                    $.get('pasarguard_api.php?ajax_call=get_sub_links', {sub_url: subUrl, server_id: sId}, function(extractedLinks) {
                        u.links = extractedLinks || [];
                        callback(u);
                    }, 'json').fail(function() { callback(u); });
                } else { callback(u); }
            } else { alert('خطا در دریافت مستقیم اطلاعات کاربر از سرور انتخاب شده.'); }
        }, 'json');
    }

    // --- توابع کپی ---
    function copySubLink(username, btnIconId) {
        fetchUserConfigs(username, function(u) {
            let sub = u.subscription_url || u.sub_url;
            if (!sub) { alert('هیچ لینک سابی برای این کاربر ایجاد نشده است.'); return; }
            navigator.clipboard.writeText(sub).then(() => { 
                let tooltip = document.getElementById('tooltip_' + btnIconId);
                if(tooltip) tooltip.innerText = "کپی شد!";
                setTimeout(() => { if(tooltip) tooltip.innerText = "کپی ساب‌اسکریپشن"; }, 1500);
            });
        });
    }

    function copyConfigs(username, type, btnElement) {
        let oldText = btnElement.innerHTML;
        btnElement.innerHTML = `<span class="animate-pulse">استخراج...</span>`;
        fetchUserConfigs(username, function(u) {
            let linksArr = u.links || [];
            if (!linksArr.length) { 
                alert('هیچ کانفیگی برای این کاربر یافت نشد.'); btnElement.innerHTML = oldText; return; 
            }
            let finalOutput = type === 'base64' ? btoa(unescape(encodeURIComponent(linksArr.join('\n')))) : linksArr.join('\n');
            navigator.clipboard.writeText(finalOutput).then(() => {
                btnElement.innerHTML = `<span class="text-emerald-500">کپی شد!</span>`;
                setTimeout(() => { btnElement.innerHTML = oldText; $('.dropdown-menu').addClass('hidden'); }, 1500);
            });
        });
    }

    // --- مودال QR و صفحه‌بندی ---
    function openQrModal(username) {
        $('.dropdown-menu').addClass('hidden');
        $('#qr_modal_title').text(username);
        $('#qr_configs_list').html('<div class="text-center text-gray-500 py-10 text-xs font-bold animate-pulse">در حال استخراج اطلاعات...</div>');
        $('#qrcode_wrapper').html('<div class="animate-spin w-8 h-8 border-4 border-[#3b5998] border-t-transparent rounded-full"></div>');
        $('#qr_pagination').addClass('hidden').removeClass('flex');
        $('#qrModal').removeClass('hidden').addClass('flex');

        fetchUserConfigs(username, function(u) {
            let sub = u.subscription_url || u.sub_url || '';
            activeQrLinks = u.links || []; 
            currentQrPage = 1;

            if (sub) {
                let qrContainer = document.getElementById("qrcode_wrapper");
                qrContainer.innerHTML = "";
                new QRCode(qrContainer, { text: sub, width: 160, height: 160, colorDark : "#1e293b", colorLight : "#ffffff", correctLevel : QRCode.CorrectLevel.M });
            } else {
                $('#qrcode_wrapper').html('<div class="text-xs text-rose-500 font-bold text-center">لینک ساب<br>موجود نیست</div>');
            }

            renderQrConfigsPage();
        });
    }

    function renderQrConfigsPage() {
        let totalPages = Math.ceil(activeQrLinks.length / QR_PER_PAGE) || 1;
        if(currentQrPage > totalPages) currentQrPage = totalPages;
        if(currentQrPage < 1) currentQrPage = 1;

        let start = (currentQrPage - 1) * QR_PER_PAGE;
        let paginatedLinks = activeQrLinks.slice(start, start + QR_PER_PAGE);

        let listHtml = '';
        if(activeQrLinks.length === 0) {
            listHtml = '<div class="text-xs text-rose-500 py-6 text-center font-bold">هیچ کانفیگی یافت نشد.</div>';
            $('#qr_pagination').addClass('hidden').removeClass('flex');
        } else {
            paginatedLinks.forEach(cfg => {
                let name = 'Config', address = '-';
                try {
                    if(cfg.includes('#')) { name = decodeURIComponent(cfg.split('#')[1]); }
                    let match = cfg.match(/@([^:\/?]+)/);
                    if (match && match[1]) { address = match[1]; }
                } catch(e) {}
                let cfgB64 = btoa(unescape(encodeURIComponent(cfg)));
                listHtml += `
                <div class="bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-xl p-3 flex justify-between items-center shadow-sm">
                    <div class="overflow-hidden pr-2">
                        <h5 class="text-[11px] font-bold text-gray-800 dark:text-gray-200 truncate mb-1" title="${name}">${name}</h5>
                        <span class="bg-gray-100 dark:bg-slate-700 text-gray-500 dark:text-gray-400 px-2 py-0.5 rounded-full text-[9px]">${address}</span>
                    </div>
                    <button onclick="copySingleConfig('${cfgB64}', this)" class="shrink-0 p-1.5 text-gray-400 hover:text-blue-600 transition bg-gray-50 dark:bg-slate-700/50 rounded-lg">
                        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path></svg>
                    </button>
                </div>`;
            });
            
            if (totalPages > 1) {
                $('#qr_pagination').removeClass('hidden').addClass('flex');
                $('#qr_page_info').text(`${currentQrPage} / ${totalPages}`);
                $('#qr_btn_prev').prop('disabled', currentQrPage === 1);
                $('#qr_btn_next').prop('disabled', currentQrPage === totalPages);
            } else {
                $('#qr_pagination').addClass('hidden').removeClass('flex');
            }
        }
        $('#qr_configs_list').html(listHtml);
    }

    function qrNextPage() { currentQrPage++; renderQrConfigsPage(); }
    function qrPrevPage() { currentQrPage--; renderQrConfigsPage(); }

    function copySingleConfig(b64Config, btnElement) {
        let configStr = decodeURIComponent(escape(atob(b64Config)));
        navigator.clipboard.writeText(configStr).then(() => {
            let original = btnElement.innerHTML;
            btnElement.innerHTML = `<span class="text-[10px] text-emerald-600 font-bold px-1">کپی شد</span>`;
            setTimeout(() => { btnElement.innerHTML = original; }, 1500);
        });
    }

    function copyAllConfigsModal() {
        if(activeQrLinks.length > 0) { navigator.clipboard.writeText(activeQrLinks.join('\n')).then(() => { alert('تمام کانفیگ‌ها کپی شدند.'); }); } 
        else { alert('هیچ کانفیگی وجود ندارد.'); }
    }

    // --- توابع جستجوی پیشرفته ---
    function updateSearchModeUI() {
        let mode = $('input[name="adv_search_mode"]:checked').val();
        if(mode === 'username') {
            $('#smode_user_box').removeClass('border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-800').addClass('border-blue-500 bg-blue-50 dark:bg-blue-900/20');
            $('#smode_proto_box').addClass('border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-800').removeClass('border-blue-500 bg-blue-50 dark:bg-blue-900/20');
            $('#smode_user_dot').addClass('bg-blue-600').removeClass('bg-gray-200 dark:bg-slate-600');
            $('#smode_proto_dot').removeClass('bg-blue-600').addClass('bg-gray-200 dark:bg-slate-600');
        } else {
            $('#smode_proto_box').removeClass('border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-800').addClass('border-blue-500 bg-blue-50 dark:bg-blue-900/20');
            $('#smode_user_box').addClass('border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-800').removeClass('border-blue-500 bg-blue-50 dark:bg-blue-900/20');
            $('#smode_proto_dot').addClass('bg-blue-600').removeClass('bg-gray-200 dark:bg-slate-600');
            $('#smode_user_dot').removeClass('bg-blue-600').addClass('bg-gray-200 dark:bg-slate-600');
        }
    }

    function openAdvSearchModal() {
        let sId = getSelectedServerId();
        if(!sId) { alert("ابتدا سرور را انتخاب کنید."); return; }

        $('#advSearchModal').removeClass('hidden').addClass('flex');
        
        $.get('pasarguard_api.php?ajax_call=groups&server_id=' + sId, function(res) {
            allPsgGroups = Array.isArray(res) ? res : (res.groups || res.data || []);
            let html = '<option value="all">Select Group ...</option>';
            allPsgGroups.forEach(g => {
                let gId = g.id !== undefined ? g.id : (g.value || '');
                let gName = g.name || g.title || `Group ${gId}`;
                html += `<option value="${gId}">${gName}</option>`;
            });
            $('#adv_group').html(html);
        }, 'json').fail(function() {
            $('#adv_group').html('<option value="all">خطا در دریافت گروه‌ها از سرور</option>');
        });
    }

    function applyAdvancedFilters() {
        let statusFilter = $('#adv_status').val() || 'all';
        let groupFilter = $('#adv_group').val() || 'all';
        let showCheckboxes = $('#adv_show_checkbox').is(':checked');

        let filteredUsers = masterUserList;

        if (statusFilter !== 'all') {
            filteredUsers = filteredUsers.filter(u => u.status === statusFilter);
        }

        if (groupFilter !== 'all') {
            filteredUsers = filteredUsers.filter(u => {
                if (u.group_ids && Array.isArray(u.group_ids) && u.group_ids.includes(parseInt(groupFilter))) return true;
                if (u.groups && Array.isArray(u.groups) && u.groups.some(g => g.id == groupFilter || g.value == groupFilter)) return true;
                return false;
            });
        }

        renderUserTable(filteredUsers, showCheckboxes);
        $('#advSearchModal').addClass('hidden').removeClass('flex');
    }

    // --- لود و رندر اصلی جدول کاربران ---
    function loadPsgUsers() {
        let sId = getSelectedServerId();
        if(!sId) return;

        $('#refresh_icon_svg').addClass('animate-spin');
        if (!dtPsgUsers) { $('#users_table_container').addClass('hidden'); $('#users_loading').removeClass('hidden'); }

        $.when(
            $.ajax({ url: 'pasarguard_api.php?ajax_call=users_list&server_id=' + sId, dataType: 'json' }),
            $.ajax({ url: 'pasarguard_api.php?ajax_call=system_stats&server_id=' + sId, dataType: 'json' })
        ).done(function(usersRes, statsRes) {
            $('#refresh_icon_svg').removeClass('animate-spin');
            $('#users_loading').addClass('hidden');

            let uData = usersRes[0]; let sData = statsRes[0];
            if (uData.error) { $('#users_error').html('❌ ' + uData.error).removeClass('hidden'); return; }

            masterUserList = (Array.isArray(uData) ? uData : (uData.users || [])).reverse(); 
            $('#sum_total').text(sData.total_user ?? sData.users_total ?? masterUserList.length);
            $('#sum_active').text(sData.users_active ?? sData.active_users ?? masterUserList.filter(u=>u.status==='active').length);
            $('#sum_online').text(sData.online_users ?? sData.users_online ?? 0);

            applyAdvancedFilters(); 
        }).fail(function() {
            $('#refresh_icon_svg').removeClass('animate-spin');
            $('#users_loading').addClass('hidden');
            $('#users_error').html('❌ خطا در ارتباط با سرور.').removeClass('hidden');
        });
    }

    function renderUserTable(list, showCheckboxes = true) {
        if (dtPsgUsers) { dtPsgUsers.destroy(); }
        let html = '';
        let searchMode = $('input[name="adv_search_mode"]:checked').val() || 'username';

        list.forEach((user, idx) => {
            let limitGB = formatBytesToGB(user.data_limit);
            let usedExact = formatBytesExact(user.used_traffic);
            let percent = (limitGB > 0) ? Math.min(100, Math.round((user.used_traffic / user.data_limit) * 100)) : 0;
            let isOnline = user.online === true || user.status === 'online'; 
            let dotColor = isOnline ? 'bg-emerald-500 shadow-[0_0_5px_rgba(16,185,129,0.5)]' : 'bg-transparent border border-gray-300';
            
            let searchData = "";
            if (searchMode === 'protocol') {
                searchData = Object.keys(user.proxies || {}).join(' ') + " " + (user.inbounds ? Object.keys(user.inbounds).join(' ') : '');
            } else {
                searchData = user.note || '';
            }

            html += `
            <tr class="border-b border-gray-100 dark:border-slate-700/50 hover:bg-[#f8fafc] dark:hover:bg-slate-700/30 transition">
                <td class="px-4 py-3 min-w-[200px] chk-col-td">
                    <div class="flex items-center gap-3">
                        <input type="checkbox" class="user-checkbox w-3.5 h-3.5 rounded border-gray-300 text-blue-600 focus:ring-blue-500 cursor-pointer ${showCheckboxes ? '' : 'hidden'}" value="${user.username}" onchange="updateBulkActionBar()">
                        <span class="w-2 h-2 rounded-full ${dotColor} shrink-0"></span>
                        <span class="font-bold text-gray-800 dark:text-slate-200 text-xs">${user.username}</span>
                        <span class="hidden">${searchData}</span>
                    </div>
                </td>
                <td class="px-4 py-3 min-w-[120px]">
                    ${getStatusBadge(user.status)}
                </td>
                <td class="px-4 py-3 min-w-[250px]">
                    <div class="flex flex-col gap-1 w-full max-w-xs">
                        <div class="w-full bg-[#e2e8f0] dark:bg-slate-700 rounded-full h-1 overflow-hidden mt-1">
                            <div class="bg-[#3b5998] h-1 rounded-full" style="width: ${percent}%"></div>
                        </div>
                        <div class="flex justify-between items-center text-[9px] font-bold text-gray-500 mt-1">
                            <span>0 B / ${limitGB > 0 ? limitGB + ' GB' : '∞'}</span>
                            <span class="text-gray-400">Total: ${usedExact}</span>
                        </div>
                    </div>
                </td>
                <td class="px-2 py-3 text-right">
                    <div class="flex justify-end gap-1.5 text-gray-400 items-center">
                        <div class="relative group dropdown-wrapper">
                            <button onclick="copySubLink('${user.username}', 'sub_${idx}')" class="p-1 hover:text-gray-700 dark:hover:text-gray-200 transition bg-blue-600 hover:bg-blue-700 text-white rounded px-2 py-1 shadow-sm opacity-0 group-hover:opacity-100 absolute -top-8 right-0 whitespace-nowrap z-10 font-bold text-[10px]" id="tooltip_sub_${idx}">کپی ساب‌اسکریپشن</button>
                            <button onclick="copySubLink('${user.username}', 'sub_${idx}')" class="p-1 hover:text-gray-700 dark:hover:text-gray-200 transition">
                                <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"></path></svg>
                            </button>
                        </div>
                        
                        <div class="relative inline-block dropdown-wrapper">
                            <button onclick="toggleMenu('copy_configs_${idx}')" class="p-1 hover:text-gray-700 dark:hover:text-gray-200 transition" title="Copy Configs">
                                <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path></svg>
                            </button>
                            <div id="copy_configs_${idx}" class="dropdown-menu hidden absolute right-0 top-6 w-32 bg-white dark:bg-slate-800 border border-gray-100 dark:border-slate-700 rounded-lg shadow-xl z-50 text-left text-[11px] font-bold py-1">
                                <button onclick="copyConfigs('${user.username}', 'links', this)" class="w-full text-left px-4 py-2 hover:bg-gray-50 dark:hover:bg-slate-700 text-gray-700 dark:text-gray-200 flex items-center gap-2"><svg class="w-3 h-3 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M4 6h16M4 12h16M4 18h16"></path></svg> links</button>
                                <button onclick="copyConfigs('${user.username}', 'base64', this)" class="w-full text-left px-4 py-2 hover:bg-gray-50 dark:hover:bg-slate-700 text-gray-700 dark:text-gray-200 flex items-center gap-2"><svg class="w-3 h-3 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path></svg> links (base64)</button>
                            </div>
                        </div>

                        <button onclick="openQrModal('${user.username}')" class="p-1 hover:text-gray-700 dark:hover:text-gray-200 transition" title="Show QR Code">
                            <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm14 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z"></path></svg>
                        </button>
                        
                        <div class="relative inline-block ml-1 dropdown-wrapper">
                            <button onclick="toggleMenu('menu_${idx}')" class="hover:text-gray-700 dark:hover:text-gray-200 transition p-1">
                                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="1.5" fill="currentColor"></circle><circle cx="12" cy="5" r="1.5" fill="currentColor"></circle><circle cx="12" cy="19" r="1.5" fill="currentColor"></circle></svg>
                            </button>
                            <div id="menu_${idx}" class="dropdown-menu hidden absolute right-0 top-6 w-40 bg-white dark:bg-slate-800 border border-gray-100 dark:border-slate-700 rounded-lg shadow-xl z-[60] text-left text-[11px] font-bold py-1">
                                <button onclick="openUserModal('edit', '${user.username}')" class="w-full text-left px-4 py-2 hover:bg-gray-50 dark:hover:bg-slate-700 text-gray-700 dark:text-gray-200 flex items-center gap-2"><svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path></svg> ویرایش کاربر</button>
                                <button onclick="actionUserSingle('reset', '${user.username}')" class="w-full text-left px-4 py-2 hover:bg-gray-50 dark:hover:bg-slate-700 text-gray-700 dark:text-gray-200 flex items-center gap-2"><svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path></svg> ریست حجم</button>
                                <div class="border-t border-gray-100 dark:border-slate-700 my-1"></div>
                                <button onclick="actionUserSingle('delete', '${user.username}')" class="w-full text-left px-4 py-2 hover:bg-rose-50 dark:hover:bg-rose-900/20 text-rose-500 flex items-center gap-2"><svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg> حذف کاربر</button>
                            </div>
                        </div>
                    </div>
                </td>
            </tr>`;
        });

        $('#psg_users_body').html(html);
        
        if(showCheckboxes) { $('.chk-col-th, .chk-col-td').removeClass('hidden'); } 
        else { $('.chk-col-th, .chk-col-td').addClass('hidden'); }

        $('#users_table_container').removeClass('hidden');

        dtPsgUsers = $('#psgUsersTable').DataTable({ 
            "ordering": false,
            "pageLength": 50,
            "language": { "emptyTable": "هیچ کاربری یافت نشد." }
        });

        $('#customPsgSearch').off('keyup').on('keyup', function() { dtPsgUsers.search(this.value).draw(); });

        $('#selectAllCheckbox').prop('checked', false);
        updateBulkActionBar();
    }

    // --- توابع عملیات گروهی ---
    function toggleSelectAll() {
        let isChecked = $('#selectAllCheckbox').prop('checked');
        $('.user-checkbox').prop('checked', isChecked);
        updateBulkActionBar();
    }

    function updateBulkActionBar() {
        selectedUsers = [];
        $('.user-checkbox:checked').each(function() { selectedUsers.push($(this).val()); });
        
        if (selectedUsers.length > 0) {
            $('#bulk_count').text(selectedUsers.length);
            $('#bulk_action_bar').removeClass('translate-y-24 opacity-0 pointer-events-none').addClass('translate-y-0 opacity-100');
        } else {
            $('#bulk_action_bar').addClass('translate-y-24 opacity-0 pointer-events-none').removeClass('translate-y-0 opacity-100');
            $('#selectAllCheckbox').prop('checked', false);
        }
    }

    function executeBulk(type) {
        let sId = getSelectedServerId();
        if(!sId) return;

        if (selectedUsers.length === 0) return;
        let msgs = { 'delete': `حذف کامل ${selectedUsers.length} کاربر؟`, 'reset': `ریست حجم ${selectedUsers.length} کاربر؟`, 'active': `فعال‌سازی ${selectedUsers.length} کاربر؟`, 'disabled': `مسدود کردن ${selectedUsers.length} کاربر؟` };
        if (!confirm(msgs[type])) return;
        
        $('#bulk_action_bar').addClass('opacity-50 pointer-events-none');
        $.post('pasarguard_api.php?ajax_call=bulk_action&server_id=' + sId, { bulk_type: type, usernames: selectedUsers }, function(res) {
            $('#bulk_action_bar').removeClass('opacity-50 pointer-events-none');
            if(res && res.status === 'success') { loadPsgUsers(); } else { alert('عملیات با خطا مواجه شد.'); }
        }, 'json');
    }

    function actionUserSingle(actionType, username) {
        $('.dropdown-menu').addClass('hidden');
        selectedUsers = [username];
        executeBulk(actionType);
    }

    // --- مودال ساخت و ویرایش ---
    function loadGroupsForModal() {
        let sId = getSelectedServerId();
        if(!sId) {
            $('#modal_groups_list').html('<div class="text-center text-xs text-amber-500 font-bold mt-5">ابتدا سرور را انتخاب کنید</div>');
            return;
        }

        $.get('pasarguard_api.php?ajax_call=groups&server_id=' + sId, function(res) {
            allPsgGroups = Array.isArray(res) ? res : (res.groups || res.data || []);
            renderGroupsList();
        }, 'json');
    }

    function renderGroupsList() {
        let html = '';
        allPsgGroups.forEach(g => {
            let gId = g.id !== undefined ? g.id : (g.value || '');
            let gName = g.name || g.title || `Group ${gId}`;
            html += `<label class="flex items-center gap-2 p-2 hover:bg-gray-50 dark:hover:bg-slate-700/50 cursor-pointer rounded-lg transition"><input type="checkbox" name="modal_group_ids[]" value="${gId}" class="rounded border-gray-300 text-blue-600"> <span class="text-xs text-gray-700 dark:text-gray-300">${gName}</span></label>`;
        });
        $('#modal_groups_list').html(html || '<div class="text-center text-xs text-gray-400 mt-2">گروهی یافت نشد</div>');
    }

    function openUserModal(mode, username = '') {
        currentModalMode = mode;
        $('.dropdown-menu').addClass('hidden');
        $('#userModal').removeClass('hidden').addClass('flex');
        loadGroupsForModal();

        if(mode === 'create') {
            $('#modal_title_text').text('ایجاد کاربر جدید');
            $('#modal_username_val').val('').prop('readonly', false).removeClass('bg-gray-100 dark:bg-slate-900 cursor-not-allowed text-gray-500');
            $('#modal_status_val').val('active');
            $('#modal_limit_val').val('');
            $('#modal_expire_val').val('');
            $('#modal_note_val').val('');
            $('#modal_reset_strategy').val('no_reset');
            
            $('input[name="modal_proxies[]"]').prop('checked', true); 
            $('input[name="modal_group_ids[]"]').prop('checked', false);
            
            $('#btn_save_modal').text('ایجاد کاربر').removeClass('bg-[#8ca3d4]').addClass('bg-[#3b5998]');
            $('#modal_loading_overlay').addClass('hidden');
        } else {
            $('#modal_title_text').text('ویرایش ' + username);
            $('#modal_username_val').val(username).prop('readonly', true).addClass('bg-gray-100 dark:bg-slate-900 cursor-not-allowed text-gray-500');
            $('#modal_loading_overlay').removeClass('hidden');
            $('#btn_save_modal').text('ذخیره تغییرات').removeClass('bg-[#3b5998]').addClass('bg-[#8ca3d4]');

            fetchUserConfigs(username, function(u) {
                $('#modal_status_val').val(u.status || 'active');
                $('#modal_limit_val').val(formatBytesToGB(u.data_limit));
                $('#modal_note_val').val(u.note || '');
                $('#modal_reset_strategy').val(u.data_limit_reset_strategy || 'no_reset');
                
                if (u.expire) {
                    let d = new Date(u.expire);
                    d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
                    $('#modal_expire_val').val(d.toISOString().slice(0,16));
                } else { $('#modal_expire_val').val(''); }
                
                $('input[name="modal_proxies[]"]').prop('checked', false);
                if (u.proxies) { Object.keys(u.proxies).forEach(p => { $(`input[name="modal_proxies[]"][value="${p}"]`).prop('checked', true); }); }
                
                $('input[name="modal_group_ids[]"]').prop('checked', false);
                if (u.group_ids && Array.isArray(u.group_ids)) { u.group_ids.forEach(gId => { $(`input[name="modal_group_ids[]"][value="${gId}"]`).prop('checked', true); }); }
                if (u.groups && Array.isArray(u.groups)) { u.groups.forEach(g => { $(`input[name="modal_group_ids[]"][value="${g.id || g.value}"]`).prop('checked', true); }); }

                $('#modal_loading_overlay').addClass('hidden');
            });
        }
    }

    function closeUserModal() { $('#userModal').addClass('hidden').removeClass('flex'); }

    function submitUserModal() {
        let sId = getSelectedServerId();
        if(!sId) { alert("لطفاً ابتدا سرور مقصد را انتخاب کنید."); return; }

        let username = $('#modal_username_val').val().trim();
        if(!username) { alert('وارد کردن نام کاربری الزامی است.'); return; }

        let data = {
            username: username, status: $('#modal_status_val').val(),
            data_limit_gb: $('#modal_limit_val').val() || 0,
            expire_date: $('#modal_expire_val').val() ? new Date($('#modal_expire_val').val()).toISOString() : '',
            note: $('#modal_note_val').val(), reset_strategy: $('#modal_reset_strategy').val(),
            proxies: [], group_ids: []
        };
        $('input[name="modal_proxies[]"]:checked').each(function() { data.proxies.push($(this).val()); });
        $('input[name="modal_group_ids[]"]:checked').each(function() { data.group_ids.push(parseInt($(this).val())); });

        let endpoint = currentModalMode === 'create' ? 'create_user' : 'edit_user';
        $('#btn_save_modal').text('در حال پردازش...').attr('disabled', true);

        $.post('pasarguard_api.php?ajax_call=' + endpoint + '&server_id=' + sId, data, function(res) {
            $('#btn_save_modal').text(currentModalMode === 'create' ? 'ایجاد کاربر' : 'ذخیره تغییرات').attr('disabled', false);
            if(res && (res.code === 200 || res.code === 201 || res.status === 'success')) { 
                closeUserModal(); loadPsgUsers(); 
            } else { alert('خطا در ذخیره تغییرات.'); }
        }, 'json');
    }

    $(document).ready(function() { 
        if(document.getElementById('target_server_id') && document.getElementById('target_server_id').value !== '') {
            loadPsgUsers(); 
        }
    });
</script>