<?php
// modules/subscriptions/widgets/scripts.php
if (basename($_SERVER['PHP_SELF']) == 'scripts.php') { die('Access Denied'); }
?>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>

<div id="debug_console" class="hidden my-4 bg-gray-900 border border-gray-700 rounded-2xl shadow-xl overflow-hidden relative mx-6">
    <div class="bg-gray-800 text-gray-300 px-4 py-3 border-b border-gray-700 flex justify-between items-center text-xs font-bold">
        <span class="flex items-center gap-2"><span>🛠</span> گزارش لحظه‌ای سیستم (Debugger)</span>
        <button onclick="$('#debug_console').addClass('hidden')" class="hover:text-white transition">بستن ✕</button>
    </div>
    <div id="debug_log_list" class="p-4 space-y-1.5 h-64 overflow-y-auto custom-scrollbar" dir="ltr"></div>
</div>

<script id="subs_db_data" type="application/json">
    <?php echo json_encode($subscriptions ?? [], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) ?: '[]'; ?>
</script>

<script>
    window.addEventListener('error', function(event) {
        $('#refresh_live_icon').removeClass('animate-spin');
        $('#subs_loading_overlay').addClass('hidden');
        $('#subs_error_box').html('❌ خطای جاوااسکریپت: ' + event.message).removeClass('hidden');
    });

    const SysDebug = {
        log: function(msg) { this.print(`[INFO] ${msg}`, 'text-blue-400'); },
        err: function(msg, raw = null) { 
            $('#debug_console').removeClass('hidden'); 
            this.print(`[ERROR] ${msg}`, 'text-rose-400 font-black'); 
            if(raw) this.print(`[RAW DETAIL] ${raw}`, 'text-rose-300 text-[10px] break-all');
        },
        success: function(msg) { this.print(`[SUCCESS] ${msg}`, 'text-emerald-400'); },
        print: function(text, classes) {
            let time = new Date().toLocaleTimeString('fa-IR');
            $('#debug_log_list').append(`<div class="text-[11px] font-mono mb-1 ${classes}"><span class="text-gray-500">[${time}]</span> ${text}</div>`);
            let consoleElem = document.getElementById('debug_log_list');
            if(consoleElem) consoleElem.scrollTop = consoleElem.scrollHeight;
        }
    };

    window.subsDbList = [];
    window.dtSubs = null;
    window.liveUsersDict = {};
    window.activeQrLinks = []; 
    window.currentQrPage = 1;
    window.QR_PER_PAGE = 5;
    const IS_ADMIN = <?php echo $isAdmin ? 'true' : 'false'; ?>;

    window.addEventListener('DOMContentLoaded', function() {
        if (typeof jQuery === 'undefined' || typeof $ === 'undefined') {
            document.getElementById('subs_loading_overlay').classList.add('hidden');
            document.getElementById('subs_error_box').innerHTML = '❌ کتابخانه jQuery لود نشده است.';
            document.getElementById('subs_error_box').classList.remove('hidden');
            return;
        }

        try {
            let dbData = document.getElementById('subs_db_data').textContent;
            window.subsDbList = JSON.parse(dbData);
            if (!Array.isArray(window.subsDbList)) window.subsDbList = [];
        } catch(e) { window.subsDbList = []; SysDebug.err("خطا در پارس دیتابیس", e.message); }

        if($('#target_server_id').length && $('#target_server_id').val() !== '') {
            loadSubsLive();
        } else {
            $('#subs_loading_overlay').addClass('hidden');
            $('#subs_error_box').html('⚠️ سروری برای دریافت اطلاعات انتخاب نشده است.').removeClass('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 getSelectedServerId() { return document.getElementById('target_server_id') ? document.getElementById('target_server_id').value : ''; }
    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 formatCurrency(input) {
        let value = input.value.replace(/,/g, '').replace(/[^0-9]/g, '');
        if (value !== '') { input.value = Number(value).toLocaleString(); } 
        else { input.value = ''; }
    }

    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' || status === 'online') 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'); 
    }

    function loadSubsLive() {
        try {
            let sId = getSelectedServerId();
            if(!sId) return;

            SysDebug.log(`دریافت لایو سرور ID: ${sId}`);
            $('#refresh_live_icon').addClass('animate-spin');
            $('#subs_table_container').addClass('hidden'); 
            $('#subs_loading_overlay').removeClass('hidden'); 
            $('#subs_error_box').addClass('hidden');

            let filteredDbList = window.subsDbList.filter(item => (item.server_id == sId) || (!item.server_id && sId == 1));

            $.ajax({ 
                url: '../pasarguard/pasarguard_api.php', 
                type: 'GET',
                data: { ajax_call: 'users_list', server_id: sId },
                dataType: 'json',
                timeout: 15000
            }).done(function(uData) {
                try {
                    $('#refresh_live_icon').removeClass('animate-spin');
                    $('#subs_loading_overlay').addClass('hidden');

                    if (uData && uData.error) { 
                        SysDebug.err("خطای API: " + uData.error);
                        $('#subs_error_box').html('❌ ' + uData.error).removeClass('hidden'); 
                        renderSubsTable(filteredDbList);
                        return; 
                    }

                    let usersList = Array.isArray(uData) ? uData : (uData.users || uData.data || []);
                    window.liveUsersDict = {};
                    usersList.forEach(u => {
                        if(u && u.username) { window.liveUsersDict[u.username] = u; }
                    });

                    SysDebug.success(`دیتا با موفقیت دریافت شد.`);
                    renderSubsTable(filteredDbList);
                } catch (e) {
                    SysDebug.err("خطای پردازش جاوااسکریپت", e.message);
                    $('#subs_error_box').html('❌ خطای داخلی جاوااسکریپت.').removeClass('hidden');
                    renderSubsTable(filteredDbList);
                }
            }).fail(function(xhr, status, error) {
                SysDebug.err(`خطای اتصال به سرور: ${status}`, xhr.responseText);
                $('#refresh_live_icon').removeClass('animate-spin');
                $('#subs_loading_overlay').addClass('hidden');
                $('#subs_error_box').html('❌ خطا در برقراری ارتباط با سرور VPN. لود آفلاین انجام شد.').removeClass('hidden');
                renderSubsTable(filteredDbList);
            });
        } catch (e) {
            SysDebug.err("Crash in loadSubsLive", e.message);
            $('#subs_loading_overlay').addClass('hidden');
        }
    }

    function renderSubsTable(dbList) {
        try {
            if ($.fn.DataTable.isDataTable('#subsTable')) {
                $('#subsTable').DataTable().destroy();
            }
            
            let html = '';
            
            if (Array.isArray(dbList)) {
                dbList.forEach((item, idx) => {
                    let uName = item.account_username || 'Unknown';
                    let safeUName = String(uName).replace(/'/g, "\\'"); 
                    let liveData = window.liveUsersDict[uName] || null;
                    
                    let isOnline = false;
                    let statusBadge = `<span class="inline-flex items-center gap-1 bg-rose-50 dark:bg-rose-900/30 text-rose-700 dark:text-rose-400 px-2 py-0.5 rounded-full text-[10px] font-bold border border-rose-200 dark:border-rose-800">حذف شده از سرور</span>`;
                    let expireText = '';
                    let usageHtml = `<span class="text-[9px] text-rose-500 font-bold bg-rose-50 dark:bg-rose-900/30 px-2 py-1 rounded border border-rose-100 dark:border-rose-800">در سرور یافت نشد</span>`;
                    let dotColor = 'bg-transparent border border-gray-300 dark:border-slate-500';
                    
                    let usageStatusVal = 'unused';
                    let remainStatusVal = 'normal';

                    if (liveData) {
                        isOnline = liveData.online === true || liveData.status === 'online' || liveData.status === 'active';
                        dotColor = isOnline ? 'bg-emerald-500 shadow-[0_0_5px_rgba(16,185,129,0.5)]' : 'bg-transparent border border-gray-300';
                        statusBadge = getStatusBadge(liveData.status);
                        expireText = liveData.expire ? "⏳ " + new Date(liveData.expire).toLocaleDateString('fa-IR') : "⏳ نامحدود";
                        
                        let limitGB = formatBytesToGB(liveData.data_limit);
                        let percent = (limitGB > 0) ? Math.min(100, Math.round((liveData.used_traffic / liveData.data_limit) * 100)) : 0;
                        let remainPercent = 100 - percent;

                        // 💡 ۴. اعمال منطق فیلتر "تمام شده"
                        if (liveData.used_traffic > 1048576) { usageStatusVal = 'used'; } 
                        
                        if (liveData.status === 'limited' || remainPercent <= 0 || (limitGB > 0 && percent >= 100)) {
                            remainStatusVal = 'ended';
                        } else if (remainPercent < 20) {
                            remainStatusVal = 'under_20';
                        } else if (remainPercent < 50) {
                            remainStatusVal = 'under_50';
                        }

                        let barClass = remainStatusVal === 'ended' || remainPercent < 20 ? 'bg-rose-500' : (remainPercent < 50 ? 'bg-amber-500' : 'bg-blue-600');

                        usageHtml = `
                        <div class="flex flex-col gap-1 w-full max-w-[200px]">
                            <div class="w-full bg-[#e2e8f0] dark:bg-slate-700 rounded-full h-1 overflow-hidden mt-1">
                                <div class="${barClass} 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>${percent}% (${limitGB > 0 ? limitGB + ' GB' : '∞'})</span>
                                <span class="text-gray-400">Total: ${formatBytesExact(liveData.used_traffic)}</span>
                            </div>
                        </div>`;
                    }

                    // 💡 ۵. نمایش اطلاعات مشتری، تاریخ خرید دقیق و تراز
                    let sellerName = item.seller_name || 'مدیریت';
                    let customerName = item.customer_name ? item.customer_name : 'ثبت نشده';
                    let paidAmount = item.total_paid ? Number(item.total_paid).toLocaleString() : '0';
                    let profitAmount = IS_ADMIN ? (item.total_admin_profit ? Number(item.total_admin_profit).toLocaleString() : '0') : (item.total_profit ? Number(item.total_profit).toLocaleString() : '0');
                    
                    let rawDate = item.sold_at || item.created_at;
                    let soldDateStr = rawDate ? new Date(rawDate).toLocaleDateString('fa-IR', {year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute:'2-digit'}) : '';
                    
                    let sellerHtml = `
                    <div class="flex flex-col items-end gap-1">
                        <span class="text-[10px] font-bold text-gray-700 dark:text-gray-300 flex items-center gap-1 mb-0.5" title="فروشنده"><svg class="w-3 h-3 text-blue-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> ${sellerName}</span>
                        <span class="text-[9px] text-gray-500 bg-gray-50 dark:bg-slate-800 border border-gray-100 dark:border-slate-600 px-1.5 py-0.5 rounded font-mono">مشتری: ${customerName}</span>
                        <div class="flex gap-1">
                            <span class="text-[9px] text-gray-500 bg-gray-50 dark:bg-slate-800 border border-gray-100 dark:border-slate-600 px-1.5 py-0.5 rounded font-mono" title="کل مبلغ پرداختی">تراز: ${paidAmount}</span>
                            <span class="text-[9px] text-emerald-600 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-900/20 border border-emerald-100 dark:border-emerald-800/50 px-1.5 py-0.5 rounded font-mono" title="سود حاصله">سود: ${profitAmount}</span>
                        </div>
                        ${soldDateStr ? `<span class="text-[8px] text-gray-400 font-mono" dir="ltr">${soldDateStr}</span>` : ''}
                    </div>`;
                    
                    let safeItemId = item.id || '';
                    let safeTxId = item.tx_id || '';
                    let safeCustomerName = item.customer_name ? String(item.customer_name).replace(/'/g, "\\'") : '';
                    let safePaidAmount = item.total_paid ? item.total_paid : '';
                    let safeBankId = item.bank_id || '';
                    let safeItemLink = item.config_link ? String(item.config_link).replace(/'/g, "\\'") : '';
                    let planNameHtml = item.plan_name ? `${item.plan_name} (${item.volume}G)` : 'بدون طرح';

                    html += `
                    <tr class="border-b border-gray-100 dark:border-slate-700/50 hover:bg-[#f8fafc] dark:hover:bg-slate-700/30 transition group inv-row">
                        <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-600 cursor-pointer" value="${safeUName}" onchange="updateBulkActionBar()">
                                <span class="w-2 h-2 rounded-full ${dotColor} shrink-0"></span>
                                <div class="flex flex-col">
                                    <span class="font-bold text-gray-800 dark:text-slate-200 text-xs truncate" title="${uName}">${uName}</span>
                                    <span class="text-[9px] text-gray-500 font-bold bg-gray-100 dark:bg-slate-700 px-1 rounded inline-block w-max mt-0.5">${planNameHtml}</span>
                                </div>
                            </div>
                        </td>
                        <td class="px-4 py-3 min-w-[120px]">
                            ${statusBadge}
                            <div class="text-[9px] text-gray-400 mt-1 font-mono tracking-tight">${expireText}</div>
                        </td>
                        <td class="px-4 py-3 min-w-[250px]">${usageHtml}</td>
                        <td class="px-4 py-3 text-right">${sellerHtml}</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="copySubLinkDirect('${safeItemLink}', this)" 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="copySubLinkDirect('${safeItemLink}', this)" 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">
                                        <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="copyConfigsDirect('${safeItemLink}', '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="copyConfigsDirect('${safeItemLink}', '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="openQrModalDirect('${safeUName}', '${safeItemLink}')" 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="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">
                                        <div class="px-3 py-1 text-[9px] text-gray-400 uppercase text-right" dir="rtl">تراز مالی و اشتراک</div>
                                        
                                        <button onclick="openEditSubModal('${safeTxId}', '${safeUName}', '${safeCustomerName}', '${safePaidAmount}', '${safeBankId}')" class="w-full text-right px-4 py-2 hover:bg-amber-50 dark:hover:bg-slate-700 text-amber-600 dark:text-amber-500 flex items-center gap-2" dir="rtl">✏️ ویرایش تراز مالی</button>
                                        <button onclick="openEditDbItem('${safeItemId}', '${safeUName}', '${safeItemLink}')" class="w-full text-right px-4 py-2 hover:bg-blue-50 dark:hover:bg-slate-700 text-gray-700 dark:text-gray-200 flex items-center gap-2" dir="rtl">🔗 ویرایش یوزرنیم/لینک</button>
                                        
                                        <div class="border-t border-gray-100 dark:border-slate-700 my-1"></div>
                                        <div class="px-3 py-1 text-[9px] text-gray-400 uppercase text-right" dir="rtl">سرور VPN</div>
                                        <button onclick="openVpnUserModal('${safeUName}')" 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('active', '${safeUName}')" class="w-full text-left px-4 py-2 hover:bg-emerald-50 dark:hover:bg-emerald-900/20 text-emerald-600 flex items-center gap-2"><div class="w-2 h-2 rounded-full bg-emerald-500"></div> فعال کردن</button>
                                        <button onclick="actionUserSingle('disabled', '${safeUName}')" class="w-full text-left px-4 py-2 hover:bg-orange-50 dark:hover:bg-orange-900/20 text-orange-600 flex items-center gap-2"><div class="w-2 h-2 rounded-full bg-orange-500"></div> مسدود کردن</button>
                                        <button onclick="actionUserSingle('reset', '${safeUName}')" class="w-full text-left px-4 py-2 hover:bg-blue-50 dark:hover:bg-blue-900/20 text-blue-600 flex items-center gap-2">🔄 ریست حجم</button>
                                        <button onclick="actionUserSingle('delete', '${safeUName}')" 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">✖ حذف از سرور</button>
                                    </div>
                                </div>
                            </div>
                        </td>
                        <td class="hidden">${usageStatusVal}</td>
                        <td class="hidden">${remainStatusVal}</td>
                    </tr>`;
                });
            }

            $('#subs_table_body').html(html);
            $('#subs_table_container').removeClass('hidden');

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

            $('#customSubSearch').off('keyup').on('keyup', function() { window.dtSubs.search(this.value).draw(); });
            
            $('#filter_live_usage').off('change').on('change', function() { 
                let v = this.value; 
                window.dtSubs.column(5).search(v === 'all' ? '' : '^' + v + '$', true, false).draw(); 
            });
            
            $('#filter_live_remain').off('change').on('change', function() { 
                let v = this.value; 
                window.dtSubs.column(6).search(v === 'all' ? '' : '^' + v + '$', true, false).draw(); 
            });
            
            $('#selectAllCheckbox').prop('checked', false);
            updateBulkActionBar();
            SysDebug.success("جدول رندر شد.");

        } catch(e) {
            SysDebug.err("خطا در رندر جدول", e.message);
        }
    }

    // 💡 ۷. باز کردن مودال ویرایش تراز مالی
    function openEditSubModal(txId, username, customerName, paidAmount, bankId) {
        $('.dropdown-menu').addClass('hidden');
        if(!txId || txId === 'null') {
            alert('هیچ تراکنشی برای این اشتراک ثبت نشده است!');
            return;
        }
        $('#edit_tx_id').val(txId);
        $('#edit_account_username').val(username);
        $('#edit_customer_name').val(customerName);
        
        let formattedPaid = paidAmount ? Number(paidAmount).toLocaleString() : '';
        $('#edit_paid_amount').val(formattedPaid);
        $('#edit_bank_id').val(bankId);
        
        $('#editSubModal').removeClass('hidden').addClass('flex');
    }

    // ==============================================
    // توابع کپی و QR 
    // ==============================================
    function copySubLinkDirect(link, btn) {
        if (!link || link === 'null' || link.trim() === '') { alert('لینک ساب در دیتابیس موجود نیست.'); return; }
        navigator.clipboard.writeText(link).then(() => { 
            let old = btn.innerHTML;
            btn.innerHTML = "<span class='text-emerald-500 font-bold text-[10px]'>کپی شد!</span>";
            setTimeout(() => { btn.innerHTML = old; }, 1500);
        });
    }

    function copyConfigsDirect(link, type, btnElement) {
        if (!link || link === 'null' || link.trim() === '') { alert('لینک ساب موجود نیست.'); return; }
        let oldText = btnElement.innerHTML;
        btnElement.innerHTML = `<span class="animate-pulse text-[10px]">استخراج...</span>`;
        let sId = getSelectedServerId() || 1;
        
        $.get('../pasarguard/pasarguard_api.php', {ajax_call: 'get_sub_links', sub_url: link, server_id: sId}, function(extractedLinks) {
            let linksArr = extractedLinks || [];
            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 text-[10px]">کپی شد!</span>`;
                setTimeout(() => { btnElement.innerHTML = oldText; $('.dropdown-menu').addClass('hidden'); }, 1500);
            });
        }, 'json').fail(function() { 
            alert('خطا در استخراج کانفیگ‌ها از لینک.'); 
            btnElement.innerHTML = oldText; 
        });
    }

    function openQrModalDirect(username, link) {
        $('.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-blue-600 border-t-transparent rounded-full"></div>');
        $('#qr_pagination').addClass('hidden').removeClass('flex');
        $('#qrModal').removeClass('hidden').addClass('flex');

        if (!link || link === 'null' || link.trim() === '') {
             $('#qrcode_wrapper').html('<div class="text-xs text-rose-500 font-bold text-center">لینک ساب<br>موجود نیست</div>');
             $('#qr_configs_list').html('<div class="text-center text-rose-500 py-10 text-xs font-bold">لینک ساب برای استخراج کانفیگ وجود ندارد.</div>');
             return;
        }

        let sId = getSelectedServerId() || 1;
        let qrContainer = document.getElementById("qrcode_wrapper");
        qrContainer.innerHTML = "";
        new QRCode(qrContainer, { text: link, width: 160, height: 160, colorDark : "#1e293b", colorLight : "#ffffff", correctLevel : QRCode.CorrectLevel.M });

        $.get('../pasarguard/pasarguard_api.php', {ajax_call: 'get_sub_links', sub_url: link, server_id: sId}, function(extractedLinks) {
            window.activeQrLinks = extractedLinks || []; 
            window.currentQrPage = 1;
            renderQrConfigsPage();
        }, 'json').fail(function() { 
            $('#qr_configs_list').html('<div class="text-center text-rose-500 py-10 text-xs font-bold">خطا در دریافت کانفیگ‌ها</div>');
        });
    }

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

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

        let listHtml = '';
        if(window.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(`${window.currentQrPage} / ${totalPages}`);
                $('#qr_btn_prev').prop('disabled', window.currentQrPage === 1);
                $('#qr_btn_next').prop('disabled', window.currentQrPage === totalPages);
            } else {
                $('#qr_pagination').addClass('hidden').removeClass('flex');
            }
        }
        $('#qr_configs_list').html(listHtml);
    }

    function qrNextPage() { window.currentQrPage++; renderQrConfigsPage(); }
    function qrPrevPage() { window.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(window.activeQrLinks.length > 0) { navigator.clipboard.writeText(window.activeQrLinks.join('\n')).then(() => { alert('تمام کانفیگ‌ها کپی شدند.'); }); } 
        else { alert('هیچ کانفیگی وجود ندارد.'); }
    }

    // ==============================================
    // عملیات گروهی و تکی (AJAX)
    // ==============================================
    function updateBulkActionBar() {
        let selected = $('.user-checkbox:checked').length;
        if (selected > 0) { $('#bulk_count').text(selected); $('#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 toggleSelectAll() { let isChecked = $('#selectAllCheckbox').prop('checked'); $('.user-checkbox').prop('checked', isChecked); updateBulkActionBar(); }

    function executeBulk(action) {
        let sId = getSelectedServerId();
        let checkboxes = $('.user-checkbox:checked');
        if (checkboxes.length === 0 || !confirm(`اجرای عملیات '${action}' روی ${checkboxes.length} کاربر در سرور VPN؟`)) return;
        $('#bulk_action_bar').addClass('opacity-50 pointer-events-none'); 
        let users = []; checkboxes.each(function() { users.push($(this).val()); });
        $.post('../pasarguard/pasarguard_api.php', { ajax_call: 'bulk_action', server_id: sId, bulk_type: action, usernames: users }, function(res) {
            $('#bulk_action_bar').removeClass('opacity-50 pointer-events-none'); 
            if (res && res.status === 'success') { alert('ارسال شد'); loadSubsLive(); } else alert('خطا در انجام عملیات.');
        }, 'json').fail(function() { alert('خطا در ارتباط با API'); $('#bulk_action_bar').removeClass('opacity-50 pointer-events-none'); });
    }
    
    function actionUserSingle(actionType, username) {
        $('.dropdown-menu').addClass('hidden');
        let sId = getSelectedServerId();
        if (!confirm(`اجرای عملیات روی سرور اصلی؟`)) return;
        $.post('../pasarguard/pasarguard_api.php', { ajax_call: 'bulk_action', server_id: sId, bulk_type: actionType, usernames: [username] }, function(res) {
            if (res && res.status === 'success') { loadSubsLive(); } else alert('خطا.');
        }, 'json').fail(function() { alert('خطا در ارتباط با API'); });
    }

    function openEditDbItem(id, username, link) {
        $('.dropdown-menu').addClass('hidden'); $('#edit_db_item_id').val(id); $('#edit_db_username').val(username); $('#edit_db_link').val(link);
        updateIframePreview(link); $('#editDbItemModal').removeClass('hidden').addClass('flex');
    }
    function updateIframePreview(url) { document.getElementById('sub_link_preview').src = (url && (url.startsWith('http'))) ? url : 'about:blank'; }

    // ==============================================
    // مودال ویرایش پیشرفته کاربر VPN
    // ==============================================
    function openVpnUserModal(username) {
        $('.dropdown-menu').addClass('hidden'); 
        let sId = getSelectedServerId();
        $('#vpn_modal_username').val(username);
        $('#vpnUserModal').removeClass('hidden').addClass('flex'); 
        $('#vpn_modal_loading').removeClass('hidden');

        $.get('../pasarguard/pasarguard_api.php', {ajax_call: 'groups', server_id: sId}, function(res) {
            let groups = Array.isArray(res) ? res : (res.groups || res.data || []); let html = '';
            groups.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"><input type="checkbox" name="vpn_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>`; });
            $('#vpn_modal_groups_list').html(html);
            
            $.get('../pasarguard/pasarguard_api.php', {ajax_call: 'get_user', username: username, server_id: sId}, function(userRes) {
                if(userRes && userRes.code === 200 && userRes.data) {
                    let u = userRes.data;
                    $('#vpn_modal_status').val(u.status || 'active'); 
                    
                    // تشخیص هوشمند و تنظیم مگابایت/گیگابایت
                    let limitBytes = u.data_limit || 0;
                    if (limitBytes > 0 && limitBytes < 1073741824) {
                        $('#vpn_modal_limit').val(parseFloat((limitBytes / (1024 * 1024)).toFixed(2)));
                        $('#vpn_modal_limit_unit').val('MB');
                    } else {
                        $('#vpn_modal_limit').val(limitBytes ? parseFloat((limitBytes / (1024 * 1024 * 1024)).toFixed(2)) : 0);
                        $('#vpn_modal_limit_unit').val('GB');
                    }
                    
                    $('#vpn_modal_note').val(u.note || ''); 
                    $('#vpn_modal_reset').val(u.data_limit_reset_strategy || 'no_reset');
                    if (u.expire) { let d = new Date(u.expire); d.setMinutes(d.getMinutes() - d.getTimezoneOffset()); $('#vpn_modal_expire').val(d.toISOString().slice(0,16)); } else { $('#vpn_modal_expire').val(''); }
                    $('input[name="vpn_modal_proxies[]"]').prop('checked', false);
                    if (u.proxies) { Object.keys(u.proxies).forEach(p => { $(`input[name="vpn_modal_proxies[]"][value="${p}"]`).prop('checked', true); }); }
                    $('input[name="vpn_modal_group_ids[]"]').prop('checked', false);
                    if (u.group_ids && Array.isArray(u.group_ids)) { u.group_ids.forEach(gId => { $(`input[name="vpn_modal_group_ids[]"][value="${gId}"]`).prop('checked', true); }); }
                    if (u.groups && Array.isArray(u.groups)) { u.groups.forEach(g => { $(`input[name="vpn_modal_group_ids[]"][value="${g.id || g.value}"]`).prop('checked', true); }); }
                }
                $('#vpn_modal_loading').addClass('hidden');
            }, 'json').fail(function() { alert('خطا در دریافت اطلاعات کاربر'); $('#vpnUserModal').addClass('hidden').removeClass('flex'); });
        }, 'json').fail(function() { alert('خطا در دریافت اطلاعات گروه‌ها'); $('#vpnUserModal').addClass('hidden').removeClass('flex'); });
    }

    function closeVpnUserModal() { $('#vpnUserModal').addClass('hidden').removeClass('flex'); }
    
    function submitVpnUserModal() {
        let username = $('#vpn_modal_username').val();
        let sId = getSelectedServerId();
        let data = { ajax_call: 'edit_user', server_id: sId, username: username, status: $('#vpn_modal_status').val(), data_limit_val: $('#vpn_modal_limit').val() || 0, data_limit_unit: $('#vpn_modal_limit_unit').val() || 'GB', expire_date: $('#vpn_modal_expire').val() ? new Date($('#vpn_modal_expire').val()).toISOString() : '', note: $('#vpn_modal_note').val(), reset_strategy: $('#vpn_modal_reset').val(), proxies: [], group_ids: [] };
        $('input[name="vpn_modal_proxies[]"]:checked').each(function() { data.proxies.push($(this).val()); });
        $('input[name="vpn_modal_group_ids[]"]:checked').each(function() { data.group_ids.push(parseInt($(this).val())); });
        
        $('#btn_save_vpn_modal').attr('disabled', true).text('در حال ذخیره...');
        $.post('../pasarguard/pasarguard_api.php', data, function(res) {
            $('#btn_save_vpn_modal').attr('disabled', false).text('ذخیره اطلاعات در سرور');
            if(res && (res.code === 200 || res.status === 'success')) { closeVpnUserModal(); loadSubsLive(); } else { alert('خطا در ذخیره.'); }
        }, 'json').fail(function() { alert('خطا در ارتباط با API'); $('#btn_save_vpn_modal').attr('disabled', false).text('ذخیره اطلاعات در سرور'); });
    }
</script>