<?php
/**
 * OpenVPN | L2TP Bot - Admin Handlers
 * هندلرهای پنل ادمین
 * 
 * This file is included from bot.php and has access to all its variables:
 * $pdo, $credentials, $forceJoin, $support, $tutorials, $orders, $plans, $wallet
 * $chatId, $data, $msgId, $cb
 */

// Import classes (needed for static method calls)
use GemAcc\{Credentials, ForceJoin, Support, Tutorials, Orders, Plans, Wallet, DiscountCode, Avatar};

// لاگ برای دیباگ
logError("bot_admin.php loaded - callback_data: {$data}, chatId: {$chatId}");


if (!function_exists('gemaccAdminHtml')) {
    function gemaccAdminHtml($value): string {
        return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    }
}
if (!function_exists('gemaccAdminTrafficLabel')) {
    function gemaccAdminTrafficLabel(array $row): string {
        $type = $row['traffic_type'] ?? $row['category_traffic_type'] ?? 'unlimited';
        if ($type === 'limited') {
            return 'حجمی ' . (int)($row['traffic_limit_gb'] ?? $row['category_traffic_limit_gb'] ?? 0) . ' گیگ';
        }
        return 'نامحدود';
    }
}

if (!function_exists('gemaccAdminIsStarsOrder')) {
    function gemaccAdminIsStarsOrder(array $order): bool {
        return strtoupper((string)($order['payment_method'] ?? '')) === 'STARS';
    }
}
if (!function_exists('gemaccAdminIsUnpaidStarsOrder')) {
    function gemaccAdminIsUnpaidStarsOrder(array $order): bool {
        return gemaccAdminIsStarsOrder($order) && strtolower((string)($order['payment_status'] ?? '')) !== 'paid';
    }
}
if (!function_exists('gemaccAdminRejectManualStarsAction')) {
    function gemaccAdminRejectManualStarsAction(array $cb): void {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text' => 'پرداخت استارز اتوماتیک است؛ سفارش پرداخت‌نشده نباید دستی تأیید/رد شود یا اخطار فیش فیک بگیرد.',
            'show_alert' => true,
        ]);
    }
}

if (!function_exists('gemaccAdminEnsureProfitColumns')) {
    function gemaccAdminEnsureProfitColumns(PDO $pdo): void {
        try { if (function_exists('gemaccCoreAddColumn')) gemaccCoreAddColumn($pdo, 'plans', 'purchase_price', 'INT NOT NULL DEFAULT 0 AFTER `price`'); else $pdo->exec("ALTER TABLE plans ADD COLUMN purchase_price INT NOT NULL DEFAULT 0 AFTER price"); } catch (Throwable $e) {}
        try { if (function_exists('gemaccCoreAddColumn')) gemaccCoreAddColumn($pdo, 'orders', 'purchase_price', 'INT NOT NULL DEFAULT 0 AFTER `price`'); else $pdo->exec("ALTER TABLE orders ADD COLUMN purchase_price INT NOT NULL DEFAULT 0 AFTER price"); } catch (Throwable $e) {}
    }
}

if (!function_exists('gemaccAdminCatBaseName')) {
    function gemaccAdminCatBaseName(int $m): string {
        $names=[1=>'یک‌ماهه',2=>'دوماهه',3=>'سه‌ماهه',4=>'چهارماهه',5=>'پنج‌ماهه',6=>'شش‌ماهه',7=>'هفت‌ماهه',8=>'هشت‌ماهه',9=>'نه‌ماهه',10=>'ده‌ماهه',11=>'یازده‌ماهه',12=>'یک‌ساله'];
        return $names[$m] ?? ($m . ' ماهه');
    }
}
if (!function_exists('gemaccAdminRenderUsers')) {
    function gemaccAdminRenderUsers(PDO $pdo, int $chatId, int $msgId, int $page = 1): void {
        $page = max(1, $page);
        $limit = 24;
        $offset = ($page - 1) * $limit;

        $txRows = [];
        try {
            $txRows = $pdo->query("SELECT wt.id, wt.user_id, wt.amount, wt.type, wt.status, wt.created_at, COALESCE(NULLIF(u.username,''), NULLIF(u.first_name,''), CONCAT('ID ', wt.user_id)) AS display_name FROM wallet_transactions wt LEFT JOIN users u ON u.id=wt.user_id ORDER BY wt.created_at DESC, wt.id DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC);
        } catch (Throwable $e) { $txRows = []; }

        $topRows = [];
        try {
            $topRows = $pdo->query("SELECT u.id, COALESCE(NULLIF(u.username,''), NULLIF(u.first_name,''), CONCAT('ID ', u.id)) AS display_name, COUNT(o.id) orders_count, COALESCE(SUM(CASE WHEN o.status IN ('DELIVERED','APPROVED','PAID') THEN o.price ELSE 0 END),0) total_spent FROM users u JOIN orders o ON o.user_id=u.id GROUP BY u.id HAVING orders_count > 0 ORDER BY total_spent DESC, orders_count DESC LIMIT 3")->fetchAll(PDO::FETCH_ASSOC);
        } catch (Throwable $e) { $topRows = []; }

        $stmt = $pdo->prepare("SELECT id, username, first_name, last_name, balance, created_at FROM users ORDER BY created_at DESC, id DESC LIMIT {$limit} OFFSET {$offset}");
        $stmt->execute();
        $users = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $txt = "👥 <b>مدیریت کاربران</b>\n";
        $txt .= "━━━━━━━━━━━━━━━━━━━━\n";
        $txt .= "💳 <b>۵ تراکنش آخر کاربران</b>\n";
        if (!$txRows) {
            $txt .= "— تراکنشی ثبت نشده است.\n";
        } else {
            foreach ($txRows as $t) {
                $name = gemaccAdminHtml($t['display_name']);
                $type = gemaccAdminHtml($t['type'] ?? '-');
                $status = gemaccAdminHtml($t['status'] ?? '-');
                $txt .= "• {$name} | " . money((int)$t['amount']) . " | {$type}/{$status}\n";
            }
        }
        $txt .= "\n🏆 <b>۳ کاربر پرخرید</b>\n";
        if (!$topRows) {
            $txt .= "— هنوز خرید موفقی ثبت نشده است.\n";
        } else {
            $rank = 1;
            foreach ($topRows as $u) {
                $name = gemaccAdminHtml($u['display_name']);
                $txt .= "{$rank}) {$name} | 🛒 " . (int)$u['orders_count'] . " | " . money((int)$u['total_spent']) . "\n";
                $rank++;
            }
        }
        $txt .= "\n📋 صفحه {$page} کاربران — دکمه‌ها به ترتیب جدیدترین کاربران هستند.";

        $buttons = [];
        $row = [];
        foreach ($users as $u) {
            $label = trim((string)($u['username'] ?? '')) !== '' ? '@'.$u['username'] : (trim(($u['first_name'] ?? '').' '.($u['last_name'] ?? '')) ?: (string)$u['id']);
            if (mb_strlen($label, 'UTF-8') > 18) $label = mb_substr($label, 0, 17, 'UTF-8') . '…';
            $row[] = ['text' => $label, 'callback_data' => 'ADMIN_USER_' . (int)$u['id']];
            if (count($row) === 4) { $buttons[] = $row; $row = []; }
        }
        if ($row) $buttons[] = $row;
        $nav = [];
        if ($page > 1) $nav[] = ['text' => '⬅️ صفحه قبل', 'callback_data' => 'ADMIN_USERS_PAGE_' . ($page - 1)];
        if (count($users) === $limit) $nav[] = ['text' => 'صفحه بعد ➡️', 'callback_data' => 'ADMIN_USERS_PAGE_' . ($page + 1)];
        if ($nav) $buttons[] = $nav;
        $buttons[] = [['text'=>'🔎 جستجوی کاربر','callback_data'=>'ADMIN_USERS_SEARCH'], ['text'=>'🔄 بروزرسانی','callback_data'=>'ADMIN_USERS_PAGE_'.$page]];
        $buttons[] = [['text'=>'◀️ بازگشت','callback_data'=>'ADMIN']];

        tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>$buttons],JSON_UNESCAPED_UNICODE)]);
    }
}
if (!function_exists('gemaccAdminRenderPlans')) {
    function gemaccAdminRenderPlans(PDO $pdo, int $chatId, int $msgId): void {
        gemaccAdminEnsureProfitColumns($pdo);
        $cats = $pdo->query("SELECT * FROM plan_categories WHERE deleted_at IS NULL ORDER BY months ASC, traffic_type DESC, traffic_limit_gb ASC, display_order ASC, sort_order ASC, id ASC")->fetchAll(PDO::FETCH_ASSOC);
        $plans = $pdo->query("SELECT p.*, pc.name AS category_name, pc.code AS category_code, pc.months AS category_months, pc.traffic_type AS category_traffic_type, pc.traffic_limit_gb AS category_traffic_limit_gb FROM plans p LEFT JOIN plan_categories pc ON pc.id=p.category_id WHERE p.deleted_at IS NULL ORDER BY COALESCE(pc.months,p.months), COALESCE(pc.traffic_type,p.traffic_type) DESC, COALESCE(pc.traffic_limit_gb,p.traffic_limit_gb), p.display_order, p.id")->fetchAll(PDO::FETCH_ASSOC);
        $txt = "💰 <b>مدیریت پلن‌ها</b>\n";
        $txt .= "━━━━━━━━━━━━━━━━━━━━\n";
        $txt .= "این بخش با منطق مینی‌اپ هماهنگ است: دسته پلن، پلن فروش، قیمت، حذف و فعال/غیرفعال‌سازی دسته‌ها.\n\n";
        $txt .= "🗂 <b>دسته‌ها</b>\n";
        if (!$cats) $txt .= "— دسته‌ای ثبت نشده است.\n";
        foreach ($cats as $c) {
            $status = ((int)($c['is_active'] ?? 0) === 1) ? '🟢' : '🔴';
            $txt .= $status . ' #' . (int)$c['id'] . ' | ' . gemaccAdminHtml($c['name']) . ' | ' . gemaccAdminTrafficLabel($c) . "\n";
        }
        $txt .= "\n📦 <b>پلن‌های فروش</b>\n";
        if (!$plans) $txt .= "— پلنی ثبت نشده است.\n";
        foreach (array_slice($plans, 0, 20) as $p) {
            $status = ((int)($p['is_active'] ?? 0) === 1) ? '🟢' : '🔴';
            $users = (int)($p['user_count'] ?: $p['seats'] ?: 1);
            $cat = gemaccAdminHtml($p['category_name'] ?? '-');
            $title = gemaccAdminHtml($p['title'] ?? 'پلن');
            $txt .= $status . ' #' . (int)$p['id'] . " | {$cat} | {$users} کاربر | فروش: " . money((int)$p['price']) . " | خرید: " . money((int)($p['purchase_price'] ?? 0)) . " | سود: " . money(max(0,(int)$p['price']-(int)($p['purchase_price'] ?? 0))) . "\n";
            $txt .= "   {$title}\n";
        }
        if (count($plans) > 20) $txt .= "\n… فقط ۲۰ پلن اول نمایش داده شد. برای مدیریت کامل از مینی‌اپ هم می‌توانید استفاده کنید.\n";

        $buttons = [];
        $buttons[] = [['text'=>'➕ افزودن دسته پلن','callback_data'=>'ADMIN_PLAN_ADD_CATEGORY'], ['text'=>'➕ افزودن پلن فروش','callback_data'=>'ADMIN_PLAN_ADD_PLAN']];
        foreach (array_slice($cats, 0, 12) as $c) {
            $buttons[] = [
                ['text'=>'🗂 #' . (int)$c['id'] . ' ' . (mb_substr((string)$c['name'],0,14,'UTF-8')), 'callback_data'=>'ADMIN_PLAN_CAT_VIEW__'.(int)$c['id']],
                ['text'=>((int)$c['is_active'] ? '🔴 غیرفعال دسته' : '🟢 فعال دسته'), 'callback_data'=>'ADMIN_PLAN_CAT_TOGGLE__'.(int)$c['id']],
            ];
        }
        foreach (array_slice($plans, 0, 12) as $p) {
            $users = (int)($p['user_count'] ?: $p['seats'] ?: 1);
            $buttons[] = [
                ['text'=>'📦 #' . (int)$p['id'] . " | {$users}ک | " . number_format((int)$p['price']), 'callback_data'=>'ADMIN_PLAN_VIEW__'.(int)$p['id']],
                ['text'=>'🗑 حذف', 'callback_data'=>'ADMIN_PLAN_DELETE__'.(int)$p['id']],
            ];
        }
        $buttons[] = [['text'=>'🔄 بروزرسانی','callback_data'=>'ADMIN_PLANS'], ['text'=>'◀️ بازگشت','callback_data'=>'ADMIN']];
        tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>$buttons],JSON_UNESCAPED_UNICODE)]);
    }
}


function gemaccAdminRenderPendingOrdersList($orders, $chatId, $msgId): void {
    if (empty($orders)) {
        $txt = "📋 **سفارشات در انتظار / صف تحویل**\n\n✅ سفارشی در انتظار یا صف تحویل نیست.";
        $buttons = [[['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']]];
    } else {
        $txt = "📋 **سفارشات در انتظار / صف تحویل** (" . count($orders) . " عدد)\n\n";
        $buttons = [];
        foreach ($orders as $o) {
            $userName = $o['first_name'] ?? $o['username'] ?? 'کاربر';
            $durationLabel = Plans::getDurationLabel($o['duration']);
            $txt .= "━━━━━━━━━━━━━━\n";
            $txt .= "🆔 #{$o['id']} | 👤 {$userName}\n";
            $txt .= "🔢 آیدی عددی کاربر: `{$o['user_id']}`\n";
            $txt .= "📦 {$durationLabel} | {$o['requested_seats']} کاربره\n";
            $txt .= "💵 " . money($o['price']) . "\n";
            $txt .= "📌 وضعیت: " . (($o['status'] ?? '') === 'QUEUED' ? 'در صف تحویل' : 'در انتظار تأیید') . "\n";
            if (($o['status'] ?? '') === 'QUEUED') {
                $buttons[] = [
                    ['text' => "🗑 خروج از صف #{$o['id']}", 'callback_data' => "ADMIN_QUEUE_REMOVE__{$o['id']}"],
                ];
            } else {
                $buttons[] = [
                    ['text' => "✅ #{$o['id']}", 'callback_data' => "ADMIN_APPROVE_ORDER__{$o['id']}"],
                    ['text' => "❌ #{$o['id']}", 'callback_data' => "ADMIN_REJECT_ORDER__{$o['id']}"],
                ];
                $buttons[] = [
                    ['text' => "⚠️ اخطار فیش فیک #{$o['id']}", 'callback_data' => "ADMIN_FAKE_RECEIPT_ORDER__{$o['id']}"],
                ];
            }
        }
        $buttons[] = [['text' => '🔄 بروزرسانی', 'callback_data' => 'ADMIN_ORDERS']];
        $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
    }
    tg('editMessageText', [
        'chat_id' => $chatId,
        'message_id' => $msgId,
        'text' => $txt,
        'parse_mode' => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
}

// ═══════════════════ پنل اصلی ادمین ═══════════════════

if ($data === 'ADMIN') {
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => "👑 **پنل مدیریت**\n\nگزینه مورد نظر را انتخاب کنید:",
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(kbAdminPanel(), JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}



// ═══════════════════ مدیریت کاربران و فروشندگان v6 ═══════════════════
if ($data === 'ADMIN_USERS' || $data === 'ADMIN_USERS_TOP' || preg_match('/^ADMIN_USERS_PAGE_\d+$/', $data)) {
    $page = 1;
    if (preg_match('/^ADMIN_USERS_PAGE_(\d+)$/', $data, $m)) $page = max(1, (int)$m[1]);
    gemaccAdminRenderUsers($pdo, (int)$chatId, (int)$msgId, $page);
    exit('OK');
}
if (preg_match('/^ADMIN_USER_\d+$/', $data)) {
    $uid = (int)str_replace('ADMIN_USER_', '', $data);
    $st = $pdo->prepare("SELECT u.*, COALESCE(COUNT(o.id),0) orders_count, COALESCE(SUM(CASE WHEN o.status IN ('DELIVERED','APPROVED','PAID') THEN o.price ELSE 0 END),0) total_spent FROM users u LEFT JOIN orders o ON o.user_id=u.id WHERE u.id=? GROUP BY u.id");
    $st->execute([$uid]); $u = $st->fetch(PDO::FETCH_ASSOC);
    if (!$u) { tg('answerCallbackQuery',['callback_query_id'=>$cb['id'],'text'=>'کاربر یافت نشد','show_alert'=>true]); exit('OK'); }
    $name = trim(($u['first_name'] ?? '') . ' ' . ($u['last_name'] ?? '')) ?: (($u['username'] ?? '') ? '@'.$u['username'] : 'کاربر');
    $txt = "👤 <b>" . gemaccAdminHtml($name) . "</b>\n\n🆔 <code>{$uid}</code>\n💰 موجودی: ".money((int)$u['balance'])."\n🛒 خریدها: ".(int)$u['orders_count']."\n💵 جمع خرید: ".money((int)$u['total_spent'])."\n🔐 نقش ادمین: ".((int)($u['is_admin'] ?? 0) ? 'بله' : 'خیر');
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'➕ افزایش موجودی','callback_data'=>'ADMIN_USER_INC_'.$uid],['text'=>'➖ کاهش موجودی','callback_data'=>'ADMIN_USER_DEC_'.$uid]],[['text'=>'✉️ پیام خصوصی','callback_data'=>'ADMIN_USER_MSG_'.$uid],['text'=>'🎫 ارسال تخفیف','callback_data'=>'ADMIN_USER_DISC_'.$uid]],[['text'=>'🗑 حذف کاربر','callback_data'=>'ADMIN_USER_DEL_'.$uid]],[['text'=>'◀️ کاربران','callback_data'=>'ADMIN_USERS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}
foreach (['ADMIN_USER_INC_'=>'ADMIN_USER_INCREASE','ADMIN_USER_DEC_'=>'ADMIN_USER_DECREASE','ADMIN_USER_MSG_'=>'ADMIN_USER_MESSAGE','ADMIN_USER_DISC_'=>'ADMIN_USER_DISCOUNT'] as $prefix=>$modeName) {
    if (strpos($data, $prefix) === 0) {
        $uid=(int)str_replace($prefix,'',$data); setUserMode($chatId,$modeName,['user_id'=>$uid]);
        $prompt = $modeName==='ADMIN_USER_MESSAGE' ? 'متن پیام خصوصی را ارسال کنید:' : ($modeName==='ADMIN_USER_DISCOUNT' ? 'کد تخفیف را ارسال کنید:' : 'مبلغ را به تومان ارسال کنید:');
        tg('editMessageText',['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$prompt,'reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_USER_'.$uid]]]],JSON_UNESCAPED_UNICODE)]); exit('OK');
    }
}
if (strpos($data, 'ADMIN_USER_DEL_') === 0) {
    $uid=(int)str_replace('ADMIN_USER_DEL_','',$data);
    $pdo->prepare("DELETE FROM users WHERE id=? AND is_admin=0")->execute([$uid]);
    tg('editMessageText',['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>'✅ کاربر حذف شد.','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'◀️ کاربران','callback_data'=>'ADMIN_USERS']]]],JSON_UNESCAPED_UNICODE)]); exit('OK');
}
if ($data === 'ADMIN_RESELLERS') {
    $pdo->exec("CREATE TABLE IF NOT EXISTS resellers (user_id BIGINT NOT NULL PRIMARY KEY, discount_percent DECIMAL(5,2) NOT NULL DEFAULT 0, fixed_discount INT NOT NULL DEFAULT 0, is_active TINYINT(1) NOT NULL DEFAULT 1, notes TEXT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
    $rows=$pdo->query("SELECT r.*,u.username,u.first_name FROM resellers r LEFT JOIN users u ON u.id=r.user_id ORDER BY r.created_at DESC LIMIT 30")->fetchAll(PDO::FETCH_ASSOC);
    $txt="🤝 <b>فروشندگان / همکاری در فروش</b>\n\nدسترسی فروشنده محدود است و فروشنده به عنوان ادمین شناخته نمی‌شود. پیام‌های کاربران فقط برای ادمین‌های واقعی ارسال می‌شود.\n\n";
    foreach($rows as $r){$name=$r['first_name']?:($r['username']?'@'.$r['username']:'کاربر');$txt.="👤 ".gemaccAdminHtml($name)."\n🆔 <code>{$r['user_id']}</code> | درصد: {$r['discount_percent']}٪ | مبلغ ثابت: ".money((int)$r['fixed_discount'])." | ".((int)$r['is_active']?'فعال':'غیرفعال')."\n\n";}
    if(!$rows)$txt.="فروشنده‌ای ثبت نشده است.\n";
    tg('editMessageText',['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'➕ افزودن/ویرایش فروشنده','callback_data'=>'ADMIN_RESELLER_ADD']],[['text'=>'◀️ بازگشت','callback_data'=>'ADMIN']]]],JSON_UNESCAPED_UNICODE)]); exit('OK');
}
if ($data === 'ADMIN_RESELLER_ADD') {
    setUserMode($chatId,'ADMIN_RESELLER_ADD',[]);
    tg('editMessageText',['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>"اطلاعات فروشنده را با این فرمت ارسال کنید:\n`user_id,percent,fixed`\n\nمثال:\n`123456789,5,200000`\n\nبعد از ذخیره، اگر این کاربر قبلاً is_admin=1 بوده باشد، دسترسی ادمین دیتابیسی او صفر می‌شود.",'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_RESELLERS']]]],JSON_UNESCAPED_UNICODE)]); exit('OK');
}

// ═══════════════════ آمار ═══════════════════

if ($data === 'ADMIN_STATS') {
    $salesStats = $orders->getSalesStats();
    $credStats = $credentials->getStats();
    
    $stmt = $pdo->query("SELECT COUNT(*) FROM users");
    $totalUsers = $stmt->fetchColumn();
    
    // دریافت offset برای محاسبه درآمد کمپین
    $salesOffset = (int)getSetting('sales_reset_offset', '0');
    $revenueOffset = (int)getSetting('revenue_reset_offset', '0');
    $lastReset = getSetting('last_sales_reset', '');
    
    gemaccAdminEnsureProfitColumns($pdo);
    $profitRow = $pdo->query("SELECT COALESCE(SUM(CASE WHEN o.status='DELIVERED' THEN COALESCE(NULLIF(o.purchase_price,0), p.purchase_price, 0) ELSE 0 END),0) AS total_cost, COALESCE(SUM(CASE WHEN o.status='DELIVERED' AND DATE(o.delivered_at)=CURDATE() THEN COALESCE(NULLIF(o.purchase_price,0), p.purchase_price, 0) ELSE 0 END),0) AS today_cost FROM orders o LEFT JOIN plans p ON p.id=o.plan_id")->fetch(PDO::FETCH_ASSOC) ?: [];
    $totalCost = (int)($profitRow['total_cost'] ?? 0);
    $todayCost = (int)($profitRow['today_cost'] ?? 0);
    $campaignSales = max(0, ($salesStats['delivered_count'] ?? 0) - $salesOffset);
    $campaignRevenue = max(0, ($salesStats['total_revenue'] ?? 0) - $revenueOffset);
    $campaignNet = max(0, $campaignRevenue - $totalCost);
    $totalNet = max(0, (int)($salesStats['total_revenue'] ?? 0) - $totalCost);
    $todayNet = max(0, (int)($salesStats['today_revenue'] ?? 0) - $todayCost);
    
    $txt = "📊 **آمار کلی**\n\n";
    $txt .= "👥 کاربران: {$totalUsers} نفر\n\n";
    
    $txt .= "💰 **فروش کمپین فعلی:**\n";
    $txt .= "• فروش: {$campaignSales} عدد\n";
    $txt .= "• ورودی مالی: " . money($campaignRevenue) . "\n";
    $txt .= "• درآمد خالص: " . money($campaignNet) . "\n";
    if ($lastReset) $txt .= "• آخرین ریست: {$lastReset}\n";
    $txt .= "\n";
    
    $txt .= "📈 **فروش کل:**\n";
    $txt .= "• کل سفارشات: " . ($salesStats['total_orders'] ?? 0) . "\n";
    $txt .= "• تحویل شده: " . ($salesStats['delivered_count'] ?? 0) . "\n";
    $txt .= "• در انتظار: " . ($salesStats['pending_count'] ?? 0) . "\n";
    $txt .= "• ورودی مالی کل: " . money($salesStats['total_revenue'] ?? 0) . "\n";
    $txt .= "• هزینه خرید کل: " . money($totalCost) . "\n";
    $txt .= "• درآمد خالص کل: " . money($totalNet) . "\n";
    $txt .= "• فروش امروز: " . ($salesStats['today_count'] ?? 0) . "\n";
    $txt .= "• ورودی مالی امروز: " . money($salesStats['today_revenue'] ?? 0) . "\n";
    $txt .= "• درآمد خالص امروز: " . money($todayNet) . "\n\n";
    
    $txt .= "🔐 **اشتراک‌ها:**\n";
    $txt .= "• کل: " . ($credStats['total'] ?? 0) . "\n";
    $txt .= "• فعال: " . ($credStats['active'] ?? 0) . "\n";
    $txt .= "• یک‌ماهه: " . ($credStats['monthly'] ?? 0) . "\n";
    $txt .= "• یک‌ساله: " . ($credStats['yearly'] ?? 0) . "\n";
    $txt .= "• صندلی استفاده شده: " . ($credStats['total_used_seats'] ?? 0) . "\n";
    $txt .= "• صندلی باقی‌مانده: " . ($credStats['total_remaining_seats'] ?? 0) . "\n";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => '🔄 ریست درآمد کمپین', 'callback_data' => 'ADMIN_RESET_INCOME']],
                [['text' => '🔃 بروزرسانی', 'callback_data' => 'ADMIN_STATS']],
                [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']],
            ],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ ریست درآمد ═══════════════════

if ($data === 'ADMIN_RESET_INCOME') {
    // ذخیره offset فعلی
    $salesStats = $orders->getSalesStats();
    
    setSetting('sales_reset_offset', (string)($salesStats['delivered_count'] ?? 0));
    setSetting('revenue_reset_offset', (string)($salesStats['total_revenue'] ?? 0));
    setSetting('last_sales_reset', jdate('Y/m/d H:i'));
    
    answerCbOnceParams([
        'callback_query_id' => $cb['id'],
        'text'              => '✅ درآمد از این لحظه ریست شد!',
        'show_alert'        => true,
    ]);
    
    // رفرش صفحه آمار
    $salesStats = $orders->getSalesStats();
    $credStats = $credentials->getStats();
    $stmt = $pdo->query("SELECT COUNT(*) FROM users");
    $totalUsers = $stmt->fetchColumn();
    $lastReset = getSetting('last_sales_reset', '');
    
    $txt = "📊 **آمار کلی**\n\n";
    $txt .= "👥 کاربران: {$totalUsers} نفر\n\n";
    $txt .= "💰 **فروش کمپین فعلی:**\n";
    $txt .= "• فروش: 0 عدد\n";
    $txt .= "• درآمد: " . money(0) . "\n";
    $txt .= "• آخرین ریست: {$lastReset}\n\n";
    $txt .= "📈 **فروش کل:**\n";
    $txt .= "• تحویل شده: " . ($salesStats['delivered_count'] ?? 0) . "\n";
    $txt .= "• درآمد کل: " . money($salesStats['total_revenue'] ?? 0) . "\n\n";
    $txt .= "🔐 **اشتراک‌ها:** فعال: " . ($credStats['active'] ?? 0) . "\n";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => '🔄 ریست درآمد کمپین', 'callback_data' => 'ADMIN_RESET_INCOME']],
                [['text' => '🔃 بروزرسانی', 'callback_data' => 'ADMIN_STATS']],
                [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']],
            ],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ مدیریت سفارشات ═══════════════════

if ($data === 'ADMIN_ORDERS') {
    $pendingOrders = $orders->getPendingOrders(10);
    gemaccAdminRenderPendingOrdersList($pendingOrders, $chatId, $msgId);
    exit('OK');
}



if (strpos($data, 'ADMIN_QUEUE_REMOVE__') === 0) {
    $orderId = (int)str_replace('ADMIN_QUEUE_REMOVE__', '', $data);
    $order = $orders->getById($orderId);
    if (!$order || ($order['status'] ?? '') !== 'QUEUED') {
        answerCbOnceParams(['callback_query_id'=>$cb['id'],'text'=>'این سفارش در صف تحویل نیست یا یافت نشد.','show_alert'=>true]);
        exit('OK');
    }
    try {
        $orders->cancel($orderId);
        tgSendSafe('sendMessage', ['chat_id'=>$order['user_id'], 'text'=>"🚫 سفارش #{$orderId} از صف تحویل خارج شد.
در صورت نیاز با پشتیبانی تماس بگیرید."]);
        gemaccAdminActionNotify('سفارش از صف تحویل خارج شد', ['شماره سفارش'=>$orderId, 'کاربر'=>$order['user_id'] ?? '-', 'مبلغ'=>isset($order['price']) ? money((int)$order['price']) : '-'], $chatId);
        answerCbOnceParams(['callback_query_id'=>$cb['id'],'text'=>'✅ سفارش از صف خارج شد.','show_alert'=>true]);
    } catch (Throwable $e) {
        answerCbOnceParams(['callback_query_id'=>$cb['id'],'text'=>'❌ خطا در حذف از صف: '.$e->getMessage(),'show_alert'=>true]);
    }
    $pendingOrders = $orders->getPendingOrders(10);
    gemaccAdminRenderPendingOrdersList($pendingOrders, $chatId, $msgId);
    exit('OK');
}


// ═══════════════════ اخطار فیش فیک سفارش - v27.50 fixed callback ═══════════════════
if (strpos($data, 'ADMIN_FAKE_RECEIPT_ORDER__') === 0) {
    $orderId = (int)str_replace('ADMIN_FAKE_RECEIPT_ORDER__', '', $data);
    if ($orderId <= 0) {
        answerCbOnceParams(['callback_query_id'=>$cb['id'],'text'=>'شناسه سفارش نامعتبر است','show_alert'=>true]);
        exit('OK');
    }
    $order = $orders->getById($orderId);
    if ($order && gemaccAdminIsStarsOrder($order)) {
        gemaccAdminRejectManualStarsAction($cb);
        exit('OK');
    }
    $result = function_exists('gemaccMarkFakeReceipt')
        ? gemaccMarkFakeReceipt($pdo, $orderId, (int)$chatId)
        : ['ok'=>false,'error'=>'تابع اخطار فیش فیک در دسترس نیست'];
    answerCbOnceParams([
        'callback_query_id'=>$cb['id'],
        'text'=>!empty($result['ok']) ? (string)($result['message'] ?? 'اخطار ثبت شد') : ('❌ '.(string)($result['error'] ?? 'خطا')),
        'show_alert'=>true,
    ]);
    try {
        if (!empty($result['ok'])) {
            tgSendSafe('sendMessage', [
                'chat_id'=>$chatId,
                'text'=>"⚠️ اخطار فیش فیک برای سفارش #{$orderId} ثبت شد.\nتعداد اخطار کاربر: ".($result['warning_count'] ?? '-')."/3".(!empty($result['blocked']) ? "\n🚫 کاربر مسدود شد." : ''),
            ]);
        }
    } catch (Throwable $ignored) {}
    try { $pendingOrders = $orders->getPendingOrders(10); gemaccAdminRenderPendingOrdersList($pendingOrders, $chatId, $msgId); } catch (Throwable $ignored) {}
    exit('OK');
}

// ═══════════════════ تأیید سفارش (با بررسی idempotency) ═══════════════════
if (strpos($data, 'ADMIN_APPROVE_ORDER__') === 0) {
    $orderId = (int)str_replace('ADMIN_APPROVE_ORDER__', '', $data);
    
    // بررسی وضعیت فعلی سفارش (idempotency)
    $order = $orders->getById($orderId);
    if (!$order) {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '❌ سفارش یافت نشد',
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    if (gemaccAdminIsUnpaidStarsOrder($order)) {
        gemaccAdminRejectManualStarsAction($cb);
        exit('OK');
    }
    if (($order['payment_method'] ?? '') === 'CRYPTO_PLISIO' && ($order['payment_status'] ?? '') !== 'paid') {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => 'این سفارش درگاه Plisio است و فقط بعد از پرداخت موفق خودکار پردازش می‌شود.',
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    
    // اگر قبلاً پردازش شده، خطا نده
    if ($order['status'] !== 'PENDING') {
        $statusLabels = [
            'APPROVED'  => 'قبلاً تأیید شده',
            'REJECTED'  => 'قبلاً رد شده',
            'DELIVERED' => 'قبلاً تحویل داده شده',
            'QUEUED'    => 'در صف انتظار است',
        ];
        $msg = $statusLabels[$order['status']] ?? 'قبلاً پردازش شده';
        
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => "ℹ️ این سفارش {$msg}",
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    
    // تخصیص صندلی، ثبت تحویل و ارسال پیام تلگرام از مسیر واحد production-safe
    $result = function_exists('vpnApproveOrderAndNotify') ? vpnApproveOrderAndNotify($pdo, $orderId, true) : $orders->approve($orderId);

    if (!empty($result['success'])) {
        $notification = $result['notification'] ?? ['telegram_sent'=>true];
        $cashbackAmount = $wallet->applyCashback($order['user_id'], $order['price']);
        if ($cashbackAmount > 0) {
            tgSendSafe('sendMessage', [
                'chat_id'    => $order['user_id'],
                'text'       => "🎁 *کش‌بک ویژه!*\n\n💰 مبلغ " . money($cashbackAmount) . " به کیف پول شما برگشت!\n\n✅ با تشکر از خرید شما 🙏",
                'parse_mode' => 'Markdown',
            ]);
        }

        $userName = $order['first_name'] ?? $order['username'] ?? 'کاربر';
        $adminMsg = "✅ *تحویل موفق سفارش #{$orderId}*\n\n👤 کاربر: {$userName}\n🆔 آیدی: `{$order['user_id']}`\n📦 سرویس: " . Plans::getDurationLabel($order['duration']) . " - {$order['requested_seats']} کاربره\n💵 مبلغ: " . money($order['price']) . "\n📨 نتیجه: سرویس در چت کاربر ارسال شد یا وضعیت ارسال در خط بعد مشخص می‌شود.";
        if (function_exists('vpnNotificationAdminMessage')) {
            $adminMsg .= "\n\n" . vpnNotificationAdminMessage($notification, $orderId);
        }
        if ($cashbackAmount > 0) $adminMsg .= "\n🎁 کش‌بک: " . money($cashbackAmount);

        tgSendSafe('sendMessage', [
            'chat_id'    => $chatId,
            'text'       => $adminMsg,
            'parse_mode' => 'Markdown',
        ]);
        gemaccAdminActionNotify('سفارش تأیید شد و تحویل انجام شد', ['شماره سفارش'=>$orderId, 'کاربر'=>$order['user_id'] ?? '-', 'مبلغ'=>money((int)$order['price']), 'ارسال تلگرام'=>!empty($notification['telegram_sent']) ? 'موفق' : 'ناموفق'], $chatId);

        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => !empty($notification['telegram_sent']) ? '✅ تحویل شد و پیام ارسال شد' : '⚠️ تحویل شد، پیام ارسال نشد',
            'show_alert'        => true,
        ]);
    } elseif (!empty($result['queued'])) {
        gemaccAdminActionNotify('سفارش تأیید شد اما به صف تحویل رفت', ['شماره سفارش'=>$orderId, 'کاربر'=>$order['user_id'] ?? '-', 'مبلغ'=>money((int)$order['price'])], $chatId);
        notifyAdmins(
            "📦 **موجودی کافی نیست**\n\nسفارش #{$orderId} با پرداخت تأیید شد و در صف تحویل قرار گرفت.\n\n📅 مدت: " . Plans::getDurationLabel($order['duration']) . "\n👥 تعداد: {$order['requested_seats']} صندلی\n\nبعد از افزودن اشتراک در همین دسته، سرویس خودکار برای کاربر ارسال می‌شود.",
            [
                'inline_keyboard' => [
                    [['text' => '➕ افزودن اشتراک جدید در همین دسته', 'callback_data' => "ADMIN_ADD_CREDENTIAL_{$order['duration']}"]],
                ],
            ]
        );

        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '📦 موجودی کافی نیست؛ سفارش در صف تحویل قرار گرفت.',
            'show_alert'        => true,
        ]);
    } elseif (!empty($result['already_delivered'])) {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => 'ℹ️ این سفارش قبلاً تحویل شده است',
            'show_alert'        => true,
        ]);
    } else {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '❌ ' . ($result['message'] ?? 'خطا در پردازش'),
            'show_alert'        => true,
        ]);
    }

    // بروزرسانی لیست سفارشات
    $pendingOrders = $orders->getPendingOrders(10);
    
    gemaccAdminRenderPendingOrdersList($pendingOrders, $chatId, $msgId);
    exit('OK');
}

// ═══════════════════ رد سفارش (با بررسی idempotency) ═══════════════════
if (strpos($data, 'ADMIN_REJECT_ORDER__') === 0) {
    $orderId = (int)str_replace('ADMIN_REJECT_ORDER__', '', $data);
    $order = $orders->getById($orderId);
    
    if (!$order) {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '❌ سفارش یافت نشد',
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    
    if (gemaccAdminIsUnpaidStarsOrder($order)) {
        gemaccAdminRejectManualStarsAction($cb);
        exit('OK');
    }

    // بررسی idempotency
    if ($order['status'] !== 'PENDING') {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => 'ℹ️ این سفارش قبلاً پردازش شده',
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    
    if ($orders->reject($orderId)) {
        // اگر پرداخت با کیف پول بوده، استرداد
        if ($order['payment_method'] === 'WALLET') {
            $wallet->refund($order['user_id'], $order['price'], 'استرداد - رد سفارش #' . $orderId);
            
            tg('sendMessage', [
                'chat_id' => $order['user_id'],
                'text'    => "❌ سفارش #{$orderId} رد شد.\n\n💰 مبلغ " . money($order['price']) . " به کیف پول شما برگردانده شد.",
            ]);
        } else {
            tg('sendMessage', [
                'chat_id' => $order['user_id'],
                'text'    => "❌ سفارش #{$orderId} رد شد.\n\nبرای اطلاعات بیشتر با پشتیبانی تماس بگیرید.",
            ]);
        }
        
        // پیام تأیید برای ادمین
        $userName = $order['first_name'] ?? $order['username'] ?? 'کاربر';
        tg('sendMessage', [
            'chat_id'    => $chatId,
            'text'       => "❌ *سفارش #{$orderId} رد شد*\n\n👤 کاربر: {$userName}\n🆔 آیدی: `{$order['user_id']}`\n📦 " . Plans::getDurationLabel($order['duration']) . " - {$order['requested_seats']} کاربره\n💵 " . money($order['price']),
            'parse_mode' => 'Markdown',
        ]);
        gemaccAdminActionNotify('سفارش رد شد', ['شماره سفارش'=>$orderId, 'کاربر'=>$order['user_id'] ?? '-', 'مبلغ'=>money((int)$order['price'])], $chatId);
        
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '✅ سفارش رد شد',
            'show_alert'        => true,
        ]);
    }
    
    // بروزرسانی لیست - با استفاده از ADMIN_ORDERS callback
    $data = 'ADMIN_ORDERS';
    // Fall through to ADMIN_ORDERS handler by not exiting
    goto refresh_orders;
}

refresh_orders:
if ($data === 'ADMIN_ORDERS_REFRESH') {
    // این برای بروزرسانی پس از reject استفاده می‌شود
    $data = 'ADMIN_ORDERS';
}

// ═══════════════════ مدیریت واریزها ═══════════════════

if ($data === 'ADMIN_DEPOSITS') {
    $deposits = $wallet->getPendingDeposits(10);
    
    if (empty($deposits)) {
        $txt = "💳 **درخواست‌های واریز**\n\n✅ درخواستی در انتظار نیست.";
        $buttons = [[['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']]];
    } else {
        $txt = "💳 **درخواست‌های واریز** (" . count($deposits) . " عدد)\n\n";
        $buttons = [];
        
        foreach ($deposits as $d) {
            $userName = $d['first_name'] ?? $d['username'] ?? 'کاربر';
            
            $txt .= "━━━━━━━━━━━━━━\n";
            $txt .= "🆔 #{$d['id']} | 👤 {$userName}\n";
            $txt .= "💵 " . money($d['amount']) . "\n";
            
            $buttons[] = [
                ['text' => "✅ #{$d['id']}", 'callback_data' => "ADMIN_APPROVE_DEPOSIT__{$d['id']}"],
                ['text' => "❌ #{$d['id']}", 'callback_data' => "ADMIN_REJECT_DEPOSIT__{$d['id']}"],
            ];
        }
        
        $buttons[] = [['text' => '🔄 بروزرسانی', 'callback_data' => 'ADMIN_DEPOSITS']];
        $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
    }
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ تأیید واریز (با بررسی idempotency) ═══════════════════
if (strpos($data, 'ADMIN_APPROVE_DEPOSIT__') === 0) {
    $txId = (int)str_replace('ADMIN_APPROVE_DEPOSIT__', '', $data);
    $tx = $wallet->getTransactionById($txId);
    
    if (!$tx) {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '❌ تراکنش یافت نشد',
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    
    // بررسی idempotency
    if ($tx['status'] !== 'PENDING') {
        $statusLabels = [
            'COMPLETED' => 'قبلاً تأیید شده',
            'REJECTED'  => 'قبلاً رد شده',
        ];
        $msg = $statusLabels[$tx['status']] ?? 'قبلاً پردازش شده';
        
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => "ℹ️ این واریز {$msg}",
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    
    $result = $wallet->approveDeposit($txId, $chatId);
    
    if ($result['success']) {
        $bonus = $result['bonus'] ?? 0;
        $totalAmount = $tx['amount'] + $bonus;
        
        $userMsg = "✅ واریز شما تأیید شد!\n\n💰 مبلغ " . money($tx['amount']) . " به کیف پول شما اضافه شد.";
        if ($bonus > 0) {
            $userMsg .= "\n\n🎁 **بونوس ویژه:** " . money($bonus) . " اضافه شد!\n💵 کل شارژ: " . money($totalAmount);
        }
        
        tg('sendMessage', [
            'chat_id'    => $tx['user_id'],
            'text'       => $userMsg,
            'parse_mode' => 'Markdown',
        ]);
        
        // پیام تأیید برای ادمین
        $adminMsg = "✅ *واریز #{$txId} تأیید شد*\n\n🆔 کاربر: `{$tx['user_id']}`\n💵 مبلغ: " . money($tx['amount']);
        if ($bonus > 0) {
            $adminMsg .= "\n🎁 بونوس: " . money($bonus);
        }
        
        tgSendSafe('sendMessage', [
            'chat_id'    => $chatId,
            'text'       => $adminMsg,
            'parse_mode' => 'Markdown',
        ]);
        gemaccAdminActionNotify('درخواست واریز تأیید شد', ['شماره تراکنش'=>$txId, 'کاربر'=>$tx['user_id'] ?? '-', 'مبلغ'=>money((int)$tx['amount']), 'بونوس'=>money((int)$bonus)], $chatId);
        
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '✅ واریز تأیید شد',
            'show_alert'        => true,
        ]);
    } else {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '❌ خطا در تأیید',
            'show_alert'        => true,
        ]);
    }
    
    // بروزرسانی لیست
    $deposits = $wallet->getPendingDeposits(10);
    
    if (empty($deposits)) {
        $txt = "💳 **درخواست‌های واریز**\n\n✅ درخواستی در انتظار نیست.";
        $buttons = [[['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']]];
    } else {
        $txt = "💳 **درخواست‌های واریز** (" . count($deposits) . " عدد)\n\n";
        $buttons = [];
        
        foreach ($deposits as $d) {
            $userName = $d['first_name'] ?? $d['username'] ?? 'کاربر';
            $txt .= "━━━━━━━━━━━━━━\n";
            $txt .= "🆔 #{$d['id']} | 👤 {$userName}\n";
            $txt .= "💵 " . money($d['amount']) . "\n";
            
            $buttons[] = [
                ['text' => "✅ #{$d['id']}", 'callback_data' => "ADMIN_APPROVE_DEPOSIT__{$d['id']}"],
                ['text' => "❌ #{$d['id']}", 'callback_data' => "ADMIN_REJECT_DEPOSIT__{$d['id']}"],
            ];
        }
        
        $buttons[] = [['text' => '🔄 بروزرسانی', 'callback_data' => 'ADMIN_DEPOSITS']];
        $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
    }
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ رد واریز (با بررسی idempotency) ═══════════════════
if (strpos($data, 'ADMIN_REJECT_DEPOSIT__') === 0) {
    $txId = (int)str_replace('ADMIN_REJECT_DEPOSIT__', '', $data);
    $tx = $wallet->getTransactionById($txId);
    
    if (!$tx) {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '❌ تراکنش یافت نشد',
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    
    // بررسی idempotency
    if ($tx['status'] !== 'PENDING') {
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => 'ℹ️ این واریز قبلاً پردازش شده',
            'show_alert'        => true,
        ]);
        exit('OK');
    }
    
    if ($wallet->rejectDeposit($txId, $chatId)) {
        tg('sendMessage', [
            'chat_id' => $tx['user_id'],
            'text'    => "❌ درخواست واریز شما رد شد.\n\nبرای اطلاعات بیشتر با پشتیبانی تماس بگیرید.",
        ]);
        
        // پیام تأیید برای ادمین
        tg('sendMessage', [
            'chat_id'    => $chatId,
            'text'       => "❌ *واریز #{$txId} رد شد*\n\n🆔 کاربر: `{$tx['user_id']}`\n💵 مبلغ: " . money($tx['amount']),
            'parse_mode' => 'Markdown',
        ]);
        gemaccAdminActionNotify('درخواست واریز رد شد', ['شماره تراکنش'=>$txId, 'کاربر'=>$tx['user_id'] ?? '-', 'مبلغ'=>money((int)$tx['amount'])], $chatId);
        
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '✅ واریز رد شد',
            'show_alert'        => true,
        ]);
    }
    
    // بروزرسانی لیست - استفاده مجدد از کد بالا
    $deposits = $wallet->getPendingDeposits(10);
    
    if (empty($deposits)) {
        $txt = "💳 **درخواست‌های واریز**\n\n✅ درخواستی در انتظار نیست.";
        $buttons = [[['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']]];
    } else {
        $txt = "💳 **درخواست‌های واریز** (" . count($deposits) . " عدد)\n\n";
        $buttons = [];
        
        foreach ($deposits as $d) {
            $userName = $d['first_name'] ?? $d['username'] ?? 'کاربر';
            $txt .= "━━━━━━━━━━━━━━\n";
            $txt .= "🆔 #{$d['id']} | 👤 {$userName}\n";
            $txt .= "💵 " . money($d['amount']) . "\n";
            
            $buttons[] = [
                ['text' => "✅ #{$d['id']}", 'callback_data' => "ADMIN_APPROVE_DEPOSIT__{$d['id']}"],
                ['text' => "❌ #{$d['id']}", 'callback_data' => "ADMIN_REJECT_DEPOSIT__{$d['id']}"],
            ];
        }
        
        $buttons[] = [['text' => '🔄 بروزرسانی', 'callback_data' => 'ADMIN_DEPOSITS']];
        $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
    }
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ افزودن اشتراک ═══════════════════

if ($data === 'ADMIN_ADD_CREDENTIAL' || strpos($data, 'ADMIN_ADD_CREDENTIAL_CAT_') === 0 || strpos($data, 'ADMIN_ADD_CREDENTIAL_') === 0) {
    if ($data === 'ADMIN_ADD_CREDENTIAL') {
        $cats = $plans->getActiveCategories();
        $rows = [];
        foreach ($cats as $cat) {
            $traffic = (($cat['traffic_type'] ?? 'unlimited') === 'limited') ? ('حجمی ' . (int)($cat['traffic_limit_gb'] ?? 0) . ' گیگ') : 'نامحدود';
            $rows[] = [['text' => '➕ ' . $cat['name'] . ' - ' . $traffic, 'callback_data' => 'ADMIN_ADD_CREDENTIAL_CAT_' . (int)$cat['id']]];
        }
        if (!$rows) $rows[] = [['text' => 'اول دسته پلن بسازید', 'callback_data' => 'ADMIN_PLANS']];
        $rows[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
        tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>"🔐 **افزودن اشتراک جدید**\n\nدسته دقیق اشتراک را انتخاب کنید:",'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>$rows], JSON_UNESCAPED_UNICODE)]);
    } else {
        if (strpos($data, 'ADMIN_ADD_CREDENTIAL_CAT_') === 0) {
            $categoryId = (int)str_replace('ADMIN_ADD_CREDENTIAL_CAT_', '', $data);
            $st=$pdo->prepare('SELECT * FROM plan_categories WHERE id=? AND is_active=1 AND deleted_at IS NULL LIMIT 1'); $st->execute([$categoryId]); $cat=$st->fetch(PDO::FETCH_ASSOC);
        } else {
            $duration = str_replace('ADMIN_ADD_CREDENTIAL_', '', $data);
            $cat = $plans->getCategoryByCode($duration);
            $categoryId = (int)($cat['id'] ?? 0);
        }
        if (empty($cat)) { answerCbOnce($cb, '❌ دسته پیدا نشد', true); exit('OK'); }
        $serviceType = function_exists('gemaccServiceTypeFromHint') ? gemaccServiceTypeFromHint((string)($cat['service_type'] ?? 'openvpn_l2tp'), (string)($cat['service_name'] ?? $cat['name'] ?? '')) : (in_array(strtolower((string)($cat['service_type'] ?? '')), ['windscribe','expressvpn','v2ray'], true) ? strtolower((string)$cat['service_type']) : 'openvpn_l2tp');
        $trafficLabel = (($cat['traffic_type'] ?? 'unlimited') === 'limited')
            ? ('حجمی ' . (int)($cat['traffic_limit_gb'] ?? 0) . ' گیگ')
            : 'نامحدود';
        if ($serviceType === 'windscribe') $traffic = 'Windscribe';
        elseif ($serviceType === 'expressvpn') $traffic = 'ExpressVPN';
        elseif ($serviceType === 'v2ray') $traffic = 'V2Ray - ' . $trafficLabel;
        else $traffic = $trafficLabel;

        setUserMode($chatId, 'ADMIN_ADD_CREDENTIAL', ['duration' => $cat['code'], 'category_id' => $categoryId]);
        $txt = "🔐 **افزودن اشتراک {$cat['name']} - {$traffic}**

";
        if ($serviceType === 'windscribe') {
            $txt .= "🌀 اکانت Windscribe را فقط تک‌تک ارسال کنید، چون ظرفیت هر اکانت جدا پرسیده می‌شود.

فرمت:
`username:password`

بعد از ارسال، ربات می‌پرسد این اکانت چند دستگاه/کاربر ظرفیت دارد.";
        } elseif ($serviceType === 'v2ray') {
            $txt .= "⚡ متن کامل کانفیگ V2Ray را ارسال کنید. پس از ثبت متن، ربات تصویر QR را می‌خواهد؛ اگر QR ندارید `/skip` بفرستید.

لینک‌های VLESS، VMess، Trojan و سایر کانفیگ‌های متنی سازگار پذیرفته می‌شوند.";
        } elseif ($serviceType === 'expressvpn') {
            $txt .= "🚀 اکانت ExpressVPN را به فرمت زیر ارسال کنید. ثبت تکی یا انبوه خط‌به‌خط قابل استفاده است و ظرفیت طبق دسته/مرحله بعد اعمال می‌شود:
`username:password`

مثال:
`express_user:express_pass`";
        } else {
            $txt .= "📧 اشتراک را به فرمت زیر ارسال کنید. برای OpenVPN/L2TP ثبت تکی و انبوه خط‌به‌خط قابل استفاده است:
`username:password`

مثال:
`openz313:5350`";
        }
        tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_ADD_CREDENTIAL']],[['text'=>'◀️ بازگشت به پنل','callback_data'=>'ADMIN']]]], JSON_UNESCAPED_UNICODE)]);
    }
    exit('OK');
}

// ═══════════════════ مدیریت اشتراک‌ها ═══════════════════

admin_credentials_refresh:
if ($data === 'ADMIN_CREDENTIALS' || isset($GLOBALS['_credentials_refresh'])) {
    $credList = $credentials->getList(10);
    
    if (empty($credList)) {
        $txt = "🔐 **مدیریت اشتراک‌ها**\n\n📦 هیچ اشتراکی ثبت نشده است.";
        $buttons = [
            [['text' => '➕ افزودن اشتراک', 'callback_data' => 'ADMIN_ADD_CREDENTIAL']],
            [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']],
        ];
    } else {
        $txt = "🔐 **مدیریت اشتراک‌ها**\n\n";
        $buttons = [];
        
        foreach ($credList as $c) {
            $durationLabel = Plans::getDurationLabel($c['duration']);
            $remaining = $c['remaining_seats'];
            $sold = ((int)($c['used_seats'] ?? 0) > 0 || (int)($c['is_sold'] ?? 0) > 0 || in_array(strtolower((string)($c['status'] ?? 'available')), ['sold','delivered','assigned','used'], true));
            $status = $sold ? '🛒' : '🟢';
            
            $txt .= "━━━━━━━━━━━━━━\n";
            $txt .= "{$status} #{$c['id']} | {$durationLabel}\n";
            $txt .= "📧 `{$c['email']}`\n";
            $txt .= "👥 وضعیت: " . ($sold ? 'فروخته‌شده' : 'فروخته‌نشده / آماده فروش') . " | باقی‌مانده: {$remaining}/{$c['max_seats']}\n";
            
            $row = [['text' => "👁 #{$c['id']}", 'callback_data' => "ADMIN_CRED_VIEW__{$c['id']}"]];
            
            // فقط اشتراک‌هایی که فروخته نشده‌اند قابل حذف هستند. دکمه خاموش/روشن حذف شد چون در مدیریت موجودی کاربرد عملی نداشت.
            if (!$sold) {
                $row[] = ['text' => "🗑️", 'callback_data' => "ADMIN_CRED_DELETE__{$c['id']}"];
            }
            
            $buttons[] = $row;
        }
        
        $buttons[] = [['text' => '➕ افزودن اشتراک', 'callback_data' => 'ADMIN_ADD_CREDENTIAL']];
        $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
    }
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if (strpos($data, 'ADMIN_CRED_VIEW__') === 0) {
    $credId = (int)str_replace('ADMIN_CRED_VIEW__', '', $data);
    $cred = $credentials->getById($credId);
    
    if (!$cred) {
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '❌ اشتراک یافت نشد', 'show_alert' => true]);
        exit('OK');
    }
    
    $durationLabel = Plans::getDurationLabel($cred['duration']);
    $remaining = $cred['max_seats'] - $cred['used_seats'];
    
    $txt = "🔐 **جزئیات اشتراک #{$credId}**\n\n";
    $txt .= "📧 یوزرنیم:\n`{$cred['email']}`\n\n";
    $txt .= "🔐 رمز عبور:\n`{$cred['password']}`\n\n";
    $txt .= "📅 مدت: {$durationLabel}\n";
    $txt .= "👥 صندلی: {$cred['used_seats']}/{$cred['max_seats']} استفاده شده\n";
    $txt .= "📊 باقی‌مانده: {$remaining}\n";
    $txt .= "⏰ قابل فروش تا: " . ($cred['sellable_until'] ?? '-') . "\n";
    $sold = ((int)($cred['used_seats'] ?? 0) > 0 || (int)($cred['is_sold'] ?? 0) > 0 || in_array(strtolower((string)($cred['status'] ?? 'available')), ['sold','delivered','assigned','used'], true));
    $txt .= "🔘 وضعیت فروش: " . ($sold ? '🛒 فروخته‌شده' : '📦 فروخته‌نشده / آماده فروش') . "\n";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN_CREDENTIALS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if (strpos($data, 'ADMIN_CRED_DISABLE__') === 0 || strpos($data, 'ADMIN_CRED_ENABLE__') === 0) {
    answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => 'دکمه خاموش/روشن حذف شده است', 'show_alert' => true]);
    exit('OK');
}

if (strpos($data, 'ADMIN_CRED_DELETE__') === 0) {
    $credId = (int)str_replace('ADMIN_CRED_DELETE__', '', $data);
    
    // بررسی اینکه فروخته نشده باشه
    $pdo = db();
    $stmt = $pdo->prepare("SELECT used_seats, is_sold, status FROM credentials WHERE id = ?");
    $stmt->execute([$credId]);
    $cred = $stmt->fetch(PDO::FETCH_ASSOC);
    
    if ($cred && ((int)$cred['used_seats'] > 0 || (int)($cred['is_sold'] ?? 0) > 0 || in_array(strtolower((string)($cred['status'] ?? 'available')), ['sold','delivered','assigned','used'], true))) {
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '❌ این اشتراک فروخته شده و قابل حذف نیست', 'show_alert' => true]);
    } else {
        $stmt = $pdo->prepare("DELETE FROM credentials WHERE id = ?");
        $stmt->execute([$credId]);
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '✅ اشتراک حذف شد', 'show_alert' => true]);
    }
    exit('OK');
}

// ═══════════════════ مدیریت پلن‌ها - هماهنگ با مینی‌اپ ═══════════════════
if ($data === 'ADMIN_PLANS') {
    gemaccAdminRenderPlans($pdo, (int)$chatId, (int)$msgId);
    exit('OK');
}
if ($data === 'ADMIN_PLAN_ADD_CATEGORY') {
    setUserMode($chatId, 'ADMIN_ADD_PLAN_CATEGORY', []);
    $txt = "➕ <b>افزودن دسته پلن</b>\n\nفرمت ارسال:\n<code>months,traffic_type,traffic_gb,name,service</code>\n\nservice یکی از این موارد است:\n<code>openvpn_l2tp</code>، <code>windscribe</code>، <code>expressvpn</code> یا <code>v2ray</code>\n\nنمونه V2Ray نامحدود:\n<code>1,unlimited,,یک‌ماهه,v2ray</code>\n\nنمونه V2Ray حجمی ۵۰ گیگ:\n<code>1,limited,50,یک‌ماهه,v2ray</code>";
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_PLANS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}
if ($data === 'ADMIN_PLAN_ADD_PLAN') {
    $cats = $pdo->query("SELECT * FROM plan_categories WHERE deleted_at IS NULL AND is_active=1 ORDER BY months, traffic_type DESC, traffic_limit_gb, id")->fetchAll(PDO::FETCH_ASSOC);
    $rows=[];
    foreach($cats as $c){ $rows[] = [[ 'text'=>'➕ '.gemaccServiceLabelFromRow($c).' | '.($c['name'] ?? $c['code']).' - '.gemaccAdminTrafficLabel($c), 'callback_data'=>'ADMIN_PLAN_ADD_PLAN_CAT__'.(int)$c['id'] ]]; }
    if(!$rows) $rows[] = [[ 'text'=>'اول دسته پلن بسازید', 'callback_data'=>'ADMIN_PLAN_ADD_CATEGORY' ]];
    $rows[] = [[ 'text'=>'◀️ بازگشت', 'callback_data'=>'ADMIN_PLANS' ]];
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>'📦 <b>افزودن پلن فروش</b>\n\nدسته پلن را انتخاب کنید:','parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>$rows],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}
if (strpos($data, 'ADMIN_PLAN_ADD_PLAN_CAT__') === 0) {
    $catId=(int)str_replace('ADMIN_PLAN_ADD_PLAN_CAT__','',$data);
    $st=$pdo->prepare("SELECT * FROM plan_categories WHERE id=? AND deleted_at IS NULL LIMIT 1"); $st->execute([$catId]); $cat=$st->fetch(PDO::FETCH_ASSOC);
    if(!$cat){ answerCbOnce($cb,'دسته یافت نشد',true); exit('OK'); }
    setUserMode($chatId, 'ADMIN_ADD_PLAN_ITEM', ['category_id'=>$catId]);
    $isV2Plan = gemaccServiceTypeFromHint((string)($cat['service_type'] ?? ''), (string)(($cat['service_name'] ?? '').' '.($cat['name'] ?? ''))) === 'v2ray';
    $formatHint = $isV2Plan
        ? "برای V2Ray ظرفیت همیشه ۱ است. فرمت:\n<code>1,price,title</code>\n\nنمونه:\n<code>1,250000,V2Ray یک‌ماهه</code>"
        : "فرمت ارسال:\n<code>user_count,price,title</code>\n\nنمونه:\n<code>1,250000,سرویس یک کاربره</code>";
    $txt = "📦 <b>افزودن پلن فروش برای ".gemaccAdminHtml(gemaccServiceLabelFromRow($cat))." | ".gemaccAdminHtml($cat['name'])." - ".gemaccAdminHtml(gemaccAdminTrafficLabel($cat))."</b>\n\n".$formatHint."\n\nعنوان اختیاری است.";
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_PLANS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}
if (strpos($data, 'ADMIN_PLAN_CAT_VIEW__') === 0) {
    $catId=(int)str_replace('ADMIN_PLAN_CAT_VIEW__','',$data);
    $st=$pdo->prepare("SELECT * FROM plan_categories WHERE id=? AND deleted_at IS NULL LIMIT 1"); $st->execute([$catId]); $cat=$st->fetch(PDO::FETCH_ASSOC);
    if(!$cat){ answerCbOnce($cb,'دسته یافت نشد',true); exit('OK'); }
    $cnt=$pdo->prepare("SELECT COUNT(*) FROM plans WHERE category_id=? AND deleted_at IS NULL"); $cnt->execute([$catId]);
    $txt="🗂 <b>دسته پلن #{$catId}</b>\n\nنام: ".gemaccAdminHtml($cat['name'])."\nکد: <code>".gemaccAdminHtml($cat['code'])."</code>\nمدت: ".(int)$cat['months']." ماه\nنوع: ".gemaccAdminHtml(gemaccAdminTrafficLabel($cat))."\nوضعیت: ".((int)$cat['is_active']?'فعال':'غیرفعال')."\nتعداد پلن‌ها: ".(int)$cnt->fetchColumn();
    tg('editMessageText',['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>((int)$cat['is_active']?'🔴 غیرفعال کردن':'🟢 فعال کردن'),'callback_data'=>'ADMIN_PLAN_CAT_TOGGLE__'.$catId]],[['text'=>'🗑 حذف دسته و پلن‌ها','callback_data'=>'ADMIN_PLAN_CAT_DELETE__'.$catId]],[['text'=>'◀️ پلن‌ها','callback_data'=>'ADMIN_PLANS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}
if (strpos($data, 'ADMIN_PLAN_CAT_TOGGLE__') === 0) {
    $catId=(int)str_replace('ADMIN_PLAN_CAT_TOGGLE__','',$data);
    $pdo->prepare("UPDATE plan_categories SET is_active=1-is_active, updated_at=NOW() WHERE id=?")->execute([$catId]);
    answerCbOnce($cb,'✅ وضعیت دسته تغییر کرد');
    gemaccAdminRenderPlans($pdo, (int)$chatId, (int)$msgId);
    exit('OK');
}
if (strpos($data, 'ADMIN_PLAN_CAT_DELETE__') === 0) {
    $catId=(int)str_replace('ADMIN_PLAN_CAT_DELETE__','',$data);
    $pdo->prepare("UPDATE plan_categories SET deleted_at=NOW(), is_active=0 WHERE id=?")->execute([$catId]);
    $pdo->prepare("UPDATE plans SET is_active=0, deleted_at=COALESCE(deleted_at,NOW()) WHERE category_id=?")->execute([$catId]);
    answerCbOnce($cb,'✅ دسته و پلن‌های آن از فروش خارج شدند');
    gemaccAdminRenderPlans($pdo, (int)$chatId, (int)$msgId);
    exit('OK');
}
if (strpos($data, 'ADMIN_PLAN_DELETE__') === 0) {
    $planId=(int)str_replace('ADMIN_PLAN_DELETE__','',$data);
    $st=$pdo->prepare("SELECT id FROM orders WHERE plan_id=? LIMIT 1"); $st->execute([$planId]);
    if($st->fetch()) $pdo->prepare("UPDATE plans SET is_active=0, deleted_at=NOW(), updated_at=NOW() WHERE id=?")->execute([$planId]);
    else $pdo->prepare("DELETE FROM plans WHERE id=?")->execute([$planId]);
    answerCbOnce($cb,'✅ پلن حذف/از فروش خارج شد');
    gemaccAdminRenderPlans($pdo, (int)$chatId, (int)$msgId);
    exit('OK');
}

if (strpos($data, 'ADMIN_PLAN_VIEW__') === 0) {
    $planId = (int)str_replace('ADMIN_PLAN_VIEW__', '', $data);
    $st = $pdo->prepare("SELECT p.*, pc.name AS category_name, pc.code AS category_code, pc.months AS category_months, pc.traffic_type AS category_traffic_type, pc.traffic_limit_gb AS category_traffic_limit_gb FROM plans p LEFT JOIN plan_categories pc ON pc.id=p.category_id WHERE p.id=? AND p.deleted_at IS NULL LIMIT 1");
    $st->execute([$planId]);
    $plan = $st->fetch(PDO::FETCH_ASSOC);
    if (!$plan) { answerCbOnceParams(['callback_query_id'=>$cb['id'],'text'=>'❌ پلن یافت نشد','show_alert'=>true]); exit('OK'); }
    $users = (int)($plan['user_count'] ?: $plan['seats'] ?: 1);
    $txt = "📦 <b>جزئیات پلن #{$planId}</b>\n\n";
    $txt .= "عنوان: " . gemaccAdminHtml($plan['title'] ?? 'پلن') . "\n";
    $txt .= "دسته: " . gemaccAdminHtml($plan['category_name'] ?? '-') . "\n";
    $txt .= "کد دسته: <code>" . gemaccAdminHtml($plan['category_code'] ?? $plan['duration'] ?? '-') . "</code>\n";
    $txt .= "نوع ترافیک: " . gemaccAdminHtml(gemaccAdminTrafficLabel($plan)) . "\n";
    $txt .= "تعداد کاربر: {$users}\n";
    $txt .= "قیمت: " . money((int)$plan['price']) . "\n";
    $txt .= "وضعیت: " . ((int)$plan['is_active'] ? 'فعال' : 'غیرفعال');
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'HTML','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'✏️ تغییر قیمت','callback_data'=>'ADMIN_PLAN_EDIT_PRICE__'.$planId]],[['text'=>'🗑 حذف/خروج از فروش','callback_data'=>'ADMIN_PLAN_DELETE__'.$planId]],[['text'=>'◀️ پلن‌ها','callback_data'=>'ADMIN_PLANS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}

// ═══════════════════ مدیریت پلن‌ها ═══════════════════

if ($data === 'ADMIN_PLANS') {
    $allPlans = $plans->getAll();
    
    $txt = "💵 **مدیریت پلن‌ها**\n\n";
    $buttons = [];
    
    // گروه‌بندی بر اساس duration - یک‌ماهه بالا
    $monthly = array_filter($allPlans, fn($p) => $p['duration'] === '1M');
    $yearly = array_filter($allPlans, fn($p) => $p['duration'] === '1Y');
    
    $txt .= "📅 **پلن‌های یک‌ماهه:**\n";
    foreach ($monthly as $p) {
        $status = $p['is_active'] ? '🟢' : '🔴';
        $seats = $p['seats'] ?? $p['users'] ?? 1;
        $txt .= "{$status} {$seats} کاربره: " . money($p['price']) . "\n";
        
        $toggleText = $p['is_active'] ? '❌ غیرفعال' : '✅ فعال';
        $buttons[] = [
            ['text' => "📅 {$seats} کاربره | " . number_format($p['price']) . " ت", 'callback_data' => "ADMIN_PLAN_VIEW__{$p['id']}"],
            ['text' => $toggleText, 'callback_data' => "ADMIN_PLAN_TOGGLE__{$p['id']}"],
        ];
    }
    
    $txt .= "\n📆 **پلن‌های یک‌ساله:**\n";
    foreach ($yearly as $p) {
        $status = $p['is_active'] ? '🟢' : '🔴';
        $seats = $p['seats'] ?? $p['users'] ?? 1;
        $txt .= "{$status} {$seats} کاربره: " . money($p['price']) . "\n";
        
        $toggleText = $p['is_active'] ? '❌ غیرفعال' : '✅ فعال';
        $buttons[] = [
            ['text' => "📆 {$seats} کاربره | " . number_format($p['price']) . " ت", 'callback_data' => "ADMIN_PLAN_VIEW__{$p['id']}"],
            ['text' => $toggleText, 'callback_data' => "ADMIN_PLAN_TOGGLE__{$p['id']}"],
        ];
    }
    
    $buttons[] = [['text' => '🔄 بروزرسانی', 'callback_data' => 'ADMIN_PLANS']];
    $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if (strpos($data, 'ADMIN_PLAN_VIEW__') === 0) {
    $planId = (int)str_replace('ADMIN_PLAN_VIEW__', '', $data);
    $plan = $plans->getById($planId);
    
    if (!$plan) {
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '❌ پلن یافت نشد', 'show_alert' => true]);
        exit('OK');
    }
    
    $durationLabel = Plans::getDurationLabel($plan['duration']);
    $seats = $plan['seats'] ?? 1;
    $status = $plan['is_active'] ? '🟢 فعال' : '🔴 غیرفعال';
    
    $txt = "📦 **جزئیات پلن #{$plan['id']}**\n\n";
    $txt .= "📝 عنوان: {$plan['title']}\n";
    $txt .= "⏱ مدت: {$durationLabel}\n";
    $txt .= "👥 تعداد کاربر: {$seats}\n";
    $txt .= "💰 قیمت: " . money($plan['price']) . "\n";
    $txt .= "🔘 وضعیت: {$status}\n";
    
    $toggleText = $plan['is_active'] ? '🔴 غیرفعال کردن' : '🟢 فعال کردن';
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => $toggleText, 'callback_data' => "ADMIN_PLAN_TOGGLE__{$plan['id']}"]],
                [['text' => '✏️ تغییر قیمت', 'callback_data' => "ADMIN_PLAN_EDIT_PRICE__{$plan['id']}"]],
                [['text' => '◀️ بازگشت به لیست', 'callback_data' => 'ADMIN_PLANS']],
            ],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if (strpos($data, 'ADMIN_PLAN_EDIT_PRICE__') === 0) {
    $planId = (int)str_replace('ADMIN_PLAN_EDIT_PRICE__', '', $data);
    $plan = $plans->getById($planId);
    
    if (!$plan) {
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '❌ پلن یافت نشد', 'show_alert' => true]);
        exit('OK');
    }
    
    setUserMode($chatId, 'ADMIN_EDIT_PLAN_PRICE', ['plan_id' => $planId]);
    
    $txt = "✏️ **تغییر قیمت پلن**\n\n";
    $txt .= "📦 پلن: {$plan['title']}\n";
    $txt .= "💰 قیمت فعلی: " . money($plan['price']) . "\n\n";
    $txt .= "قیمت جدید را به تومان ارسال کنید:";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_PLANS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if (strpos($data, 'ADMIN_PLAN_TOGGLE__') === 0) {
    $planId = (int)str_replace('ADMIN_PLAN_TOGGLE__', '', $data);
    $plan = $plans->getById($planId);
    
    if ($plan) {
        $plans->toggle($planId, !$plan['is_active']);
        $newStatus = !$plan['is_active'] ? 'فعال' : 'غیرفعال';
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => "✅ پلن {$newStatus} شد", 'show_alert' => false]);
        
        // رفرش فوری لیست
        goto admin_plans_refresh;
    } else {
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '❌ پلن یافت نشد', 'show_alert' => true]);
        exit('OK');
    }
}

admin_plans_refresh:
if ($data === 'ADMIN_PLANS' || isset($GLOBALS['_plans_refresh'])) {
    // رفرش لیست پلن‌ها
    $allPlans = $plans->getAll();
    
    $txt = "💵 **مدیریت پلن‌ها**\n\n";
    $buttons = [];
    
    // گروه‌بندی بر اساس duration - یک‌ماهه بالا
    $monthly = array_filter($allPlans, fn($p) => $p['duration'] === '1M');
    $yearly = array_filter($allPlans, fn($p) => $p['duration'] === '1Y');
    
    $txt .= "📅 **پلن‌های یک‌ماهه:**\n";
    foreach ($monthly as $p) {
        $status = $p['is_active'] ? '🟢' : '🔴';
        $seats = $p['seats'] ?? $p['users'] ?? 1;
        $txt .= "{$status} {$seats} کاربره: " . money($p['price']) . "\n";
        
        $toggleText = $p['is_active'] ? '❌ غیرفعال' : '✅ فعال';
        $buttons[] = [
            ['text' => "📅 {$seats} کاربره | " . number_format($p['price']) . " ت", 'callback_data' => "ADMIN_PLAN_VIEW__{$p['id']}"],
            ['text' => $toggleText, 'callback_data' => "ADMIN_PLAN_TOGGLE__{$p['id']}"],
        ];
    }
    
    $txt .= "\n📆 **پلن‌های یک‌ساله:**\n";
    foreach ($yearly as $p) {
        $status = $p['is_active'] ? '🟢' : '🔴';
        $seats = $p['seats'] ?? $p['users'] ?? 1;
        $txt .= "{$status} {$seats} کاربره: " . money($p['price']) . "\n";
        
        $toggleText = $p['is_active'] ? '❌ غیرفعال' : '✅ فعال';
        $buttons[] = [
            ['text' => "📆 {$seats} کاربره | " . number_format($p['price']) . " ت", 'callback_data' => "ADMIN_PLAN_VIEW__{$p['id']}"],
            ['text' => $toggleText, 'callback_data' => "ADMIN_PLAN_TOGGLE__{$p['id']}"],
        ];
    }
    
    $buttons[] = [['text' => '🔄 بروزرسانی', 'callback_data' => 'ADMIN_PLANS']];
    $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ پیام همگانی ═══════════════════

if ($data === 'ADMIN_BROADCAST') {
    setUserMode($chatId, 'ADMIN_BROADCAST', []);
    
    $txt = "📢 **پیام همگانی**\n\n";
    $txt .= "پیام خود را ارسال کنید (متن یا عکس با caption).\n\n";
    $txt .= "💡 **توکن‌های دکمه (عمودی):**\n";
    $txt .= "• `/dash` → 💰 کیف پول\n";
    $txt .= "• `/plans` → 🛒 خرید اشتراک\n";
    $txt .= "• `/sup` → 💬 پشتیبانی\n";
    $txt .= "• `/app` → 📲 مینی‌اپ\n\n";
    $txt .= "مثال:\n";
    $txt .= "`سلام! تخفیف ویژه داریم /plans /app`";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ مدیریت آموزش ═══════════════════

if ($data === 'ADMIN_TUTORIALS') {
    $txt = "📚 **مدیریت آموزش‌ها**\n\nابتدا سرویس را انتخاب کنید. آموزش‌های OpenVPN/L2TP، Windscribe، ExpressVPN و V2Ray کاملاً جدا هستند:";
    tg('editMessageText', [
        'chat_id' => $chatId,
        'message_id' => $msgId,
        'text' => $txt,
        'parse_mode' => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard'=>[
            [['text'=>'🧊 آموزش‌های OpenVPN | L2TP','callback_data'=>'ADMIN_TUTORIALS_SERVICE_openvpn_l2tp']],
            [['text'=>'🟦 آموزش‌های Windscribe','callback_data'=>'ADMIN_TUTORIALS_SERVICE_windscribe']],
            [['text'=>'🚀 آموزش‌های ExpressVPN','callback_data'=>'ADMIN_TUTORIALS_SERVICE_expressvpn']],
            [['text'=>'⚡ آموزش‌های V2Ray','callback_data'=>'ADMIN_TUTORIALS_SERVICE_v2ray']],
            [['text'=>'◀️ بازگشت','callback_data'=>'ADMIN']],
        ]], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if (strpos($data, 'ADMIN_TUTORIALS_SERVICE_') === 0) {
    $serviceType = str_replace('ADMIN_TUTORIALS_SERVICE_', '', $data);
    $allTutorials = $tutorials->getAll($serviceType);
    $serviceName = Tutorials::getServiceName($serviceType);
    $serviceEmoji = Tutorials::getServiceEmoji($serviceType);
    $txt = "📚 **مدیریت آموزش {$serviceName}** {$serviceEmoji}\n\n";
    $buttons = [];
    foreach (Tutorials::DEVICES as $device) {
        $tutorial = array_filter($allTutorials, fn($t) => $t['device'] === $device);
        $tutorial = reset($tutorial);
        $name = Tutorials::getDeviceName($device);
        $emoji = Tutorials::getDeviceEmoji($device);
        $hasVideo = $tutorial && $tutorial['video_file_id'] ? '📹' : '';
        $hasText = $tutorial && $tutorial['text_content'] ? '📝' : '';
        $txt .= "{$emoji} **{$name}:** {$hasText} {$hasVideo}\n";
        $buttons[] = [['text' => "{$emoji} ویرایش {$name}", 'callback_data' => "ADMIN_TUTORIAL_EDIT__{$serviceType}__{$device}"]];
    }
    $buttons[] = [['text' => '◀️ انتخاب سرویس', 'callback_data' => 'ADMIN_TUTORIALS']];
    tg('editMessageText', [
        'chat_id' => $chatId,
        'message_id' => $msgId,
        'text' => $txt,
        'parse_mode' => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if (strpos($data, 'ADMIN_TUTORIAL_EDIT__') === 0) {
    $parts = explode('__', str_replace('ADMIN_TUTORIAL_EDIT__', '', $data));
    $serviceType = $parts[0] ?? 'openvpn_l2tp';
    $device = $parts[1] ?? 'ANDROID';
    $deviceName = Tutorials::getDeviceName($device);
    $serviceName = Tutorials::getServiceName($serviceType);
    setUserMode($chatId, 'ADMIN_EDIT_TUTORIAL', ['device' => $device, 'service_type' => $serviceType]);
    $txt = "📚 **ویرایش آموزش {$serviceName} - {$deviceName}**\n\nمتن آموزش جدید را ارسال کنید.\nبرای افزودن ویدیو، ویدیو را ارسال کنید.";
    tg('editMessageText', [
        'chat_id' => $chatId,
        'message_id' => $msgId,
        'text' => $txt,
        'parse_mode' => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_TUTORIALS_SERVICE_'.$serviceType]]]], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ مدیریت کانال‌های اجباری ═══════════════════

// هندلر اضافه کردن کانال - باید قبل از هندلر اصلی باشد
if ($data === 'ADMIN_CH_ADD') {
    logError("ADMIN_CH_ADD handler entered");
    
    setUserMode($chatId, 'ADMIN_ADD_CHANNEL', []);
    
    $txt = "📢 **افزودن کانال**\n\n";
    $txt .= "یوزرنیم کانال را ارسال کنید:\n";
    $txt .= "مثال: `@your_channel`\n\n";
    $txt .= "💡 مطمئن شوید ربات در کانال ادمین است.";
    
    $result = tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_CHANNELS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    
    if (!$result || !isset($result['ok']) || !$result['ok']) {
        logError("ADMIN_CH_ADD editMessageText failed: " . json_encode($result));
        // ارسال پیام جدید اگر ویرایش نشد
        tg('sendMessage', [
            'chat_id'      => $chatId,
            'text'         => $txt,
            'parse_mode'   => 'Markdown',
            'reply_markup' => json_encode([
                'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_CHANNELS']]],
            ], JSON_UNESCAPED_UNICODE),
        ]);
    }
    exit('OK');
}

// هندلر فعال/غیرفعال کردن سیستم کانال اجباری
if ($data === 'ADMIN_FORCE_JOIN_TOGGLE') {
    logError("ADMIN_FORCE_JOIN_TOGGLE handler entered");
    
    try {
        $current = $forceJoin->isEnabled();
        $forceJoin->setEnabled(!$current);
        
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => $current ? '🔴 سیستم غیرفعال شد' : '🟢 سیستم فعال شد',
            'show_alert'        => true,
        ]);
    } catch (Exception $e) {
        logError("ADMIN_FORCE_JOIN_TOGGLE error: " . $e->getMessage());
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '❌ خطا: ' . $e->getMessage(),
            'show_alert'        => true,
        ]);
    }
    
    // رفتن به هندلر ADMIN_CHANNELS برای رفرش UI
    $data = 'ADMIN_CHANNELS';
}

// هندلر فعال/غیرفعال کردن کانال
if (strpos($data, 'ADMIN_CH_TOGGLE__') === 0) {
    logError("ADMIN_CH_TOGGLE handler entered - data: {$data}");
    
    try {
        $chId = (int)str_replace('ADMIN_CH_TOGGLE__', '', $data);
        $ch = $forceJoin->getById($chId);
        if ($ch) {
            $newStatus = !$ch['is_active'];
            $forceJoin->toggleChannel($chId, $newStatus);
            answerCbOnceParams([
                'callback_query_id' => $cb['id'],
                'text'              => $newStatus ? '🟢 کانال فعال شد' : '🔴 کانال غیرفعال شد',
            ]);
        }
    } catch (Exception $e) {
        logError("ADMIN_CH_TOGGLE error: " . $e->getMessage());
    }
    
    // رفتن به هندلر ADMIN_CHANNELS برای رفرش UI
    $data = 'ADMIN_CHANNELS';
}

// هندلر حذف کانال
if (strpos($data, 'ADMIN_CH_DELETE__') === 0) {
    logError("ADMIN_CH_DELETE handler entered - data: {$data}");
    
    try {
        $chId = (int)str_replace('ADMIN_CH_DELETE__', '', $data);
        $forceJoin->removeChannel($chId);
        answerCbOnceParams([
            'callback_query_id' => $cb['id'],
            'text'              => '🗑️ کانال حذف شد',
            'show_alert'        => true,
        ]);
    } catch (Exception $e) {
        logError("ADMIN_CH_DELETE error: " . $e->getMessage());
    }
    
    // رفتن به هندلر ADMIN_CHANNELS برای رفرش UI
    $data = 'ADMIN_CHANNELS';
}

// هندلر اصلی نمایش لیست کانال‌ها
if ($data === 'ADMIN_CHANNELS') {
    logError("ADMIN_CHANNELS handler entered - data: {$data}");
    
    try {
        $channels = $forceJoin->getAllChannels();
        $isEnabled = $forceJoin->isEnabled();
        
        logError("ADMIN_CHANNELS - channels count: " . count($channels) . ", enabled: " . ($isEnabled ? 'yes' : 'no'));
        
        $txt = "📢 **کانال‌های اجباری**\n\n";
        $txt .= "🔘 وضعیت سیستم: " . ($isEnabled ? '🟢 فعال' : '🔴 غیرفعال') . "\n\n";
        
        $buttons = [];
        
        if (empty($channels)) {
            $txt .= "📭 هیچ کانالی ثبت نشده است.\n";
            $txt .= "برای اضافه کردن کانال، از دکمه زیر استفاده کنید.";
        } else {
            $txt .= "📋 لیست کانال‌ها:\n";
            foreach ($channels as $ch) {
                $status = $ch['is_active'] ? '🟢' : '🔴';
                $txt .= "{$status} {$ch['channel_username']}\n";
                
                $buttons[] = [
                    ['text' => $status . ' ' . $ch['channel_username'], 'callback_data' => "ADMIN_CH_TOGGLE__{$ch['id']}"],
                    ['text' => '🗑', 'callback_data' => "ADMIN_CH_DELETE__{$ch['id']}"],
                ];
            }
        }
        
        $toggleText = $isEnabled ? '🔴 غیرفعال کردن سیستم' : '🟢 فعال کردن سیستم';
        $buttons[] = [['text' => $toggleText, 'callback_data' => 'ADMIN_FORCE_JOIN_TOGGLE']];
        $buttons[] = [['text' => '➕ افزودن کانال', 'callback_data' => 'ADMIN_CH_ADD']];
        $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
        
        $result = tg('editMessageText', [
            'chat_id'      => $chatId,
            'message_id'   => $msgId,
            'text'         => $txt,
            'parse_mode'   => 'Markdown',
            'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
        ]);
        
        logError("ADMIN_CHANNELS editMessageText result: " . json_encode($result));
        
        // اگر ویرایش پیام ناموفق بود، پیام جدید ارسال کن
        if (!$result || !isset($result['ok']) || !$result['ok']) {
            logError("ADMIN_CHANNELS editMessageText failed, sending new message");
            tg('sendMessage', [
                'chat_id'      => $chatId,
                'text'         => $txt,
                'parse_mode'   => 'Markdown',
                'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
            ]);
        }
        
    } catch (PDOException $e) {
        logError("ADMIN_CHANNELS PDO error: " . $e->getMessage());
        tg('sendMessage', [
            'chat_id'    => $chatId,
            'text'       => "❌ **خطای دیتابیس:**\n\nجدول `forced_channels` ممکن است وجود نداشته باشد.\nلطفاً از install.php برای نصب مجدد دیتابیس استفاده کنید.\n\n`" . $e->getMessage() . "`",
            'parse_mode' => 'Markdown',
        ]);
    } catch (Exception $e) {
        logError("ADMIN_CHANNELS error: " . $e->getMessage());
        tg('sendMessage', [
            'chat_id'    => $chatId,
            'text'       => "❌ خطا در بارگذاری کانال‌ها:\n" . $e->getMessage(),
        ]);
    }
    exit('OK');
}

// ═══════════════════ تنظیمات ═══════════════════

if ($data === 'ADMIN_SETTINGS') {
    $cardNumber = getCardNumber();
    $cardOwner = getSetting('card_owner_name', '');
    $welcomeMsg = getSetting('welcome_message', '');
    $supportGroup = getSetting('support_group', '');
    $defaultTolerance = max(0, (int)getSetting('default_payment_tolerance_toman', 50000));
    $volumeTolerance = max(0, (int)getSetting('volume_payment_tolerance_toman', 30000));
    $plisioEnabled = getSetting('plisio_enabled','0') === '1';
    $usdtRate = (int)getSetting('manual_crypto_usdt_irt_rate','0');
    $trxRate = (int)getSetting('manual_crypto_trx_irt_rate','0');
    
    $txt = "⚙️ **تنظیمات سیستم**

";
    $txt .= "━━━━━━━━━━━━━━━━━━━━
";
    $txt .= "💳 شماره کارت:
`{$cardNumber}`
";
    if ($cardOwner) {
        $txt .= "👤 صاحب کارت: {$cardOwner}
";
    }
    $txt .= "💬 گروه پرسش و پاسخ:
`" . ($supportGroup !== '' ? $supportGroup : 'تنظیم نشده') . "`
";
    $txt .= "⚖️ تلورانس پرداخت نامحدود/پیش‌فرض: `" . number_format($defaultTolerance) . " تومان`
";
    $txt .= "📦 تلورانس پرداخت اشتراک حجمی: `" . number_format($volumeTolerance) . " تومان`
";
    $txt .= "🪙 درگاه Plisio: `" . ($plisioEnabled ? 'فعال' : 'غیرفعال') . "`
";
    $txt .= "💵 نرخ دستی تتر: `" . ($usdtRate > 0 ? number_format($usdtRate) . ' تومان' : 'تنظیم نشده') . "`
";
    $txt .= "🔴 نرخ دستی ترون: `" . ($trxRate > 0 ? number_format($trxRate) . ' تومان' : 'تنظیم نشده') . "`
";
    $txt .= "━━━━━━━━━━━━━━━━━━━━
";
    
    $buttons = [
        [['text' => '💳 تغییر شماره کارت', 'callback_data' => 'ADMIN_CHANGE_CARD']],
        [['text' => '👤 تغییر نام صاحب کارت', 'callback_data' => 'ADMIN_CHANGE_CARD_OWNER']],
        [['text' => '🏦 مدیریت چند کارت بانکی چرخشی', 'callback_data' => 'ADMIN_CHANGE_BANK_CARDS']],
        [['text' => '📝 تغییر پیام خوش‌آمد', 'callback_data' => 'ADMIN_CHANGE_WELCOME']],
        [['text' => '💬 تغییر/پاک کردن آدرس گروه پرسش پاسخ', 'callback_data' => 'ADMIN_CHANGE_SUPPORT_GROUP']],
        [['text' => '⚖️ مدیریت تلورانس قیمت', 'callback_data' => 'ADMIN_PAYMENT_TOLERANCE']],
        [['text' => '💹 قیمت خرید پلن‌ها / سود خالص', 'callback_data' => 'ADMIN_PLAN_COSTS']],
        [['text' => '⏸ خاموش/روشن فروش', 'callback_data' => 'ADMIN_SALES_TOGGLE']],
        [['text' => '👑 مدیریت ادمین‌ها', 'callback_data' => 'ADMIN_MANAGE_ADMINS']],
        [['text' => '🪙 مدیریت پرداخت ارز/Plisio', 'callback_data' => 'ADMIN_CRYPTO_GATEWAY']],
        [['text' => '🔄 پردازش صف انتظار', 'callback_data' => 'ADMIN_PROCESS_QUEUE']],
        [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']],
    ];
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}


if ($data === 'ADMIN_CHANGE_BANK_CARDS') {
    setUserMode($chatId, 'ADMIN_CHANGE_BANK_CARDS', []);
    $current = getSetting('bank_cards', '');
    $txt = "🏦 **مدیریت کارت‌های بانکی چرخشی**\n\nهر خط یک کارت با این فرمت ارسال شود:\n`شماره کارت|نام صاحب کارت|نام بانک`\n\nمثال:\n`6104331062907218|علی رضایی|ملت`\n`5022291234567890|علی رضایی|پاسارگاد`\n\nکارت فعلی:\n" . ($current ? "`{$current}`" : 'تنظیم نشده');
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_SETTINGS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}

if ($data === 'ADMIN_CHANGE_CARD_OWNER') {
    setUserMode($chatId, 'ADMIN_CHANGE_CARD_OWNER', []);
    
    $txt = "👤 **تغییر نام صاحب کارت**\n\n";
    $txt .= "نام صاحب کارت را ارسال کنید:\n";
    $txt .= "مثال: `علی رضایی`";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_SETTINGS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_CHANGE_WELCOME') {
    setUserMode($chatId, 'ADMIN_CHANGE_WELCOME', []);
    
    $txt = "📝 **تغییر پیام خوش‌آمدگویی**\n\n";
    $txt .= "پیام جدید خوش‌آمدگویی را ارسال کنید:\n\n";
    $txt .= "💡 این پیام در منوی اصلی ربات نمایش داده می‌شود.";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_SETTINGS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_CHANGE_SUPPORT_GROUP') {
    setUserMode($chatId, 'ADMIN_CHANGE_SUPPORT_GROUP', []);
    
    $txt = "💬 **آدرس گروه پرسش و پاسخ**

";
    $txt .= "لینک جدید را ارسال کنید. برای پاک کردن کامل دکمه گروه، کلمه `حذف` یا `-` را بفرستید.

";
    $txt .= "مثال: `https://t.me/your_group`";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_SETTINGS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}




if ($data === 'ADMIN_PLAN_COSTS') {
    gemaccAdminEnsureProfitColumns($pdo);
    $plansRows = $pdo->query("SELECT p.*, pc.name AS category_name FROM plans p LEFT JOIN plan_categories pc ON pc.id=p.category_id WHERE p.deleted_at IS NULL ORDER BY COALESCE(pc.months,p.months), p.display_order, p.id LIMIT 40")->fetchAll(PDO::FETCH_ASSOC);
    $txt = "💹 **قیمت خرید پلن‌ها / محاسبه سود خالص**

";
    $txt .= "برای اینکه در بخش درآمد، ورودی مالی و درآمد خالص جدا شود، قیمت خرید هر پلن را ثبت کن.

";
    if (!$plansRows) $txt .= "— پلنی ثبت نشده است.
";
    foreach ($plansRows as $p) {
        $txt .= '#' . (int)$p['id'] . ' | ' . ($p['category_name'] ?: $p['duration']) . ' | فروش: ' . money((int)$p['price']) . ' | خرید: ' . money((int)($p['purchase_price'] ?? 0)) . ' | سود: ' . money(max(0,(int)$p['price']-(int)($p['purchase_price'] ?? 0))) . "
";
    }
    $buttons = [];
    $buttons[] = [['text'=>'🟦 قیمت خرید هر کاربر فقط Windscribe','callback_data'=>'ADMIN_EDIT_WS_PLAN_COST_UNIT']];
    $buttons[] = [['text'=>'💹 ثبت قیمت خرید هر کاربر برای همه پلن‌ها','callback_data'=>'ADMIN_EDIT_PLAN_COST_UNIT']];
    foreach (array_chunk(array_slice($plansRows,0,24), 2) as $chunk) {
        $row=[];
        foreach ($chunk as $p) $row[]=['text'=>'#'.(int)$p['id'].' قیمت خرید','callback_data'=>'ADMIN_EDIT_PLAN_COST_'.(int)$p['id']];
        $buttons[]=$row;
    }
    $buttons[] = [['text'=>'◀️ بازگشت به تنظیمات','callback_data'=>'ADMIN_SETTINGS']];
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>$buttons],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}

if (strpos($data, 'ADMIN_EDIT_PLAN_COST_') === 0) {
    gemaccAdminEnsureProfitColumns($pdo);
    $planId = (int)str_replace('ADMIN_EDIT_PLAN_COST_', '', $data);
    $st = $pdo->prepare("SELECT p.*, pc.name AS category_name FROM plans p LEFT JOIN plan_categories pc ON pc.id=p.category_id WHERE p.id=? AND p.deleted_at IS NULL LIMIT 1");
    $st->execute([$planId]);
    $planRow = $st->fetch(PDO::FETCH_ASSOC);
    if (!$planRow) { answerCbOnce($cb, 'پلن یافت نشد'); exit('OK'); }
    setUserMode($chatId, 'ADMIN_EDIT_PLAN_COST', ['plan_id'=>$planId]);
    $txt = "💹 **ثبت قیمت خرید پلن**

";
    $txt .= "پلن: `#{$planId}` " . ($planRow['category_name'] ?: $planRow['title']) . "
";
    $txt .= "قیمت فروش: `" . number_format((int)$planRow['price']) . " تومان`
";
    $txt .= "قیمت خرید فعلی: `" . number_format((int)($planRow['purchase_price'] ?? 0)) . " تومان`

";
    $txt .= "قیمت خرید جدید را به تومان ارسال کن. مثال: `180000`";
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_PLAN_COSTS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}



if ($data === 'ADMIN_EDIT_WS_PLAN_COST_UNIT') {
    setUserMode($chatId, 'ADMIN_EDIT_WS_PLAN_COST_UNIT', []);
    $txt = "🟦 **ثبت قیمت خرید هر کاربر Windscribe**

فقط یک‌بار قیمت خرید ۱ کاربر را بفرست.
سیستم برای پلن‌های ۲، ۳، ۵ کاربره و یک‌ساله، خودش ضرب می‌کند.

مثال: `180000`";
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_PLAN_COSTS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}

if ($data === 'ADMIN_EDIT_PLAN_COST_UNIT') {
    setUserMode($chatId, 'ADMIN_EDIT_PLAN_COST_UNIT', []);
    $txt = "💹 **ثبت قیمت خرید هر کاربر برای همه پلن‌ها**

قیمت خرید ۱ کاربر را به تومان ارسال کن. مثال: `180000`
سیستم خودکار قیمت خرید پلن ۵ کاربره را ۵ برابر می‌کند.";
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_PLAN_COSTS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}

if ($data === 'ADMIN_SALES_TOGGLE') {
    $enabled = getSetting('sales_enabled','1') === '1';
    setSetting('sales_enabled', $enabled ? '0' : '1');
    answerCbOnce($cb, $enabled ? '⏸ فروش متوقف شد' : '✅ فروش فعال شد', true);
    $data = 'ADMIN_SETTINGS';
}

if ($data === 'ADMIN_MANAGE_ADMINS') {
    $admins = function_exists('adminIds') ? adminIds() : [];
    $txt = "👑 **مدیریت ادمین‌ها**

ادمین اصلی پروژه: `5516198479`

ادمین‌های فعال:
";
    foreach ($admins as $aid) $txt .= "• `{$aid}`
";
    $txt .= "
برای اضافه کردن ادمین جدید، آیدی عددی تلگرام را ارسال کن.";
    setUserMode($chatId, 'ADMIN_ADD_ADMIN_ID', []);
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'🧹 پاکسازی ادمین‌های اضافی','callback_data'=>'ADMIN_CLEAR_EXTRA_ADMINS']],[['text'=>'◀️ تنظیمات','callback_data'=>'ADMIN_SETTINGS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}
if ($data === 'ADMIN_CLEAR_EXTRA_ADMINS') {
    setSetting('admin_extra_ids','');
    $pdo->prepare("UPDATE users SET is_admin=0 WHERE id<>?")->execute([5516198479]);
    answerCbOnce($cb, '✅ فقط ادمین اصلی باقی ماند', true);
    exit('OK');
}

if ($data === 'ADMIN_CRYPTO_GATEWAY') {
    $enabled = getSetting('plisio_enabled','0') === '1';
    $api = trim((string)getSetting('plisio_api_key',''));
    $usdRate = (int)getSetting('plisio_usd_rate_toman','60000');
    $currencies = trim((string)getSetting('plisio_currencies','USDT_BSC,TRX'));
    $allowAllCurrencies = getSetting('plisio_allow_all_currencies','1') === '1';
    $assets = trim((string)getSetting('crypto_enabled_assets','USDT,TRX'));
    $usdtRate = (int)getSetting('manual_crypto_usdt_irt_rate','0');
    $trxRate = (int)getSetting('manual_crypto_trx_irt_rate','0');
    $manualEnabled = getSetting('manual_crypto_enabled','1') === '1';
    $txt = "🪙 **مدیریت پرداخت ارز دیجیتال / Plisio**

";
    $txt .= "⚡ وضعیت Plisio: `" . ($enabled ? 'فعال' : 'غیرفعال') . "`
";
    $txt .= "🔑 API Key: `" . ($api !== '' ? 'ثبت شده' : 'ثبت نشده') . "`
";
    $txt .= "💵 نرخ دلار Plisio: `" . number_format($usdRate) . " تومان`
";
    $txt .= "🪙 ارزهای قابل نمایش کاربر: `" . ($assets ?: 'USDT,TRX') . "`
";
    $txt .= "🔌 ارزهای ارسالی به Plisio: `" . ($currencies ?: 'خودکار') . "`
";
    $txt .= "🌐 انتخاب آزاد ارز/شبکه در درگاه: `" . ($allowAllCurrencies ? 'فعال' : 'غیرفعال') . "`

";
    $txt .= "🧾 پرداخت دستی ارز: `" . ($manualEnabled ? 'فعال' : 'غیرفعال') . "`
";
    $txt .= "💵 نرخ دستی تتر: `" . ($usdtRate > 0 ? number_format($usdtRate) . ' تومان' : 'تنظیم نشده') . "`
";
    $txt .= "🔴 نرخ دستی ترون: `" . ($trxRate > 0 ? number_format($trxRate) . ' تومان' : 'تنظیم نشده') . "`

";
    $txt .= "اگر Plisio فعال باشد، کاربر به درگاه لحظه‌ای می‌رود. اگر خاموش باشد یا API خطا بدهد، پرداخت دستی با نرخ‌های بالا نمایش داده می‌شود.";
    tg('editMessageText', [
        'chat_id'=>$chatId,'message_id'=>$msgId,'text'=>$txt,'parse_mode'=>'Markdown',
        'reply_markup'=>json_encode(['inline_keyboard'=>[
            [['text'=>$enabled?'🔴 غیرفعال کردن Plisio':'🟢 فعال کردن Plisio','callback_data'=>'ADMIN_TOGGLE_PLISIO']],
            [['text'=>'🔑 تغییر API Key Plisio','callback_data'=>'ADMIN_CHANGE_PLISIO_API_KEY']],
            [['text'=>$allowAllCurrencies?'🔒 محدود کردن درگاه به ارز انتخابی':'🌐 آزاد کردن همه ارزها/شبکه‌ها در درگاه','callback_data'=>'ADMIN_TOGGLE_PLISIO_ALL_CURRENCIES']],
            [['text'=>'💵 تغییر نرخ دلار Plisio','callback_data'=>'ADMIN_CHANGE_PLISIO_USD_RATE']],
            [['text'=>'🪙 فقط تتر','callback_data'=>'ADMIN_SET_CRYPTO_ASSETS_USDT'], ['text'=>'🔴 فقط ترون','callback_data'=>'ADMIN_SET_CRYPTO_ASSETS_TRX']],
            [['text'=>'💵 تتر + ترون','callback_data'=>'ADMIN_SET_CRYPTO_ASSETS_BOTH']],
            [['text'=>'💵 تغییر نرخ دستی تتر','callback_data'=>'ADMIN_CHANGE_MANUAL_USDT_RATE']],
            [['text'=>'🔴 تغییر نرخ دستی ترون','callback_data'=>'ADMIN_CHANGE_MANUAL_TRX_RATE']],
            [['text'=>'◀️ بازگشت به تنظیمات','callback_data'=>'ADMIN_SETTINGS']],
        ]], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}


if (strpos($data, 'ADMIN_SET_CRYPTO_ASSETS_') === 0) {
    $kind = str_replace('ADMIN_SET_CRYPTO_ASSETS_', '', $data);
    $assets = $kind === 'USDT' ? 'USDT' : ($kind === 'TRX' ? 'TRX' : 'USDT,TRX');
    setSetting('crypto_enabled_assets', $assets);
    setSetting('plisio_currencies', $assets === 'TRX' ? 'TRX' : ($assets === 'USDT' ? 'USDT_BSC' : 'USDT_BSC,TRX'));
    answerCbOnce($cb, 'ارزهای پرداخت ذخیره شد: ' . $assets);
    tg('editMessageText', [
        'chat_id'=>$chatId,
        'message_id'=>$msgId,
        'text'=>'✅ ارزهای قابل نمایش به کاربر ذخیره شد.',
        'reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'🪙 بازگشت به مدیریت پرداخت ارز','callback_data'=>'ADMIN_CRYPTO_GATEWAY']]]],JSON_UNESCAPED_UNICODE)
    ]);
    exit('OK');
}


if ($data === 'ADMIN_TOGGLE_PLISIO_ALL_CURRENCIES') {
    $new = getSetting('plisio_allow_all_currencies','1') === '1' ? '0' : '1';
    setSetting('plisio_allow_all_currencies', $new);
    answerCbOnce($cb, $new === '1' ? '🌐 کاربر در درگاه می‌تواند ارز/شبکه را آزاد انتخاب کند' : '🔒 درگاه به ارز انتخابی کاربر محدود شد', true);
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>'✅ تنظیمات انتخاب ارز/شبکه درگاه تغییر کرد.','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'🪙 بازگشت به مدیریت پرداخت ارز','callback_data'=>'ADMIN_CRYPTO_GATEWAY']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}

if ($data === 'ADMIN_TOGGLE_PLISIO') {
    $new = getSetting('plisio_enabled','0') === '1' ? '0' : '1';
    setSetting('plisio_enabled', $new);
    answerCbOnce($cb, $new === '1' ? 'Plisio فعال شد' : 'Plisio غیرفعال شد');
    $data = 'ADMIN_CRYPTO_GATEWAY';
    // Re-render by duplicating navigation through callback is not possible here; show compact result.
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>'✅ وضعیت Plisio تغییر کرد.','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'🪙 بازگشت به مدیریت پرداخت ارز','callback_data'=>'ADMIN_CRYPTO_GATEWAY']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}

if (in_array($data, ['ADMIN_CHANGE_PLISIO_API_KEY','ADMIN_CHANGE_PLISIO_USD_RATE','ADMIN_CHANGE_PLISIO_CURRENCIES','ADMIN_CHANGE_MANUAL_USDT_RATE','ADMIN_CHANGE_MANUAL_TRX_RATE'], true)) {
    $labels = [
        'ADMIN_CHANGE_PLISIO_API_KEY'=>'کلید API/Secret Key درگاه Plisio را ارسال کنید. برای حذف، `حذف` بفرستید.',
        'ADMIN_CHANGE_PLISIO_USD_RATE'=>'نرخ دلار به تومان برای تبدیل مبلغ Plisio را ارسال کنید. مثال: `60000`',
        'ADMIN_CHANGE_PLISIO_CURRENCIES'=>'ارزهای مجاز Plisio را با کاما ارسال کنید. مثال: `USDT_BSC,USDT_BSC,TRX,BTC,LTC`
اگر اکانت Plisio شما لیست ارز را خالی نشان می‌دهد، این مقدار را خالی بگذارید.',
        'ADMIN_CHANGE_MANUAL_USDT_RATE'=>'نرخ دستی هر ۱ تتر به تومان را ارسال کنید. مثال: اگر تتر ۱۸۰,۰۰۰ تومان است، `180000` بفرستید.',
        'ADMIN_CHANGE_MANUAL_TRX_RATE'=>'نرخ دستی هر ۱ ترون به تومان را ارسال کنید. مثال: `9000`',
    ];
    setUserMode($chatId, $data, []);
    tg('editMessageText', ['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>'✏️ '.$labels[$data],'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_CRYPTO_GATEWAY']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}

if ($data === 'ADMIN_PAYMENT_TOLERANCE') {
    $defaultTolerance = max(0, (int)getSetting('default_payment_tolerance_toman', 50000));
    $volumeTolerance = max(0, (int)getSetting('volume_payment_tolerance_toman', 30000));

    $txt = "⚖️ **مدیریت تلورانس قیمت**

";
    $txt .= "تلورانس فقط برای کارت‌به‌کارت است و مبلغ را به سمت بالا به عدد دقیق و غیررند تبدیل می‌کند.

";
    $txt .= "🔹 نامحدود/پیش‌فرض: `" . number_format($defaultTolerance) . " تومان`
";
    $txt .= "🔹 اشتراک‌های حجمی: `" . number_format($volumeTolerance) . " تومان`

";
    $txt .= "برای غیرفعال‌سازی اختلاف، مقدار `0` بگذارید.";

    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => '✏️ تغییر تلورانس نامحدود/پیش‌فرض', 'callback_data' => 'ADMIN_CHANGE_TOLERANCE_DEFAULT']],
                [['text' => '✏️ تغییر تلورانس اشتراک حجمی', 'callback_data' => 'ADMIN_CHANGE_TOLERANCE_VOLUME']],
                [['text' => '◀️ بازگشت به تنظیمات', 'callback_data' => 'ADMIN_SETTINGS']],
            ],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_CHANGE_TOLERANCE_DEFAULT' || $data === 'ADMIN_CHANGE_TOLERANCE_VOLUME') {
    $kind = $data === 'ADMIN_CHANGE_TOLERANCE_VOLUME' ? 'volume' : 'default';
    $key = $kind === 'volume' ? 'volume_payment_tolerance_toman' : 'default_payment_tolerance_toman';
    $label = $kind === 'volume' ? 'اشتراک‌های حجمی' : 'اشتراک‌های نامحدود/پیش‌فرض';
    $current = max(0, (int)getSetting($key, $kind === 'volume' ? 30000 : 50000));
    setUserMode($chatId, 'ADMIN_CHANGE_PAYMENT_TOLERANCE', ['kind' => $kind]);

    $txt = "✏️ **تغییر تلورانس قیمت**

";
    $txt .= "بخش: {$label}
";
    $txt .= "مقدار فعلی: `" . number_format($current) . " تومان`

";
    $txt .= "عدد جدید را به تومان ارسال کنید.
";
    $txt .= "مثال: `50000`
";
    $txt .= "برای غیرفعال‌سازی اختلاف مبلغ، `0` ارسال کنید.";

    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_PAYMENT_TOLERANCE']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_CHANGE_CARD') {
    setUserMode($chatId, 'ADMIN_CHANGE_CARD', []);
    
    $txt = "💳 **تغییر شماره کارت**\n\n";
    $txt .= "شماره کارت جدید را ارسال کنید:\n";
    $txt .= "مثال: `6104337812345678`";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_SETTINGS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_PROCESS_QUEUE') {
    $result = function_exists('vpnProcessWaitingQueue') ? vpnProcessWaitingQueue($pdo, null, 50) : $orders->processQueue();
    
    $txt = "🔄 **پردازش صف انتظار**\n\n";
    $processedCount = is_array($result['processed'] ?? null) ? count($result['processed']) : (int)($result['processed'] ?? 0);
    $waitingCount = is_array($result['still_queued'] ?? null) ? count($result['still_queued']) : (int)($result['still_waiting'] ?? 0);
    $txt .= "✅ پردازش شده: {$processedCount}\n";
    $txt .= "⏳ در انتظار: {$waitingCount}\n";
    
    // اطلاع‌رسانی به کاربرانی که سفارششان پردازش شد
    if ($processedCount > 0) {
        $txt .= "\n📨 به کاربران اطلاع‌رسانی شد.";
    }
    
    answerCbOnceParams([
        'callback_query_id' => $cb['id'],
        'text'              => "پردازش شده: {$processedCount} | در انتظار: {$waitingCount}",
        'show_alert'        => true,
    ]);
    exit('OK');
}

// ═══════════════════ مدیریت کدهای تخفیف ═══════════════════

if ($data === 'ADMIN_DISCOUNTS') {
    $allDiscounts = $discountCode->getAll();
    
    $txt = "🎫 **مدیریت کدهای تخفیف**\n\n";
    $buttons = [];
    
    if (empty($allDiscounts)) {
        $txt .= "📭 هیچ کد تخفیفی ثبت نشده است.";
    } else {
        foreach ($allDiscounts as $d) {
            $status = $d['is_active'] ? '🟢' : '🔴';
            $typeLabel = $d['type'] === 'PERCENT' ? $d['value'] . '٪' : number_format($d['value']) . ' تومان';
            $txt .= "{$status} `{$d['code']}` - {$typeLabel}\n";
            $txt .= "   استفاده: {$d['used_count']}" . ($d['max_uses'] ? "/{$d['max_uses']}" : '') . "\n";
        }
    }
    
    $buttons[] = [['text' => '➕ افزودن کد تخفیف', 'callback_data' => 'ADMIN_ADD_DISCOUNT']];
    if (!empty($allDiscounts)) {
        $buttons[] = [['text' => '📋 لیست کدها', 'callback_data' => 'ADMIN_DISCOUNT_LIST']];
    }
    $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']];
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_ADD_DISCOUNT') {
    setUserMode($chatId, 'ADMIN_ADD_DISCOUNT', ['step' => 'code']);
    
    $txt = "🎫 **افزودن کد تخفیف**\n\n";
    $txt .= "📝 کد تخفیف را وارد کنید:\n";
    $txt .= "مثال: `SALE50` یا `NEWYEAR`";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_DISCOUNTS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_DISCOUNT_LIST') {
    $allDiscounts = $discountCode->getAll();
    $buttons = [];
    
    foreach ($allDiscounts as $d) {
        $status = $d['is_active'] ? '🟢' : '🔴';
        $buttons[] = [
            ['text' => "{$status} {$d['code']}", 'callback_data' => "ADMIN_DISCOUNT_VIEW__{$d['id']}"],
            ['text' => '🗑', 'callback_data' => "ADMIN_DISCOUNT_DELETE__{$d['id']}"],
        ];
    }
    $buttons[] = [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN_DISCOUNTS']];
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => "🎫 **لیست کدهای تخفیف**\n\nروی هر کد کلیک کنید برای جزئیات:",
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(['inline_keyboard' => $buttons], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if (strpos($data, 'ADMIN_DISCOUNT_VIEW__') === 0) {
    $id = (int)str_replace('ADMIN_DISCOUNT_VIEW__', '', $data);
    $d = $discountCode->getById($id);
    
    if (!$d) {
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '❌ کد یافت نشد', 'show_alert' => true]);
        exit('OK');
    }
    
    $status = $d['is_active'] ? '🟢 فعال' : '🔴 غیرفعال';
    $typeLabel = $d['type'] === 'PERCENT' ? 'درصدی' : 'مبلغ ثابت';
    
    $txt = "🎫 **جزئیات کد تخفیف**\n\n";
    $txt .= "📝 کد: `{$d['code']}`\n";
    $txt .= "🔘 وضعیت: {$status}\n";
    $txt .= "📊 نوع: {$typeLabel}\n";
    $txt .= "💰 مقدار: " . ($d['type'] === 'PERCENT' ? $d['value'] . '٪' : number_format($d['value']) . ' تومان') . "\n";
    if ($d['max_discount']) {
        $txt .= "🔝 حداکثر تخفیف: " . number_format($d['max_discount']) . " تومان\n";
    }
    if ($d['min_purchase'] > 0) {
        $txt .= "🛒 حداقل خرید: " . number_format($d['min_purchase']) . " تومان\n";
    }
    $txt .= "👥 استفاده: {$d['used_count']}" . ($d['max_uses'] ? "/{$d['max_uses']}" : '') . "\n";
    $txt .= "👤 هر کاربر: {$d['max_uses_per_user']} بار\n";
    
    $toggleText = $d['is_active'] ? '🔴 غیرفعال کردن' : '🟢 فعال کردن';
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => $toggleText, 'callback_data' => "ADMIN_DISCOUNT_TOGGLE__{$id}"]],
                [['text'=>'📣 ارسال به کاربران','callback_data'=>"ADMIN_DISCOUNT_BROADCAST__{$id}"]],
                [['text' => '🗑 حذف', 'callback_data' => "ADMIN_DISCOUNT_DELETE__{$id}"]],
                [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN_DISCOUNT_LIST']],
            ],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}


if (strpos($data, 'ADMIN_DISCOUNT_BROADCAST__') === 0) {
    $id=(int)str_replace('ADMIN_DISCOUNT_BROADCAST__','',$data);
    $d=$discountCode->getById($id);
    if(!$d){ answerCbOnceParams(['callback_query_id'=>$cb['id'],'text'=>'کد پیدا نشد','show_alert'=>true]); exit('OK'); }
    setUserMode($chatId,'ADMIN_DISCOUNT_BROADCAST',['discount_id'=>$id,'step'=>'target']);
    tg('editMessageText',['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>"📣 ارسال کد `{$d['code']}`

مخاطب را انتخاب کن:",'parse_mode'=>'Markdown','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'خریداران','callback_data'=>'DISC_BC_TARGET_buyers'],['text'=>'خرید نکرده‌ها','callback_data'=>'DISC_BC_TARGET_non_buyers']],[['text'=>'تمام کاربران','callback_data'=>'DISC_BC_TARGET_all']],[['text'=>'◀️ بازگشت','callback_data'=>'ADMIN_DISCOUNT_VIEW__'.$id]]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}
if (strpos($data,'DISC_BC_TARGET_')===0) {
    $mode=getUserMode($chatId); if(!$mode || ($mode['mode']??'')!=='ADMIN_DISCOUNT_BROADCAST') exit('OK');
    $payload=$mode['payload']; $payload['target']=str_replace('DISC_BC_TARGET_','',$data); $payload['step']='message';
    setUserMode($chatId,'ADMIN_DISCOUNT_BROADCAST',$payload);
    tg('editMessageText',['chat_id'=>$chatId,'message_id'=>$msgId,'text'=>'📝 متن توضیحات/مناسبت تخفیف را ارسال کن. می‌توانی عکس را با کپشن هم بفرستی.','reply_markup'=>json_encode(['inline_keyboard'=>[[['text'=>'❌ انصراف','callback_data'=>'ADMIN_DISCOUNTS']]]],JSON_UNESCAPED_UNICODE)]);
    exit('OK');
}
if (strpos($data, 'ADMIN_DISCOUNT_TOGGLE__') === 0) {
    $id = (int)str_replace('ADMIN_DISCOUNT_TOGGLE__', '', $data);
    $d = $discountCode->getById($id);
    if ($d) {
        $discountCode->toggle($id, !$d['is_active']);
        gemaccAdminActionNotify(!$d['is_active'] ? 'کد تخفیف فعال شد' : 'کد تخفیف غیرفعال شد', ['شناسه کد'=>$id, 'کد'=>$d['code'] ?? '-'], $chatId);
        answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '✅ وضعیت تغییر کرد']);
    }
    exit('OK');
}

if (strpos($data, 'ADMIN_DISCOUNT_DELETE__') === 0) {
    $id = (int)str_replace('ADMIN_DISCOUNT_DELETE__', '', $data);
    $discountCode->delete($id);
    gemaccAdminActionNotify('کد تخفیف حذف شد', ['شناسه کد'=>$id], $chatId);
    answerCbOnceParams(['callback_query_id' => $cb['id'], 'text' => '✅ کد حذف شد', 'show_alert' => true]);
    exit('OK');
}

// ═══════════════════ تنظیمات بونوس و کش‌بک ═══════════════════

if ($data === 'ADMIN_BONUS_SETTINGS') {
    $bonusEnabled = getSetting('wallet_bonus_enabled', '0') === '1';
    $bonusPercent = getSetting('wallet_bonus_percent', '10');
    $bonusMinAmount = getSetting('wallet_bonus_min_amount', '100000');
    $cashbackEnabled = getSetting('cashback_enabled', '0') === '1';
    $cashbackPercent = getSetting('cashback_percent', '5');
    
    $txt = "🎁 **تنظیمات بونوس و کش‌بک**\n\n";
    
    $txt .= "━━━━━ 💰 بونوس شارژ ━━━━━\n";
    $txt .= "🔘 وضعیت: " . ($bonusEnabled ? '🟢 فعال' : '🔴 غیرفعال') . "\n";
    $txt .= "📊 درصد بونوس: {$bonusPercent}٪\n";
    $txt .= "💵 حداقل مبلغ: " . number_format($bonusMinAmount) . " تومان\n\n";
    
    $txt .= "━━━━━ 🎁 کش‌بک خرید ━━━━━\n";
    $txt .= "🔘 وضعیت: " . ($cashbackEnabled ? '🟢 فعال' : '🔴 غیرفعال') . "\n";
    $txt .= "📊 درصد کش‌بک: {$cashbackPercent}٪\n";
    
    $bonusToggleText = $bonusEnabled ? '🔴 غیرفعال بونوس' : '🟢 فعال بونوس';
    $cashbackToggleText = $cashbackEnabled ? '🔴 غیرفعال کش‌بک' : '🟢 فعال کش‌بک';
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => $bonusToggleText, 'callback_data' => 'ADMIN_TOGGLE_WALLET_BONUS']],
                [['text' => '✏️ تغییر درصد بونوس', 'callback_data' => 'ADMIN_EDIT_BONUS_PERCENT']],
                [['text' => '✏️ تغییر حداقل مبلغ', 'callback_data' => 'ADMIN_EDIT_BONUS_MIN']],
                [['text' => $cashbackToggleText, 'callback_data' => 'ADMIN_TOGGLE_CASHBACK']],
                [['text' => '✏️ تغییر درصد کش‌بک', 'callback_data' => 'ADMIN_EDIT_CASHBACK_PERCENT']],
                [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']],
            ],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_TOGGLE_WALLET_BONUS') {
    $current = getSetting('wallet_bonus_enabled', '0');
    $newValue = $current === '1' ? '0' : '1';
    setSetting('wallet_bonus_enabled', $newValue);
    
    // رفرش UI فوری
    $bonusEnabled = $newValue === '1';
    $bonusPercent = getSetting('wallet_bonus_percent', '10');
    $bonusMinAmount = getSetting('wallet_bonus_min_amount', '100000');
    $cashbackEnabled = getSetting('cashback_enabled', '0') === '1';
    $cashbackPercent = getSetting('cashback_percent', '5');
    
    $txt = "🎁 **تنظیمات بونوس و کش‌بک**\n\n";
    $txt .= "━━━━━ 💰 بونوس شارژ ━━━━━\n";
    $txt .= "🔘 وضعیت: " . ($bonusEnabled ? '🟢 فعال' : '🔴 غیرفعال') . "\n";
    $txt .= "📊 درصد بونوس: {$bonusPercent}٪\n";
    $txt .= "💵 حداقل مبلغ: " . number_format($bonusMinAmount) . " تومان\n\n";
    $txt .= "━━━━━ 🎁 کش‌بک خرید ━━━━━\n";
    $txt .= "🔘 وضعیت: " . ($cashbackEnabled ? '🟢 فعال' : '🔴 غیرفعال') . "\n";
    $txt .= "📊 درصد کش‌بک: {$cashbackPercent}٪\n";
    
    $bonusToggleText = $bonusEnabled ? '🔴 غیرفعال بونوس' : '🟢 فعال بونوس';
    $cashbackToggleText = $cashbackEnabled ? '🔴 غیرفعال کش‌بک' : '🟢 فعال کش‌بک';
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => $bonusToggleText, 'callback_data' => 'ADMIN_TOGGLE_WALLET_BONUS']],
                [['text' => '✏️ تغییر درصد بونوس', 'callback_data' => 'ADMIN_EDIT_BONUS_PERCENT']],
                [['text' => '✏️ تغییر حداقل مبلغ', 'callback_data' => 'ADMIN_EDIT_BONUS_MIN']],
                [['text' => $cashbackToggleText, 'callback_data' => 'ADMIN_TOGGLE_CASHBACK']],
                [['text' => '✏️ تغییر درصد کش‌بک', 'callback_data' => 'ADMIN_EDIT_CASHBACK_PERCENT']],
                [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']],
            ],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_TOGGLE_CASHBACK') {
    $current = getSetting('cashback_enabled', '0');
    $newValue = $current === '1' ? '0' : '1';
    setSetting('cashback_enabled', $newValue);
    
    // رفرش UI فوری
    $bonusEnabled = getSetting('wallet_bonus_enabled', '0') === '1';
    $bonusPercent = getSetting('wallet_bonus_percent', '10');
    $bonusMinAmount = getSetting('wallet_bonus_min_amount', '100000');
    $cashbackEnabled = $newValue === '1';
    $cashbackPercent = getSetting('cashback_percent', '5');
    
    $txt = "🎁 **تنظیمات بونوس و کش‌بک**\n\n";
    $txt .= "━━━━━ 💰 بونوس شارژ ━━━━━\n";
    $txt .= "🔘 وضعیت: " . ($bonusEnabled ? '🟢 فعال' : '🔴 غیرفعال') . "\n";
    $txt .= "📊 درصد بونوس: {$bonusPercent}٪\n";
    $txt .= "💵 حداقل مبلغ: " . number_format($bonusMinAmount) . " تومان\n\n";
    $txt .= "━━━━━ 🎁 کش‌بک خرید ━━━━━\n";
    $txt .= "🔘 وضعیت: " . ($cashbackEnabled ? '🟢 فعال' : '🔴 غیرفعال') . "\n";
    $txt .= "📊 درصد کش‌بک: {$cashbackPercent}٪\n";
    
    $bonusToggleText = $bonusEnabled ? '🔴 غیرفعال بونوس' : '🟢 فعال بونوس';
    $cashbackToggleText = $cashbackEnabled ? '🔴 غیرفعال کش‌بک' : '🟢 فعال کش‌بک';
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => $bonusToggleText, 'callback_data' => 'ADMIN_TOGGLE_WALLET_BONUS']],
                [['text' => '✏️ تغییر درصد بونوس', 'callback_data' => 'ADMIN_EDIT_BONUS_PERCENT']],
                [['text' => '✏️ تغییر حداقل مبلغ', 'callback_data' => 'ADMIN_EDIT_BONUS_MIN']],
                [['text' => $cashbackToggleText, 'callback_data' => 'ADMIN_TOGGLE_CASHBACK']],
                [['text' => '✏️ تغییر درصد کش‌بک', 'callback_data' => 'ADMIN_EDIT_CASHBACK_PERCENT']],
                [['text' => '◀️ بازگشت', 'callback_data' => 'ADMIN']],
            ],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_EDIT_BONUS_PERCENT') {
    setUserMode($chatId, 'ADMIN_EDIT_BONUS_PERCENT', []);
    
    $txt = "📊 **تغییر درصد بونوس**\n\n";
    $txt .= "درصد جدید را وارد کنید:\n";
    $txt .= "مثال: `10` برای ۱۰٪";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_BONUS_SETTINGS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_EDIT_BONUS_MIN') {
    setUserMode($chatId, 'ADMIN_EDIT_BONUS_MIN', []);
    
    $txt = "💵 **تغییر حداقل مبلغ بونوس**\n\n";
    $txt .= "حداقل مبلغ را به تومان وارد کنید:\n";
    $txt .= "مثال: `100000` برای ۱۰۰ هزار تومان";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_BONUS_SETTINGS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

if ($data === 'ADMIN_EDIT_CASHBACK_PERCENT') {
    setUserMode($chatId, 'ADMIN_EDIT_CASHBACK_PERCENT', []);
    
    $txt = "📊 **تغییر درصد کش‌بک**\n\n";
    $txt .= "درصد جدید را وارد کنید:\n";
    $txt .= "مثال: `5` برای ۵٪";
    
    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => $txt,
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode([
            'inline_keyboard' => [[['text' => '❌ انصراف', 'callback_data' => 'ADMIN_BONUS_SETTINGS']]],
        ], JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}

// ═══════════════════ پاسخ به تیکت ═══════════════════

if (strpos($data, 'ADMIN_REPLY__') === 0) {
    $parts = explode('__', $data);
    $ticketId = (int)$parts[1];
    $userId = (int)$parts[2];
    
    setUserMode($chatId, 'ADMIN_REPLY_TICKET', ['ticket_id' => $ticketId, 'user_id' => $userId]);
    
    tg('sendMessage', [
        'chat_id' => $chatId,
        'text'    => "✉️ پاسخ خود را ارسال کنید:\n\n(برای لغو /cancel بزنید)",
    ]);
    exit('OK');
}

// ═══════════════════ پاکسازی کش ═══════════════════

if ($data === 'ADMIN_CLEAR_CACHE') {
    $startTime = microtime(true);
    require_once dirname(__DIR__) . '/CacheCleaner.php';
    $stats = gemacc_clear_runtime_cache($pdo, [
        'receipt_retention_days' => 3,
        'delete_finished_receipts' => true,
    ]);
    $duration = (int)round((microtime(true) - $startTime) * 1000);
    $clearedItems = (int)($stats['deleted_files'] ?? 0) + (int)($stats['state_items'] ?? 0);
    $freed = $stats['freed_human'] ?? '0 B';

    logError("Cache cleared by admin {$chatId}: files=" . ($stats['deleted_files'] ?? 0) . " freed={$freed} duration={$duration}ms");

    answerCbOnceParams([
        'callback_query_id' => $cb['id'],
        'text'              => "✅ کش پاک شد | {$clearedItems} آیتم | {$freed}",
        'show_alert'        => true,
    ]);

    tg('editMessageText', [
        'chat_id'      => $chatId,
        'message_id'   => $msgId,
        'text'         => "👑 **پنل مدیریت**\n\n✅ پاکسازی کش انجام شد.\n\n• فایل‌های حذف‌شده: " . (int)($stats['deleted_files'] ?? 0) . "\n• رسیدهای حذف‌شده: " . (int)($stats['uploads_deleted'] ?? 0) . "\n• لاگ‌های حذف‌شده: " . (int)($stats['logs_deleted'] ?? 0) . "\n• آیتم‌های state: " . (int)($stats['state_items'] ?? 0) . "\n• حجم آزادشده: {$freed}\n• رسیدهای در انتظار حفظ‌شده: " . (int)($stats['skipped_pending_receipts'] ?? 0) . "\n• زمان اجرا: {$duration}ms",
        'parse_mode'   => 'Markdown',
        'reply_markup' => json_encode(kbAdminPanel(), JSON_UNESCAPED_UNICODE),
    ]);
    exit('OK');
}
