<?php

function handleMessage($message)
{
    global $unfinished_admins;

    $chatId = $message["chat"]["id"];
    if (isMaintenanceMode() && !isFounder($chatId)) {
        sendMessage($chatId, "🛠 <b>ربات در حال بروزرسانی است.</b>\n\nلطفاً کمی بعد دوباره تلاش کنید.");
        return;
    }
    $from = $message["from"] ?? [];
    $username = $from["username"] ?? "ندارد";
    $firstName = $from["first_name"] ?? "ندارد";
    $text = isset($message["text"]) ? cleanTelegramText($message["text"]) : '';

    // هر پیامی که کاربر می‌فرستد، برای آمار در users ذخیره می‌شود.
    saveUser($chatId, [
        "username" => $username,
        "first_name" => $firstName,
        "last_seen" => date('Y-m-d H:i:s'),
    ]);

    if ($text === "/start") {
        // /start همیشه هر جریان نیمه‌کاره، از جمله پرسش‌های ثبت اطلاعات را لغو می‌کند.
        deleteUser($chatId);
        clearAdminState($chatId);
        if (!isAdmin($chatId) && !isOwner($chatId) && !requireChannelMembership($chatId)) {
            saveUser($chatId, ["channel_verified" => false]);
            sendChannelGate($chatId);
            return;
        }
        saveUser($chatId, ["channel_verified" => true]);
        saveUser($chatId, [
            "username" => $username,
            "first_name" => $firstName,
            "step" => 0,
            "last_seen" => date('Y-m-d H:i:s'),
        ]);

        if (isAdmin($chatId)) {
            sendMessage($chatId, "سلام ادمین 👑\nبه بازیرو خوش آمدی.", mainMenu(true));
        } else {
            sendMessage($chatId, "سلام 👋\nبه ربات بازیرو خوش آمدید.", mainMenu());
        }
        return;
    }

    // کاربران عادی تا زمان عضویت در کانال اجازه عبور از گیت را ندارند.
    if (!isAdmin($chatId) && !isOwner($chatId) && !channelMembershipGuard($chatId)) return;

    // -------------------------
    // Cancel — must be handled BEFORE any admin/question state so the
    // cancel button can never be recorded as an answer to a question.
    // -------------------------
    if ($text === "❌ منصرف شدن") {
        deleteUser($chatId);
        clearAdminState($chatId);
        sendMessage($chatId, "لغو شد ✅", isAdmin($chatId) ? adminMenu($chatId) : mainMenu());
        return;
    }

    // -------------------------
    // Admin states: photo / text inputs
    // -------------------------
    if (isAdmin($chatId)) {
        $state = getAdminState($chatId);
        if (!empty($state["action"])) {
            if (handleAdminState($message, $state)) return;
        }
    }

    // -------------------------
    // Admin reply menu
    // -------------------------
    if (isAdmin($chatId)) {
        // Admin navigation is handled as reply-keyboard text too, so it keeps
        // working even if Telegram/client has stale inline keyboards.
        if ($text === "🎮 مدیریت بازی‌ها" || mb_strpos($text, "مدیریت بازی") !== false) {
            clearAdminState($chatId);
            if (isOwner($chatId)) {
                sendMessage($chatId, "🎮 <b>مدیریت بازی‌ها</b>\n\nیک گزینه را انتخاب کن:", adminGamesMenu());
            } else {
                $ids = getAdminGameIds($chatId);
                if (count($ids) === 1) showAdminGame($chatId, $ids[0]);
                else sendMessage($chatId, "⛔ بازی اختصاصی برای این ادمین تنظیم نشده است.", adminMenu($chatId));
            }
            return;
        }
        if ($text === "📋 لیست / ویرایش بازی‌ها" || $text === "📋 لیست بازی‌ها") {
            clearAdminState($chatId);
            showAdminGames($chatId);
            return;
        }
        if ($text === "➕ افزودن بازی") {
            clearAdminState($chatId);
            setAdminState($chatId, ["action" => "add_game_photo", "data" => []]);
            sendMessage($chatId, "➕ <b>افزودن بازی</b>\n\nاول پوستر بازی را به صورت عکس بفرست.", cancelButton());
            return;
        }
        if ($text === "🆕 مدیریت جدیدترین‌ها") {
            showAdminCategory($chatId, 'latest');
            return;
        }
        if ($text === "🔥 مدیریت بازی‌های در حال رفتن") {
            showAdminCategory($chatId, 'going');
            return;
        }
        if ($text === "↩️ برگشت به پنل ادمین") {
            clearAdminState($chatId);
            sendMessage($chatId, "👑 <b>پنل مدیریت بازیرو</b>", adminMenu($chatId));
            return;
        }
        if ($text === "❓ مدیریت سوالات") {
            if (isOwner($chatId)) {
                sendMessage($chatId, "❓ <b>مدیریت سوالات</b>\n\nسوالات هر بازی کاملاً مستقل هستند و می‌تونی برای هر بازی سوال‌های متفاوت بسازی.", adminQuestionsMenu());
            } else {
                $ids = getAdminGameIds($chatId);
                if (count($ids) === 1) showAdminQuestions($chatId, $ids[0]);
                else sendMessage($chatId, "⛔ بازی اختصاصی برای این ادمین تنظیم نشده است.", adminMenu($chatId));
            }
            return;
        }
        if ($text === "🎟 مدیریت کد تخفیف") {
            sendMessage($chatId, "🎟 <b>مدیریت کدهای تخفیف</b>", adminDiscountMenu());
            return;
        }
        if ($text === "📋 مدیریت رزروها" || $text === "📋 نمایش اطلاعات ارسال شده") {
            showSubmittedInfo($chatId);
            return;
        }
        if ($text === "📊 آمار ربات") {
            sendMessage($chatId, adminStatsText(), adminMenu($chatId));
            return;
        }
        if ($text === "📢 پیام همگانی") {
            setAdminState($chatId, ["action" => "broadcast"]);
            sendMessage($chatId, "📢 متن پیام همگانی را بفرست:", cancelButton());
            return;
        }
        if ($text === "👤 پیام به کاربر") {
            setAdminState($chatId, ["action" => "single_user_id"]);
            sendMessage($chatId, "🆔 آیدی عددی کاربر را بفرست:", cancelButton());
            return;
        }
        if ($text === "🛠 کنترل سیستم" && isFounder($chatId)) {
            clearAdminState($chatId);
            sendMessage($chatId, "🛠 <b>کنترل سیستم ربات</b>\n\nوضعیت فعلی: " . (isMaintenanceMode() ? "🔴 حالت بروزرسانی" : "🟢 فعال"), founderSystemMenu($chatId));
            return;
        }
        if ($text === "👑 ادمین") {
            clearAdminState($chatId);
            sendMessage($chatId, "👑 <b>پنل مدیریت بازیرو</b>\n\nیکی از بخش‌های مدیریت را انتخاب کن:", adminMenu($chatId));
            return;
        }
        if ($text === "🏠 منوی کاربری") {
            clearAdminState($chatId);
            saveUser($chatId, [
                "step" => 0,
                "flow" => "",
                "booking_question_index" => 0,
                "booking_answers" => [],
            ]);
            sendMessage($chatId, "🏠 منوی کاربری:", mainMenu(true));
            return;
        }
    }

    // -------------------------
    // User room menu
    // -------------------------
    if ($text === "🎭 اتاق فرار") {
        sendMessage($chatId, "🎭 <b>اتاق فرار</b>\n\nیکی از گزینه‌ها را انتخاب کن:", roomMenu());
        return;
    }

    if ($text === "☕ کافه بازی") {
        sendMessage($chatId, "⏳ این بخش فعلاً در حال بروزرسانی است.", mainMenu());
        return;
    }

    if ($text === "📞 پشتیبانی") {
        sendMessage($chatId, "📞 <b>پشتیبانی بازیرو</b>\n\nبرای ارتباط با پشتیبانی:\n@Baziro_Support", mainMenu());
        return;
    }

    // Compatibility with the previous version's keyboards.
    // Old clients can keep the old reply keyboard for a while.
    if ($text === "ناتمام") {
        $game = null;
        foreach (getGames() as $g) {
            if (($g["slug"] ?? '') === 'natamam' || ($g["name"] ?? '') === 'ناتمام') {
                $game = $g;
                break;
            }
        }
        if ($game) sendGameCard($chatId, $game, "rooms:all");
        else sendMessage($chatId, "بازی ناتمام پیدا نشد.", mainMenu());
        return;
    }

    if ($text === "کافه بازی") {
        sendMessage($chatId, "⏳ این بخش فعلاً در حال بروزرسانی است.", mainMenu());
        return;
    }

    if ($text === "📋 مدیریت درخواست‌ها" && isAdmin($chatId)) {
        showAdminBookings($chatId);
        return;
    }

    // -------------------------
    // Discount input flow
    // -------------------------
    $user = getUser($chatId);

    // After the user selects a game for a discount code, ask for the
    // customer's full name BEFORE consuming the code. The usage counter is
    // incremented only after a valid name is received.
    if (($user["flow"] ?? '') === 'discount_name') {
        $fullName = trim(preg_replace('/\s+/', ' ', (string)$text));
        if ($fullName === '' || mb_strlen($fullName) < 3) {
            sendMessage($chatId, "❌ لطفاً نام و نام خانوادگی را کامل وارد کن.\nمثال: <code>علی رضایی</code>", cancelButton());
            return;
        }

        $discountId = (int)($user['discount_id'] ?? 0);
        $gameId = (int)($user['discount_game_id'] ?? 0);
        $discount = getDiscount($discountId);
        $game = getGame($gameId);
        if (!$discount || !$game || empty($game['active']) || !in_array($gameId, array_map('intval', $discount['game_ids'] ?? []), true)) {
            deleteUser($chatId);
            sendMessage($chatId, "❌ این بازی یا کد تخفیف دیگر در دسترس نیست.", mainMenu());
            return;
        }
        if (userUsedDiscount($chatId, $discountId)) {
            deleteUser($chatId);
            sendMessage($chatId, "⚠️ این کد تخفیف را قبلاً استفاده کرده‌ای.", mainMenu());
            return;
        }
        $username = !empty($from['username']) ? '@' . $from['username'] : 'ندارد';
        $userId = (string)$chatId;

        // مصرف کد فقط بعد از دریافت نام کامل انجام می‌شود. اطلاعات نام/یوزرنیم
        // نیز همراه رکورد مصرف ذخیره می‌شود تا بعداً قابل پیگیری باشد.
        if (!useDiscount($chatId, $discountId, $gameId, [
            'full_name' => $fullName,
            'username' => $username,
            'user_id' => $userId,
        ])) {
            deleteUser($chatId);
            sendMessage($chatId, "❌ این کد تخفیف دیگر قابل استفاده نیست؛ سقف استفاده آن تکمیل شده یا منقضی شده است.", mainMenu());
            return;
        }

        // اول اطلاعات را برای خود کاربر بفرست. خطای ارسال اعلان به ادمین نباید
        // باعث شود کاربر در میانه فرآیند گیر کند. اگر ارسال به کاربر کامل شکست
        // بخورد، مصرف کد برگردانده می‌شود.
        $userInfoResult = sendDiscountGameInfo($chatId, $game, $discount, $fullName);
        if (!is_array($userInfoResult) || empty($userInfoResult['ok'])) {
            rollbackDiscountUsage($chatId, $discountId);
            sendMessage($chatId, "❌ ارسال اطلاعات رزرو با مشکل مواجه شد. کد تخفیف دوباره قابل استفاده است؛ لطفاً دوباره تلاش کن.", mainMenu());
            return;
        }

        $adminNotice = "🎟 <b>استفاده از کد تخفیف</b>\n\n";
        $adminNotice .= "🎮 بازی: <b>" . escapeHtml($game['name']) . "</b>\n";
        $adminNotice .= "🎟 کد: <code>" . escapeHtml($discount['code'] ?? '') . "</code>\n";
        $discountValue = ($discount['value'] ?? 0) . (($discount['type'] ?? 'percent') === 'percent' ? '%' : ' تومان');
        $adminNotice .= "💸 درصد/مقدار تخفیف: <b>" . escapeHtml($discountValue) . "</b>\n";
        $adminNotice .= "👤 نام و نام خانوادگی: <b>" . escapeHtml($fullName) . "</b>\n";
        $adminNotice .= "🆔 ID: <code>" . escapeHtml($userId) . "</code>\n";
        $adminNotice .= "🔗 Username: " . escapeHtml($username);

        // اعلان‌ها مستقل از پاسخ کاربر هستند؛ یک ادمین خراب/مسدود نباید
        // جریان کاربر را متوقف کند. خطاها فقط در لاگ ثبت می‌شوند.
        sendToAdmins($adminNotice, $gameId);

        deleteUser($chatId);
        return;
    }

    if (($user["flow"] ?? '') === 'discount_code') {
        $discount = findDiscountByCode($text);
        if (!discountIsValid($discount)) {
            sendMessage($chatId, "❌ این کد تخفیف معتبر نیست، منقضی شده یا سقف استفاده‌اش پر شده است.\n\nکد دیگری وارد کن:", cancelButton());
            return;
        }

        if (userUsedDiscount($chatId, $discount["id"])) {
            sendMessage($chatId, "⚠️ این کد تخفیف را قبلاً استفاده کرده‌ای.", mainMenu());
            deleteUser($chatId);
            return;
        }

        saveUser($chatId, [
            "flow" => "discount_games",
            "discount_id" => $discount["id"],
            "step" => 0,
        ]);

        $games = discountGames($discount);
        if (!$games) {
            deleteUser($chatId);
            sendMessage($chatId, "⚠️ این کد در حال حاضر برای هیچ بازی فعالی قابل استفاده نیست.", mainMenu());
            return;
        }

        $textOut = "🎟 <b>کد " . escapeHtml($discount["code"]) . " تأیید شد.</b>\n\n";
        $textOut .= "تخفیف: " . escapeHtml(($discount["value"] ?? 0) . (($discount["type"] ?? 'percent') === 'percent' ? '%' : ' تومان')) . "\n\n";
        $textOut .= "بازی‌های شامل این کد:\n\n";
        $rows = [];
        foreach ($games as $game) {
            $phone = !empty($game["phone"]) ? "\n📞 " . phoneLink($game["phone"]) : '';
            $textOut .= "🎮 <b>" . escapeHtml($game["name"]) . "</b>" . $phone . "\n";
            $rows[] = [["text" => "🎟 " . $game["name"], "callback_data" => "discount_game:" . $game["id"] . ":" . $discount["id"]]];
        }
        $rows[] = [["text" => "↩️ منوی اتاق فرار", "callback_data" => "rooms:menu"]];
        sendMessage($chatId, $textOut, inlineKeyboard($rows));
        return;
    }

    // -------------------------
    // User reservation questionnaire
    // -------------------------
    if (($user["flow"] ?? '') === 'booking') {
        // Booking flow remains active until the user explicitly cancels it
        // or sends /start. The cancel handler above runs before this block.
        handleBookingAnswer($message, $user);
        return;
    }

    // Never leave a user without a response. This is especially important
    // when Telegram still has an old keyboard cached on the client.
    if (!isAdmin($chatId)) {
        sendMessage($chatId, "یکی از گزینه‌های منو را انتخاب کن 👇", isAdmin($chatId) ? mainMenu(true) : mainMenu());
    }
}

function handleCallback($callback)
{
    $callbackId = $callback['id'] ?? '';
    $fromId = (int)($callback['from']['id'] ?? 0);
    $chatId = (int)($callback['message']['chat']['id'] ?? $fromId);
    $data = $callback['data'] ?? '';
    if (isMaintenanceMode() && !isFounder($fromId) && !isFounder($chatId)) {
        if ($callbackId !== '') answerCallback($callbackId, "🛠 ربات در حال بروزرسانی است.", true);
        return;
    }
    $callbackId = $callback["id"];
    $data = $callback["data"] ?? '';
    $message = $callback["message"] ?? [];
    $fromId = (int)($callback["from"]["id"] ?? 0);
    $chatId = $message["chat"]["id"] ?? $fromId;
    $messageId = $message["message_id"] ?? 0;

    answerCallback($callbackId);

    if ($data === 'noop') return;

    if (strpos($data, 'copyphone:') === 0) {
        $game = getGame((int)substr($data, strlen('copyphone:')));
        if ($game && !empty($game['phone'])) {
            $phone = trim((string)$game['phone']);
            // Send as plain text so the user can immediately long-press and copy it.
            sendMessage($chatId, "📞 " . escapeHtml($phone));
            answerCallback($callbackId, "📋 شماره ارسال شد؛ برای کپی روی شماره نگه دار.");
        } else {
            answerCallback($callbackId, "شماره تماس ثبت نشده است.", true);
        }
        return;
    }

    if ($data === 'channel:check') {
        if (isAdmin($fromId) || isOwner($fromId) || !channelConfigured()) {
            sendMessage($fromId, "✅ عضویت تأیید شد. خوش آمدی 👋", mainMenu(isAdmin($fromId) || isOwner($fromId)));
            saveUser($fromId, ["channel_verified" => true]);
            return;
        }
        if (isChannelMember($fromId)) {
            saveUser($fromId, ["channel_verified" => true]);
            sendMessage($fromId, "✅ عضویتت تأیید شد. حالا می‌تونی از ربات استفاده کنی 👋", mainMenu(false));
        } else {
            sendChannelGate($fromId);
        }
        return;
    }

    if (!isAdmin($fromId) && !isOwner($fromId) && !channelMembershipGuard($fromId)) return;

    // -------------------------
    // Public room menus
    // -------------------------
    if ($data === 'rooms:menu') {
        sendMessage($chatId, "🎭 <b>اتاق فرار</b>", roomMenu());
        return;
    }

    if ($data === 'rooms:all') {
        $games = array_values(array_filter(getGames(), fn($g) => !empty($g['active'])));
        shuffle($games);
        $out = $games ? "🎮 <b>همه بازی‌ها</b>\n\nروی بازی موردنظر بزن تا اطلاعات و پوسترش را ببینی:" : "🎮 <b>همه بازی‌ها</b>\n\nفعلاً بازی فعالی وجود ندارد.";
        sendMessage($chatId, $out, gamesButtons($games, 'rooms:menu'));
        return;
    }

    if ($data === 'rooms:latest') {
        $games = array_values(array_filter(getGames(), fn($g) => !empty($g['active']) && !empty($g['latest'])));
        shuffle($games);
        $out = $games ? listGamesText($games, "🆕 <b>جدیدترین بازی‌ها</b>") : "🆕 <b>جدیدترین بازی‌ها</b>\n\nفعلاً چیزی اینجا نیست.";
        sendMessage($chatId, $out, gamesButtons($games, 'rooms:menu'));
        return;
    }

    if ($data === 'rooms:going') {
        $games = array_values(array_filter(getGames(), fn($g) => !empty($g['active']) && !empty($g['going'])));
        shuffle($games);
        $out = $games ? listGamesText($games, "🔥 <b>بازی‌هایی که دارن میرن</b>") : "🔥 <b>بازی‌هایی که دارن میرن</b>\n\nفعلاً همه بازی‌ها پیشمون هستن.";
        sendMessage($chatId, $out, gamesButtons($games, 'rooms:menu'));
        return;
    }

    if ($data === 'rooms:reserve') {
        $games = array_values(array_filter(getGames(), fn($g) => !empty($g['active']) && !empty($g['reservation_enabled'])));
        $rows = [];
        foreach ($games as $game) $rows[] = [["text" => "🎮 " . $game["name"], "callback_data" => "reserve_start:" . $game["id"]]];
        $rows[] = [["text" => "↩️ برگشت", "callback_data" => "rooms:menu"]];
        sendMessage($chatId, $games ? "📝کدوم بازی رزرو کردی؟\nیادت باشه اطلاعاتت رو دقیق و کامل برامون بفرستی این کار باعث میشه بازی بهتر براتون اجرا بشه" : "فعلاً بازی قابل ثبت اطلاعاتی نداریم.", inlineKeyboard($rows));
        return;
    }

    if ($data === 'discount:enter') {
        saveUser($chatId, ["flow" => "discount_code", "step" => 0]);
        sendMessage($chatId, "🎟 کد تخفیف را وارد کن:", cancelButton());
        return;
    }

    if (strpos($data, 'suggested:list:') === 0) {
        $sourceId = (int)substr($data, strlen('suggested:list:'));
        $source = getGame($sourceId);
        if (!$source || empty($source['active'])) { sendMessage($chatId, 'این بازی دیگر فعال نیست.', mainMenu()); return; }
        $suggested = suggestedGames($sourceId);
        $rows = [];
        foreach ($suggested as $g) { $rows[] = [["text" => "🎮 " . $g['name'], "callback_data" => "game:suggested:" . $g['id'] . ":" . $sourceId]]; }
        $rows[] = [["text" => "↩️ برگشت", "callback_data" => "rooms:all"]];
        $msg = $suggested ? "💡 <b>پیشنهادهای " . escapeHtml($source['name']) . "</b>": "💡 <b>پیشنهادهای " . escapeHtml($source['name']) . "</b>\n\nفعلاً بازی پیشنهادی ثبت نشده.";
        sendMessage($chatId, $msg, inlineKeyboard($rows));
        return;
    }

    if (strpos($data, 'game:suggested:') === 0) {
        $parts = explode(':', $data);
        $targetId = (int)($parts[2] ?? 0); $sourceId = (int)($parts[3] ?? 0);
        $game = getGame($targetId); $source = getGame($sourceId);
        if ($game && !empty($game['active'])) sendGameCard($chatId, $game, 'suggested:list:' . $sourceId);
        return;
    }

    if (strpos($data, 'game:') === 0) {
        $game = getGame((int)substr($data, 5));
        if ($game && !empty($game['active'])) sendGameCard($chatId, $game, 'rooms:all');
        return;
    }

    if (strpos($data, 'reserve:') === 0) {
        $game = getGame((int)substr($data, 8));
        if (!$game || empty($game['active'])) {
            sendMessage($chatId, "این بازی دیگر فعال نیست.", mainMenu());
            return;
        }
        // پیام رزرو را فقط به عنوان متن سفارشی نگه می‌داریم؛ اطلاعات تماس/آدرس
        // و جمله معرفی بازیرو همیشه یک‌بار و به صورت استاندارد اضافه می‌شوند.
        // این کار جلوی دوباره‌نمایش‌دادن متن قدیمیِ رزرو را می‌گیرد.
        $custom = trim((string)($game['reservation_message'] ?? ''));
        $phone = trim((string)($game['phone'] ?? ''));
        $address = trim((string)($game['address'] ?? ''));
        if ($custom !== '') {
            $customLines = preg_split('/\R/u', $custom);
            $kept = [];
            foreach ($customLines as $line) {
                $plain = trim(strip_tags($line));
                if ($plain === '') continue;
                if (preg_match('/^(?:🎟\s*)?رزرو\s*' . preg_quote((string)$game['name'], '/') . '\s*$/u', $plain)) continue;
                if ($phone !== '' && strpos($plain, $phone) !== false) continue;
                if ($address !== '' && strpos($plain, $address) !== false) continue;
                if (preg_match('/^📞?\s*شماره تماس مجموعه\s*:/u', $plain)) continue;
                if (preg_match('/^📍?\s*آدرس مجموعه\s*:/u', $plain)) continue;
                if (preg_match('/^برای رزرو با (?:مجموعه )?تماس بگیر\.?$/u', $plain)) continue;
                if (strpos($plain, 'از طرف بازیرو') !== false) continue;
                $kept[] = $line;
            }
            $custom = trim(implode("\n", $kept));
        }
        $messageText = "🎟 <b>رزرو " . escapeHtml($game['name']) . "</b>\n\n";
        if ($custom !== '') $messageText .= escapeHtml($custom) . "\n\n";
        if ($phone !== '') $messageText .= "📞 <b>شماره تماس مجموعه:</b> " . phoneLink($phone) . "\n";
        if ($address !== '') $messageText .= "📍 <b>آدرس مجموعه:</b> " . escapeHtml($address) . "\n";
        $messageText .= "\nبرای رزرو با مجموعه تماس بگیر.";
        $messageText .= "\n\n😉 <b>حتماً یادت باشه بگی از طرف بازیرو داری رزرو می‌کنی.</b>";
        sendMessage($chatId, $messageText, $phone !== '' ? phoneCallKeyboard($phone, (int)$game['id'], 'rooms:reserve') : inlineKeyboard([
            [["text" => "↩️ برگشت", "callback_data" => "rooms:reserve"]]
        ]));
        return;
    }

    if (strpos($data, 'reserve_start:') === 0) {
        $game = getGame((int)substr($data, strlen('reserve_start:')));
        if (!$game || empty($game['active'])) {
            sendMessage($chatId, "این بازی در حال حاضر فعال نیست. از لیست بازی‌ها یک بازی فعال را انتخاب کن.", mainMenu());
            return;
        }
        startBooking($chatId, $game);
        return;
    }

    if (strpos($data, 'discount_game:') === 0) {
        $parts = explode(':', $data);
        $gameId = (int)($parts[1] ?? 0);
        $discountId = (int)($parts[2] ?? 0);
        $discount = getDiscount($discountId);
        $game = getGame($gameId);
        if (!$discount || !$game || empty($game['active']) || !in_array($gameId, array_map('intval', $discount['game_ids'] ?? []), true)) {
            sendMessage($chatId, "این بازی برای این کد تخفیف قابل استفاده نیست.", mainMenu());
            return;
        }
        if (userUsedDiscount($chatId, $discountId)) {
            sendMessage($chatId, "⚠️ این کد تخفیف قبلاً استفاده شده است.", mainMenu());
            return;
        }

        // Do NOT consume the discount yet. First collect the customer's
        // full name; the counter/usage record is created only after that.
        saveUser($chatId, [
            "flow" => "discount_name",
            "discount_id" => $discountId,
            "discount_game_id" => $gameId,
            "discount_step" => 0,
        ]);
        answerCallback($callbackId, "نام و نام خانوادگی را وارد کنید.");
        sendMessage($chatId, "👤 <b>نام و نام خانوادگی</b> را برای ثبت رزرو با کد تخفیف وارد کن:\n\nمثال: <code>علی رضایی</code>", cancelButton());
        return;
    }

    // -------------------------
    // Founder system controls
    // -------------------------
    if ($data === 'founder:system') {
        if (!isFounder($chatId)) { answerCallback($callbackId, "⛔ فقط Founder.", true); return; }
        sendMessage($chatId, "🛠 <b>کنترل سیستم ربات</b>\n\nوضعیت فعلی: " . (isMaintenanceMode() ? "🔴 حالت بروزرسانی" : "🟢 فعال"), founderSystemMenu($chatId));
        return;
    }
    if (strpos($data, 'founder:') === 0) {
        if (!isFounder($chatId)) { answerCallback($callbackId, "⛔ فقط Founder.", true); return; }
        if ($data === 'founder:restart') {
            answerCallback($callbackId, "🔄 در حال راه‌اندازی مجدد Webhook...", false);
            $res = refreshWebhookRegistration();
            if ($res['ok']) {
                sendMessage($chatId, "✅ <b>Webhook با موفقیت دوباره ثبت شد.</b>\n\nربات روی cPanel نیازی به Restart Process ندارد؛ این عملیات معادل راه‌اندازی مجدد مسیر دریافت آپدیت‌هاست.", founderSystemMenu($chatId));
            } else {
                error_log('BOT webhook refresh failed: ' . json_encode($res, JSON_UNESCAPED_UNICODE));
                sendMessage($chatId, "❌ <b>راه‌اندازی مجدد Webhook ناموفق بود.</b>\n\n" . escapeHtml($res['message'] ?? 'خطای نامشخص'), founderSystemMenu($chatId));
            }
            return;
        }
        if ($data === 'founder:maintenance_on') {
            setMaintenanceMode(true, $chatId);
            answerCallback($callbackId, "🔴 حالت بروزرسانی فعال شد.", true);
            sendMessage($chatId, "🔴 <b>ربات وارد حالت بروزرسانی شد.</b>\n\nکاربران و Ownerها تا زمان روشن‌کردن مجدد نمی‌توانند از ربات استفاده کنند. فقط Founder دسترسی دارد.", founderSystemMenu($chatId));
            return;
        }
        if ($data === 'founder:maintenance_off') {
            setMaintenanceMode(false, $chatId);
            answerCallback($callbackId, "🟢 ربات روشن شد.", true);
            sendMessage($chatId, "🟢 <b>ربات دوباره فعال شد.</b>", founderSystemMenu($chatId));
            return;
        }
        if ($data === 'founder:status') {
            $res = webhookSystemStatus();
            $lines = [
                '📡 <b>وضعیت ربات</b>',
                '',
                '🤖 ربات: <code>' . escapeHtml($res['bot']) . '</code>',
                '⚙️ حالت: ' . ($res['maintenance'] ? '🔴 خاموشی/بروزرسانی' : '🟢 فعال'),
                '🔗 Webhook: ' . ($res['webhook_url'] !== '' ? '🟢 فعال' : '🔴 تنظیم نشده'),
                '📥 آپدیت‌های در انتظار: <code>' . (int)$res['pending'] . '</code>',
            ];
            if ($res['expected_url'] !== '' && $res['webhook_url'] !== $res['expected_url']) {
                $lines[] = '⚠️ آدرس فعلی Webhook با آدرس این فایل یکی نیست.';
            }
            if ($res['last_error'] !== '') $lines[] = '❗ خطای آخر: <code>' . escapeHtml($res['last_error']) . '</code>';
            if (!$res['ok']) $lines[] = '❌ ارتباط با Telegram API کامل نیست.';
            sendMessage($chatId, implode("\n", $lines), founderSystemMenu($chatId));
            return;
        }
    }

    // -------------------------
    // Admin callbacks
    // -------------------------
    // Authenticate callback buttons with callback.from.id. This is more
    // reliable than trusting the message chat id (especially with forwarded
    // or inline-originated messages).
    // In a private chat callback.from.id == message.chat.id. In group/forwarded
    // contexts they can differ, so accept either identity when checking admin.
    if (!isAdmin($fromId) && !isAdmin($chatId)) {
        answerCallback($callbackId, "⛔ دسترسی ندارید.", true);
        return;
    }
    $chatId = isAdmin($fromId) ? $fromId : $chatId;

    if ($data === 'admin:my_game') {
        $ids = getAdminGameIds($chatId);
        if (!$ids) { sendMessage($chatId, "⛔ بازی اختصاصی برای این ادمین تنظیم نشده است.", adminMenu($chatId)); return; }
        if (count($ids) === 1) { showAdminGame($chatId, $ids[0]); return; }
        $rows = [];
        foreach ($ids as $gid) { $g = getGame($gid); if ($g) $rows[] = [["text" => "🎮 " . $g['name'], "callback_data" => "admin:game:" . $gid]]; }
        $rows[] = [["text" => "↩️ برگشت", "callback_data" => "admin:back"]];
        sendMessage($chatId, "🎮 <b>بازی‌های اختصاص داده‌شده به شما</b>", inlineKeyboard($rows));
        return;
    }

    if ($data === 'admin:games') {
        showAdminGames($chatId);
        return;
    }
    if ($data === 'admin:back') {
        clearAdminState($chatId);
        sendMessage($chatId, "👑 <b>پنل مدیریت بازیرو</b>", adminMenu($chatId));
        return;
    }
    if ($data === 'admin:bookings' || $data === 'admin:submitted_info') {
        showSubmittedInfo($chatId);
        return;
    }
    if (strpos($data, 'admin:submitted_info:game:') === 0) {
        $gameId = (int)substr($data, strlen('admin:submitted_info:game:'));
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        showSubmittedInfo($chatId, $gameId);
        return;
    }
    if (strpos($data, 'admin:submitted_info:booking:') === 0) {
        $bookingId = (int)substr($data, strlen('admin:submitted_info:booking:'));
        showSubmittedBooking($chatId, $bookingId);
        return;
    }

    if (strpos($data, 'admin:bookings:game:') === 0) {
        $gameId = (int)substr($data, strlen('admin:bookings:game:'));
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        showAdminBookings($chatId, $gameId);
        return;
    }
    if ($data === 'admin:stats') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        sendMessage($chatId, adminStatsText(), adminMenu($chatId));
        return;
    }
    if ($data === 'admin:broadcast') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        setAdminState($chatId, ["action" => "broadcast"]);
        sendMessage($chatId, "📢 متن پیام همگانی را بفرست:", cancelButton());
        return;
    }
    if ($data === 'admin:single_user') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        setAdminState($chatId, ["action" => "single_user_id"]);
        sendMessage($chatId, "🆔 آیدی عددی کاربر را بفرست:", cancelButton());
        return;
    }
    if ($data === 'admin:user_menu') {
        clearAdminState($chatId);
        sendMessage($chatId, "🏠 منوی کاربری:", mainMenu(true));
        return;
    }
    if ($data === 'admin:manage_owners') {
        if (!isFounder($chatId)) { sendMessage($chatId, "⛔ فقط Founder می‌تواند Ownerها را مدیریت کند.", adminMenu($chatId)); return; }
        showOwnerManagement($chatId);
        return;
    }
    if ($data === 'admin:add_owner') {
        if (!isFounder($chatId)) { sendMessage($chatId, "⛔ فقط Founder.", adminMenu($chatId)); return; }
        setAdminState($chatId, ["action" => "add_owner_id"]);
        sendMessage($chatId, "👑 آیدی عددی Owner جدید را بفرست:", cancelButton());
        return;
    }
    if ($data === 'admin:remove_owner') {
        if (!isFounder($chatId)) { sendMessage($chatId, "⛔ فقط Founder.", adminMenu($chatId)); return; }
        showOwnerRemovalList($chatId);
        return;
    }
    if (strpos($data, 'admin:remove_owner_id:') === 0) {
        if (!isFounder($chatId)) { sendMessage($chatId, "⛔ فقط Founder.", adminMenu($chatId)); return; }
        $id = (int)substr($data, strlen('admin:remove_owner_id:'));
        if ($id === getFounderId()) { sendMessage($chatId, "⛔ Founder قابل حذف نیست.", adminMenu($chatId)); return; }
        removeOwner($id);
        // Remove from runtime admin records too, but never touch Founder.
        $records = array_values(array_filter(getAdminRecords(), fn($r) => (int)$r['id'] !== $id));
        saveAdminRecords($records);
        showOwnerManagement($chatId);
        return;
    }

    if ($data === 'admin:manage_admins') {
        if (!isOwner($chatId)) {
            sendMessage($chatId, "⛔ فقط Owner می‌تواند ادمین‌ها را مدیریت کند.", adminMenu($chatId));
            return;
        }
        showAdminManagement($chatId);
        return;
    }
    if ($data === 'admin:add_admin') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ فقط Owner.", adminMenu($chatId)); return; }
        setAdminState($chatId, ["action" => "add_admin_id"]);
        sendMessage($chatId, "🆔 آیدی عددی کاربر را برای ادمین شدن بفرست:", cancelButton());
        return;
    }
    if ($data === 'admin:remove_admin') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ فقط Owner.", adminMenu($chatId)); return; }
        showAdminRemovalList($chatId);
        return;
    }
    if (strpos($data, 'admin:remove_admin_id:') === 0) {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ فقط Owner.", adminMenu($chatId)); return; }
        $id = (int)substr($data, strlen('admin:remove_admin_id:'));
        if (removeAdmin($id)) sendMessage($chatId, "✅ ادمین <code>{$id}</code> حذف شد.", adminMenu($chatId));
        else sendMessage($chatId, "⛔ Owner قابل حذف نیست.", adminMenu($chatId));
        showAdminManagement($chatId);
        return;
    }

    if (strpos($data, 'admin:assign_admin:') === 0) {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ فقط Owner.", adminMenu($chatId)); return; }
        $gameId = (int)substr($data, strlen('admin:assign_admin:'));
        if (!getGame($gameId)) { sendMessage($chatId, "بازی پیدا نشد.", adminGamesMenu()); return; }
        setAdminState($chatId, ['action' => 'assign_game_admin_id', 'game_id' => $gameId]);
        sendMessage($chatId, "🆔 آیدی عددی ادمین این بازی را بفرست.\n\nاین ادمین فقط به همین بازی دسترسی خواهد داشت.", cancelButton());
        return;
    }
    if (strpos($data, 'admin:unassign_admin:') === 0) {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ فقط Owner.", adminMenu($chatId)); return; }
        $parts = explode(':', $data);
        $gameId = (int)($parts[2] ?? 0);
        $adminId = (int)($parts[3] ?? 0);
        if ($adminId > 0) unassignAdminFromGame($adminId, $gameId);
        showAdminGame($chatId, $gameId);
        return;
    }

    if ($data === 'admin:add_game') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ فقط Owner می‌تواند بازی جدید اضافه کند.", adminMenu($chatId)); return; }
        setAdminState($chatId, ["action" => "add_game_photo", "data" => []]);
        sendMessage($chatId, "➕ <b>افزودن بازی</b>\n\nاول پوستر بازی را به صورت عکس بفرست.", cancelButton());
        return;
    }
    if ($data === 'admin:latest') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        showAdminCategory($chatId, 'latest');
        return;
    }
    if ($data === 'admin:going') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        showAdminCategory($chatId, 'going');
        return;
    }
    if ($data === 'admin:add_question') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        $games = array_values(array_filter(getGames(), fn($g) => !empty($g['active'])));
        $rows = [];
        foreach ($games as $game) $rows[] = [["text" => "🎮 " . $game["name"], "callback_data" => "admin:qgame:" . $game["id"]]];
        sendMessage($chatId, "بازی موردنظر برای افزودن سوال را انتخاب کن:", inlineKeyboard($rows));
        return;
    }
    if ($data === 'admin:question_games') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        $games = getGames();
        $rows = [];
        foreach ($games as $game) $rows[] = [["text" => "❓ " . $game["name"], "callback_data" => "admin:qgame:" . $game["id"]]];
        sendMessage($chatId, "بازی موردنظر را انتخاب کن:", inlineKeyboard($rows));
        return;
    }
    if (strpos($data, 'admin:suggestions:') === 0) {
        $gameId = (int)substr($data, strlen('admin:suggestions:'));
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, '⛔ دسترسی این بازی را نداری.', true); return; }
        showSuggestionManagement($chatId, $gameId);
        return;
    }
    if (strpos($data, 'admin:suggestion:toggle:') === 0) {
        $parts = explode(':', $data);
        $sourceId = (int)($parts[3] ?? 0); $targetId = (int)($parts[4] ?? 0);
        if (!canManageGame($chatId, $sourceId)) { answerCallback($callbackId, '⛔ فقط ادمین همین بازی می‌تواند پیشنهادها را تغییر دهد.', true); return; }
        $source = getGame($sourceId);
        $ids = array_values(array_unique(array_map('intval', $source['suggested_games'] ?? [])));
        if (in_array($targetId, $ids, true)) $ids = array_values(array_filter($ids, fn($x) => $x !== $targetId)); else $ids[] = $targetId;
        setSuggestedGames($sourceId, $ids);
        showSuggestionManagement($chatId, $sourceId);
        return;
    }

    if (strpos($data, 'admin:qgame:') === 0) {
        $gameId = (int)substr($data, 12);
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        showAdminQuestions($chatId, $gameId);
        return;
    }
    if ($data === 'admin:add_discount') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        setAdminState($chatId, ["action" => "discount_code", "data" => []]);
        sendMessage($chatId, "🎟 کد تخفیف را وارد کن.\nمثال: <code>BAZI20</code>", cancelButton());
        return;
    }
    if ($data === 'admin:discounts') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        showAdminDiscounts($chatId);
        return;
    }
    if (strpos($data, 'admin:game:') === 0) {
        $gameId = (int)substr($data, 11);
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ این بازی برای شما نیست.", true); return; }
        showAdminGame($chatId, $gameId);
        return;
    }
    if (strpos($data, 'admin:delete_game:') === 0) {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ فقط Owner می‌تواند بازی حذف کند.", adminMenu($chatId)); return; }
        $id = (int)substr($data, strlen('admin:delete_game:'));
        $game = getGame($id);
        if ($game && (($game['slug'] ?? '') === 'natamam')) {
            sendMessage($chatId, "⚠️ بازی «ناتمام» هسته اصلی فرم ربات است و حذف نمی‌شود.", adminMenu($chatId));
            return;
        }
        deleteGame($id);
        sendMessage($chatId, "🗑 بازی حذف شد.", adminGamesMenu());
        return;
    }
    if (strpos($data, 'admin:toggle_game:') === 0) {
        $id = (int)substr($data, strlen('admin:toggle_game:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        $game = getGame($id);
        if ($game) updateGame($id, ["active" => empty($game['active'])]);
        showAdminGame($chatId, $id);
        return;
    }
    if (strpos($data, 'admin:toggle_latest:') === 0) {
        $id = (int)substr($data, strlen('admin:toggle_latest:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        $game = getGame($id);
        if ($game) updateGame($id, ["latest" => empty($game['latest'])]);
        showAdminCategory($chatId, 'latest');
        return;
    }
    if (strpos($data, 'admin:toggle_going:') === 0) {
        $id = (int)substr($data, strlen('admin:toggle_going:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        $game = getGame($id);
        if ($game) updateGame($id, ["going" => empty($game['going'])]);
        showAdminCategory($chatId, 'going');
        return;
    }
    if (strpos($data, 'admin:edit_name:') === 0) {
        $id = (int)substr($data, strlen('admin:edit_name:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        setAdminState($chatId, ["action" => "edit_game_name", "game_id" => $id]);
        sendMessage($chatId, "نام جدید بازی را بفرست:", cancelButton());
        return;
    }
    if (strpos($data, 'admin:edit_desc:') === 0) {
        $id = (int)substr($data, strlen('admin:edit_desc:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        setAdminState($chatId, ["action" => "edit_game_desc", "game_id" => $id]);
        sendMessage($chatId, "توضیحات جدید بازی را بفرست:", cancelButton());
        return;
    }
    if (strpos($data, 'admin:edit_phone:') === 0) {
        $id = (int)substr($data, strlen('admin:edit_phone:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        setAdminState($chatId, ["action" => "edit_game_phone", "game_id" => $id]);
        sendMessage($chatId, "شماره تماس این بازی را بفرست:", cancelButton());
        return;
    }
    if (strpos($data, 'admin:edit_address:') === 0) {
        $id = (int)substr($data, strlen('admin:edit_address:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        setAdminState($chatId, ['action' => 'edit_game_address', 'game_id' => $id]);
        sendMessage($chatId, "📍 آدرس جدید این بازی را بفرست:", cancelButton());
        return;
    }
    if (strpos($data, 'admin:edit_reservation_message:') === 0) {
        $id = (int)substr($data, strlen('admin:edit_reservation_message:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        setAdminState($chatId, ["action" => "edit_reservation_message", "game_id" => $id]);
        sendMessage($chatId, "📝 پیام رزرو را کامل بفرست. این پیام وقتی کاربر روی «رزرو بازی» بزند نمایش داده می‌شود.\n\nمثال:\n📞 تماس: 0912...\n👤 مسئول رزرو: ...\n📍 آدرس: ...\n\nهر متنی خواستی می‌توانی بنویسی.", cancelButton());
        return;
    }
    if (strpos($data, 'admin:edit_poster:') === 0) {
        $id = (int)substr($data, strlen('admin:edit_poster:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        setAdminState($chatId, ["action" => "edit_game_poster", "game_id" => $id]);
        sendMessage($chatId, "پوستر جدید را به صورت عکس بفرست:", cancelButton());
        return;
    }
    if (strpos($data, 'admin:edit_reservation:') === 0) {
        $id = (int)substr($data, strlen('admin:edit_reservation:'));
        if (!canManageGame($chatId, $id)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        $game = getGame($id);
        if ($game) updateGame($id, ["reservation_enabled" => empty($game['reservation_enabled'])]);
        showAdminGame($chatId, $id);
        return;
    }
    if (strpos($data, 'admin:edit_final_message:') === 0) {
        $gameId = (int)substr($data, strlen('admin:edit_final_message:'));
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ دسترسی نداری.", true); return; }
        setAdminState($chatId, ['action' => 'edit_final_message', 'game_id' => $gameId]);
        sendMessage($chatId, "📝 پیام آخر را بفرست. این پیام بعد از پاسخ آخرین سوال برای کاربر ارسال می‌شود.", cancelButton());
        return;
    }
    if (strpos($data, 'admin:set_final_file:') === 0) {
        $gameId = (int)substr($data, strlen('admin:set_final_file:'));
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ دسترسی نداری.", true); return; }
        setAdminState($chatId, ['action' => 'set_final_file', 'game_id' => $gameId]);
        sendMessage($chatId, "📎 فایل پایانی را بفرست. عکس، ویدیو، فایل، صدا، ویس، GIF یا استیکر قابل قبول است. اگر فایل نمی‌خواهی، این مرحله را لغو کن.", cancelButton());
        return;
    }
    if (strpos($data, 'admin:remove_final_file:') === 0) {
        $gameId = (int)substr($data, strlen('admin:remove_final_file:'));
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ دسترسی نداری.", true); return; }
        updateGame($gameId, ['final_file' => null, 'final_files' => []]);
        showAdminQuestions($chatId, $gameId);
        return;
    }

    if (strpos($data, 'admin:finish_final_files:') === 0) {
        $gameId = (int)substr($data, strlen('admin:finish_final_files:'));
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ دسترسی نداری.", true); return; }
        clearAdminState($chatId);
        sendMessage($chatId, "✅ افزودن فایل‌های پایانی تمام شد.", adminMenu($chatId));
        showAdminQuestions($chatId, $gameId);
        return;
    }

    if (strpos($data, 'admin:question:') === 0) {
        $qid = (int)substr($data, strlen('admin:question:'));
        $q = getQuestion($qid);
        if (!$q || !canManageGame($chatId, $q['game_id'])) { answerCallback($callbackId, "⛔ دسترسی این سوال را نداری.", true); return; }
        showAdminQuestion($chatId, $qid);
        return;
    }
    if (strpos($data, 'admin:delete_question:') === 0) {
        $id = (int)substr($data, strlen('admin:delete_question:'));
        $q = getQuestion($id);
        if (!$q || !canManageGame($chatId, $q['game_id'])) { answerCallback($callbackId, "⛔ دسترسی این سوال را نداری.", true); return; }
        $gameId = $q['game_id'] ?? 0;
        deleteQuestion($id);
        sendMessage($chatId, "🗑 سوال حذف شد.");
        showAdminQuestions($chatId, $gameId);
        return;
    }
    if (strpos($data, 'admin:edit_question:') === 0) {
        $id = (int)substr($data, strlen('admin:edit_question:'));
        $q = getQuestion($id);
        if (!$q || !canManageGame($chatId, $q['game_id'])) { answerCallback($callbackId, "⛔ دسترسی این سوال را نداری.", true); return; }
        setAdminState($chatId, ['action' => 'edit_question_text', 'question_id' => $id]);
        sendMessage($chatId, "📝 متن جدید سوال را بفرست:", cancelButton());
        return;
    }
    if (strpos($data, 'admin:addq:') === 0) {
        $gameId = (int)substr($data, strlen('admin:addq:'));
        if (!canManageGame($chatId, $gameId)) { answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
        setAdminState($chatId, ["action" => "add_question_text", "game_id" => $gameId]);
        sendMessage($chatId, "❓ متن سوال جدید را بفرست:", cancelButton());
        return;
    }
    if (strpos($data, 'admin:qtype:') === 0) {
        $parts = explode(':', $data);
        $gameId = (int)($parts[2] ?? 0);
        $type = $parts[3] ?? 'text';
        $state = getAdminState($chatId);
        if (($state['action'] ?? '') === 'choose_question_type') {
            if (!canManageGame($chatId, $gameId)) { clearAdminState($chatId); answerCallback($callbackId, "⛔ دسترسی این بازی را نداری.", true); return; }
            addQuestion($gameId, $state['question_text'], $type);
            clearAdminState($chatId);
            sendMessage($chatId, "✅ سوال اضافه شد.", adminMenu($chatId));
            showAdminQuestions($chatId, $gameId);
        }
        return;
    }
    if (strpos($data, 'admin:discount:') === 0) {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        $id = (int)substr($data, strlen('admin:discount:'));
        $d = getDiscount($id);
        if ($d) {
            updateDiscount($id, ["active" => empty($d['active'])]);
            showAdminDiscounts($chatId);
        }
        return;
    }
    if (strpos($data, 'admin:del_discount:') === 0) {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        $id = (int)substr($data, strlen('admin:del_discount:'));
        $items = array_values(array_filter(getDiscounts(), fn($d) => (int)$d['id'] !== $id));
        saveDiscounts($items);
        showAdminDiscounts($chatId);
        return;
    }
    if (strpos($data, 'admin:discount_games:') === 0) {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        $id = (int)substr($data, strlen('admin:discount_games:'));
        showDiscountGameSelection($chatId, $id);
        return;
    }
    if (strpos($data, 'admin:discount_toggle_game:') === 0) {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        $parts = explode(':', $data);
        $discountId = (int)($parts[2] ?? 0);
        $gameId = (int)($parts[3] ?? 0);
        $d = getDiscount($discountId);
        if ($d) {
            $ids = array_map('intval', $d['game_ids'] ?? []);
            if (in_array($gameId, $ids, true)) $ids = array_values(array_filter($ids, fn($v) => $v !== $gameId));
            else $ids[] = $gameId;
            updateDiscount($discountId, ["game_ids" => $ids]);
        }
        showDiscountGameSelection($chatId, $discountId);
        return;
    }
    if ($data === 'admin:discount_done') {
        if (!isOwner($chatId)) { sendMessage($chatId, "⛔ این بخش فقط برای Owner است.", adminMenu($chatId)); return; }
        sendMessage($chatId, "✅ تنظیمات کد ذخیره شد.", adminDiscountMenu());
        return;
    }

    // Never leave an admin callback without feedback. This also makes
    // broken/stale buttons diagnosable instead of appearing dead.
    if (strpos($data, 'admin:') === 0) {
        sendMessage($chatId, "⚠️ این دکمه قدیمی یا نامعتبر است. پنل ادمین را دوباره باز کن.", adminMenu($chatId));
        return;
    }
}


function gamesButtons($games, $back)
{
    $rows = [];
    foreach ($games as $game) $rows[] = [["text" => "🎮 " . $game['name'], "callback_data" => "game:" . $game['id']]];
    $rows[] = [["text" => "↩️ برگشت", "callback_data" => $back]];
    return inlineKeyboard($rows);
}

function sendDiscountGameInfo($chatId, $game, $discount = null, $fullName = null)
{
    $phone = trim((string)($game['phone'] ?? ''));
    $message = "✅ <b>کد تخفیف با موفقیت استفاده شد.</b>\n\n";
    $message .= "🎮 <b>" . escapeHtml($game['name']) . "</b>\n\n";
    if (!empty($game['description'])) {
        $message .= escapeHtml($game['description']) . "\n\n";
    }
    if ($phone !== '') {
        $message .= "📞 <b>شماره تماس مجموعه:</b> " . phoneLink($phone) . "\n";
    }
    $address = trim((string)($game['address'] ?? ''));
    if ($address !== '') {
        $message .= "📍 <b>آدرس مجموعه:</b> " . escapeHtml($address) . "\n";
    }
    if ($phone !== '' || $address !== '') $message .= "\n";
    // reservation_message عمداً در مسیر کد تخفیف نمایش داده نمی‌شود؛
    // این مسیر اطلاعات تماس و آدرس را خودش استاندارد و فقط یک‌بار می‌سازد.
    if ($discount) {
        $value = ($discount['value'] ?? 0) . (($discount['type'] ?? 'percent') === 'percent' ? '%' : ' تومان');
        $message .= "🎟 تخفیف این بازی: <b>" . escapeHtml($value) . "</b>\n\n";
    }
    if ($fullName !== null) {
        $message .= "👤 نام ثبت‌شده: <b>" . escapeHtml($fullName) . "</b>\n\n";
    }
    if ($phone !== '') {
        $message .= "☎️ <b>برای رزرو با کد تخفیف با شماره زیر تماس بگیر:</b>\n📞 " . phoneLink($phone);
    } else {
        $message .= "☎️ برای رزرو با مجموعه تماس بگیر.";
    }
    $message .= "\n\n😉 <b>حتماً یادت باشه بگی از طرف بازیرو داری رزرو می‌کنی.</b>";

    // شماره تلفن فقط به صورت متن نمایش داده می‌شود؛ هیچ tel: URL یا
    // دکمه URL در این مسیر ارسال نمی‌کنیم تا reply_markup باعث شکست ارسال نشود.
    $keyboard = phoneCallKeyboard($phone, (int)$game['id'], 'rooms:menu');

    if (!empty($game['poster'])) {
        return sendPhoto($chatId, $game['poster'], $message, $keyboard);
    }
    return sendMessage($chatId, $message, $keyboard);
}

function startBooking($chatId, $game, $discount = null)
{
    $questions = getQuestions($game['id']);
    if (!$questions) {
        sendMessage($chatId, "برای این بازی هنوز سوالی تعریف نشده است. از ادمین بخواه سوالاتش را تکمیل کند.", mainMenu());
        return;
    }

    saveUser($chatId, [
        "flow" => "booking",
        "booking_game_id" => (int)$game['id'],
        "booking_question_index" => 0,
        "booking_answers" => [],
        "booking_started_at" => time(),
        "booking_discount_id" => $discount['id'] ?? null,
    ]);

    sendMessage($chatId, "🎮 <b>ثبت اطلاعات بازی " . escapeHtml($game['name']) . "</b>\n\n" . escapeHtml($questions[0]['text']), questionKeyboard($questions[0]['type']));
}

function questionKeyboard($type)
{
    if ($type === 'yesno') return yesNoKeyboard();
    if ($type === 'genre') return genreKeyboard();
    return cancelButton();
}

function handleBookingAnswer($message, $user)
{
    $chatId = $message['chat']['id'];
    $text = isset($message['text']) ? trim($message['text']) : '';
    if ($text === '') return;

    $game = getGame((int)($user['booking_game_id'] ?? 0));
    if (!$game) {
        deleteUser($chatId);
        sendMessage($chatId, "بازی پیدا نشد.", mainMenu());
        return;
    }

    $questions = getQuestions($game['id']);
    $index = (int)($user['booking_question_index'] ?? 0);
    if (!isset($questions[$index])) {
        deleteUser($chatId);
        return;
    }

    $answers = $user['booking_answers'] ?? [];
    $answers[(string)$questions[$index]['id']] = [
        'question' => $questions[$index]['text'],
        'answer' => $text,
    ];

    $index++;
    if (isset($questions[$index])) {
        saveUser($chatId, [
            'flow' => 'booking',
            'booking_question_index' => $index,
            'booking_answers' => $answers,
            'booking_started_at' => (int)($user['booking_started_at'] ?? time()),
        ]);
        sendMessage($chatId, escapeHtml($questions[$index]['text']), questionKeyboard($questions[$index]['type']));
        return;
    }

    $from = $message['from'] ?? [];
    $booking = createBooking([
        'chat_id' => (string)$chatId,
        'username' => $from['username'] ?? 'ندارد',
        'first_name' => $from['first_name'] ?? 'ندارد',
        'game_id' => (int)$game['id'],
        'game_name' => $game['name'],
        'answers' => $answers,
        'discount_id' => $user['booking_discount_id'] ?? null,
        'status' => 'new',
    ]);

    if (!empty($user['booking_discount_id'])) {
        useDiscount($chatId, (int)$user['booking_discount_id'], (int)$game['id']);
    }

    $adminText = "🎮 <b>ثبت اطلاعات جدید</b>\n\n" .
        "🎯 بازی: <b>" . escapeHtml($game['name']) . "</b>\n" .
        "👤 نام: " . escapeHtml($booking['first_name']) . "\n" .
        "🔗 یوزرنیم: @" . escapeHtml($booking['username']) . "\n" .
        "🆔 آیدی: <code>" . $chatId . "</code>\n\n";

    foreach ($answers as $answer) {
        $adminText .= "❓ " . escapeHtml($answer['question']) . "\n";
        $adminText .= "💬 " . escapeHtml($answer['answer']) . "\n\n";
    }
    if (!empty($user['booking_discount_id'])) $adminText .= "🎟 کد تخفیف استفاده شد.\n";

    sendToAdmins($adminText, (int)$game['id']);

    // فقط برای بازی «ناتمام» فایل آهنگ مخصوص بعد از تکمیل فرم ارسال می‌شود.
    // برای هیچ بازی دیگری این فایل ارسال نخواهد شد.
    $isNatamam = (($game['slug'] ?? '') === 'natamam') || (($game['name'] ?? '') === 'ناتمام');

    deleteUser($chatId);

    if ($isNatamam) {
        sendMessage(
            $chatId,
            "❤️ حتما آهنگ زیر رو چند بار قبل بازی تمامی اعضای گروه گوش کنید\n🙏 ممنون از ثبت اطلاعات شما، این خیلی به تجربه بازی شما کمک می‌کنه.\nاطلاعات گروه شما برای ما ارسال شد.",
            mainMenu()
        );
        $audioPath = __DIR__ . "/kodak.mp3";
        if (is_file($audioPath)) sendAudio($chatId, $audioPath);
        else error_log("BOT: natamam audio file not found: " . $audioPath);
    } else {
        $finalMessage = trim((string)($game['final_message'] ?? ''));
        if ($finalMessage === '') $finalMessage = "✅ اطلاعات شما با موفقیت ثبت شد.\n\nممنون که بازیرو رو انتخاب کردی ❤️";
        // Always send the final text as its own message. Files are additional
        // optional messages, so the final message is never lost when files exist.
        sendMessage($chatId, $finalMessage);
        $finalFiles = $game['final_files'] ?? [];
        if (!$finalFiles && !empty($game['final_file']['file_id'])) $finalFiles = [$game['final_file']];
        if ($finalFiles) sendFinalFiles($chatId, $finalFiles);
        sendMessage($chatId, "🏠 عملیات ثبت اطلاعات تمام شد.", mainMenu());
    }
}

function handleInlineQuery($inlineQuery)
{
    $id = $inlineQuery['id'] ?? '';
    $query = $inlineQuery['query'] ?? '';
    $fromId = (int)($inlineQuery['from']['id'] ?? 0);
    if ($id === '') return;
    if (isMaintenanceMode() && !isFounder($fromId)) {
        answerInlineQuery($id, [], 0);
        return;
    }

    // Each poster is validated individually inside inlineGameResults().
    // One broken poster can therefore never make the entire search response fail.
    answerInlineQuery($id, inlineGameResults($query), 0);
}

/* =========================
 * Admin UI
 * ========================= */

function showOwnerManagement($chatId)
{
    if (!isFounder($chatId)) { sendMessage($chatId, "⛔ فقط Founder می‌تواند Ownerها را مدیریت کند.", adminMenu($chatId)); return; }
    global $founder_rank;
    $text = "👑 <b>مدیریت Ownerها</b>\n\n";
    foreach (getConfiguredOwnerIds() as $id) {
        $rank = isFounder($id) ? ($founder_rank ?? 'فاندر') : 'Owner';
        $text .= (isFounder($id) ? '⭐ ' : '👑 ') . "<b>{$rank}</b> — <code>{$id}</code>\n";
    }
    $rows = [[["text" => "➕ افزودن Owner", "callback_data" => "admin:add_owner"]]];
    foreach (getConfiguredOwnerIds() as $id) if (!isFounder($id)) $rows[] = [["text" => "🗑 حذف Owner " . $id, "callback_data" => "admin:remove_owner_id:" . $id]];
    $rows[] = [["text" => "↩️ پنل ادمین", "callback_data" => "admin:back"]];
    sendMessage($chatId, $text . "\n⭐ <b>فقط Founder</b> اجازه افزودن یا حذف Owner را دارد.", inlineKeyboard($rows));
}

function showAdminManagement($chatId)
{
    if (!isOwner($chatId)) { sendMessage($chatId, "⛔ فقط Owner.", adminMenu($chatId)); return; }
    $records = getAdminRecords();
    $text = "👥 <b>ادمین‌های بازی‌ها</b>\n\n";
    foreach ($records as $r) {
        if (($r['role'] ?? '') === 'owner') {
            $text .= "👑 Owner — <code>" . $r['id'] . "</code>\n";
            continue;
        }
        $games = [];
        foreach ($r['game_ids'] ?? [] as $gid) {
            $g = getGame($gid);
            if ($g) $games[] = $g['name'];
        }
        $text .= "🛡 <code>" . $r['id'] . "</code> — " . ($games ? escapeHtml(implode('، ', $games)) : 'بدون بازی') . "\n";
    }
    sendMessage($chatId, $text . "\nبرای اضافه کردن ادمین، وارد مدیریت همان بازی شو و «تعیین ادمین این بازی» را بزن.", inlineKeyboard([
        [["text" => "🗑 حذف ادمین", "callback_data" => "admin:remove_admin"]],
        [["text" => "↩️ پنل ادمین", "callback_data" => "admin:back"]]
    ]));
}

function showAdminRemovalList($chatId)
{
    if (!isOwner($chatId)) return;
    $rows = [];
    foreach (getAdmins() as $id) {
        if (isOwner($id)) continue;
        $rows[] = [["text" => "🗑 حذف " . $id, "callback_data" => "admin:remove_admin_id:" . $id]];
    }
    if (!$rows) $rows[] = [["text" => "ادمین دیگری وجود ندارد", "callback_data" => "admin:manage_admins"]];
    $rows[] = [["text" => "↩️ برگشت", "callback_data" => "admin:manage_admins"]];
    sendMessage($chatId, "🗑 ادمینی که می‌خواهی حذف شود را انتخاب کن:", inlineKeyboard($rows));
}

function showSuggestionManagement($chatId, $sourceId)
{
    $source = getGame($sourceId);
    if (!$source || !canManageGame($chatId, $sourceId)) { sendMessage($chatId, "⛔ دسترسی ندارید.", adminMenu($chatId)); return; }
    $selected = array_values(array_unique(array_map('intval', $source['suggested_games'] ?? [])));
    $rows = [];
    foreach (getGames() as $g) {
        if ((int)$g['id'] === $sourceId || empty($g['active'])) continue;
        $on = in_array((int)$g['id'], $selected, true);
        $rows[] = [["text" => ($on ? "✅ " : "⬜ ") . $g['name'], "callback_data" => "admin:suggestion:toggle:" . $sourceId . ":" . $g['id']]];
    }
    $rows[] = [["text" => "↩️ برگشت به بازی", "callback_data" => "admin:game:" . $sourceId]];
    $count = count($selected);
    sendMessage($chatId, "💡 <b>مدیریت پیشنهادهای «" . escapeHtml($source['name']) . "»</b>\n\nبازی‌هایی که تیک می‌زنی در بخش «پیشنهاد شده توسط " . escapeHtml($source['name']) . "» نمایش داده می‌شوند.\n\nتعداد انتخاب‌شده: <b>" . $count . "</b>", inlineKeyboard($rows));
}

function showAdminGames($chatId)
{
    $games = getGames();
    if (!isOwner($chatId)) {
        $allowed = getAdminGameIds($chatId);
        $games = array_values(array_filter($games, fn($g) => in_array((int)$g['id'], $allowed, true)));
    }
    if (!$games) {
        sendMessage($chatId, "هیچ بازی‌ای ثبت نشده.", adminGamesMenu());
        return;
    }
    $rows = [];
    foreach ($games as $game) {
        $status = !empty($game['active']) ? '🟢' : '🔴';
        $rows[] = [["text" => $status . " " . $game['name'], "callback_data" => "admin:game:" . $game['id']]];
    }
    $rows[] = [["text" => "➕ افزودن بازی", "callback_data" => "admin:add_game"]];
    sendMessage($chatId, "🎮 <b>همه بازی‌ها</b>", inlineKeyboard($rows));
}

function showAdminGame($chatId, $id)
{
    if (!canManageGame($chatId, $id)) { sendMessage($chatId, "⛔ این بازی برای شما نیست.", adminMenu($chatId)); return; }
    $game = getGame($id);
    if (!$game) {
        sendMessage($chatId, "بازی پیدا نشد.", adminGamesMenu());
        return;
    }
    $text = "🎮 <b>مدیریت: " . escapeHtml($game['name']) . "</b>\n\n" .
        "وضعیت: " . (!empty($game['active']) ? '🟢 فعال' : '🔴 غیرفعال') . "\n" .
        "جدیدترین: " . (!empty($game['latest']) ? '✅' : '❌') . "\n" .
        "در حال رفتن: " . (!empty($game['going']) ? '✅' : '❌') . "\n" .
        "رزرو فعال: " . (!empty($game['reservation_enabled']) ? '✅' : '❌') . "\n" .
        "شماره تماس: " . escapeHtml($game['phone'] ?? 'ثبت نشده') . "\n" .
        "آدرس: " . escapeHtml($game['address'] ?? 'ثبت نشده') . "\n" .
        "متن پیام رزرو: " . (!empty($game['reservation_message']) ? 'تنظیم شده ✅' : 'پیش‌فرض') . "\n\n" .
        escapeHtml($game['description'] ?? '');

    $rows = [
        [["text" => "✏️ تغییر نام", "callback_data" => "admin:edit_name:" . $id], ["text" => "📝 تغییر توضیحات", "callback_data" => "admin:edit_desc:" . $id]],
        [["text" => "📞 تغییر شماره", "callback_data" => "admin:edit_phone:" . $id], ["text" => "📍 تغییر آدرس", "callback_data" => "admin:edit_address:" . $id]],
        [["text" => "🖼 تغییر پوستر", "callback_data" => "admin:edit_poster:" . $id]],
        [["text" => "📝 متن پیام رزرو", "callback_data" => "admin:edit_reservation_message:" . $id]],
        [["text" => "🎟 رزرو: " . (!empty($game['reservation_enabled']) ? 'روشن' : 'خاموش'), "callback_data" => "admin:edit_reservation:" . $id]],
        [["text" => "🟢/🔴 فعال یا غیرفعال", "callback_data" => "admin:toggle_game:" . $id]],
        [["text" => "🆕 جدیدترین: " . (!empty($game['latest']) ? 'روشن' : 'خاموش'), "callback_data" => "admin:toggle_latest:" . $id], ["text" => "🔥 در حال رفتن: " . (!empty($game['going']) ? 'روشن' : 'خاموش'), "callback_data" => "admin:toggle_going:" . $id]],
        [["text" => "💡 مدیریت پیشنهادها", "callback_data" => "admin:suggestions:" . $id]],
        [["text" => "❓ مدیریت سوالات", "callback_data" => "admin:qgame:" . $id]],
    ];
    if (isOwner($chatId)) {
        $gameAdmins = getGameAdmins($id);
        $adminLabel = $gameAdmins ? "👥 ادمین‌های بازی (" . count($gameAdmins) . ")" : "➕ افزودن ادمین به بازی";
        $rows[] = [["text" => $adminLabel, "callback_data" => "admin:assign_admin:" . $id]];
        foreach ($gameAdmins as $ga) {
            $rows[] = [["text" => "🛡 " . $ga['id'] . " — حذف از این بازی", "callback_data" => "admin:unassign_admin:" . $id . ":" . $ga['id']]];
        }
        $rows[] = (($game['slug'] ?? '') !== 'natamam') ? [["text" => "🗑 حذف بازی", "callback_data" => "admin:delete_game:" . $id]] : [["text" => "🔒 ناتمام (قابل حذف نیست)", "callback_data" => "rooms:menu"]];
    }
    $rows[] = [["text" => "↩️ برگشت", "callback_data" => isOwner($chatId) ? "admin:games" : "admin:back"]];
    sendMessage($chatId, $text, inlineKeyboard($rows));
}

function showAdminCategory($chatId, $category)
{
    $games = getGames();
    if (!isOwner($chatId)) {
        $allowed = getAdminGameIds($chatId);
        $games = array_values(array_filter($games, fn($g) => in_array((int)$g['id'], $allowed, true)));
    }
    $key = $category === 'latest' ? 'latest' : 'going';
    $title = $category === 'latest' ? '🆕 جدیدترین بازی‌ها' : '🔥 بازی‌های در حال رفتن';
    $rows = [];
    foreach ($games as $game) {
        $mark = !empty($game[$key]) ? '✅' : '⬜';
        $rows[] = [["text" => $mark . " " . $game['name'], "callback_data" => "admin:toggle_{$key}:" . $game['id']]];
    }
    sendMessage($chatId, "<b>" . $title . "</b>\n\nبا زدن روی هر بازی، وضعیتش تغییر می‌کند.", inlineKeyboard($rows));
}

function showAdminQuestion($chatId, $questionId)
{
    $q = getQuestion($questionId);
    if (!$q) return;
    $game = getGame($q['game_id']);
    $typeNames = ['text' => 'متن آزاد', 'yesno' => 'بله/خیر', 'genre' => 'ژانر'];
    $text = "❓ <b>مدیریت سوال</b>\n\n🎮 بازی: " . escapeHtml($game['name'] ?? '') . "\n🔢 ترتیب: " . ($q['order'] ?? 0) . "\n🧩 نوع: " . ($typeNames[$q['type']] ?? $q['type']) . "\n\n" . escapeHtml($q['text']);
    sendMessage($chatId, $text, inlineKeyboard([
        [["text" => "✏️ ویرایش متن", "callback_data" => "admin:edit_question:" . $questionId]],
        [["text" => "🗑 حذف سوال", "callback_data" => "admin:delete_question:" . $questionId]],
        [["text" => "↩️ برگشت به سوالات", "callback_data" => "admin:qgame:" . $q['game_id']]],
    ]));
}

function showAdminQuestions($chatId, $gameId)
{
    if (!canManageGame($chatId, $gameId)) { sendMessage($chatId, "⛔ این بازی برای شما نیست.", adminMenu($chatId)); return; }
    $game = getGame($gameId);
    if (!$game) return;
    $questions = getQuestions($gameId);
    $rows = [];
    foreach ($questions as $q) {
        $label = "❓ " . ($q['order'] ?? 0) . ". " . textSubstr($q['text'], 0, 28);
        $rows[] = [
            ["text" => $label, "callback_data" => "admin:question:" . $q['id']],
            ["text" => "✏️", "callback_data" => "admin:edit_question:" . $q['id']],
            ["text" => "🗑", "callback_data" => "admin:delete_question:" . $q['id']]
        ];
    }
    $finalFiles = $game['final_files'] ?? [];
    if (!$finalFiles && !empty($game['final_file']['file_id'])) $finalFiles = [$game['final_file']];
    $fileCount = count($finalFiles);
    $rows[] = [["text" => "📝 پیام پایانی: " . (!empty($game['final_message']) ? 'تنظیم شده ✅' : 'تنظیم نشده') , "callback_data" => "admin:edit_final_message:" . $gameId]];
    $rows[] = [["text" => "📎 افزودن فایل پایانی (" . $fileCount . ")", "callback_data" => "admin:set_final_file:" . $gameId], ["text" => "🗑 حذف همه فایل‌ها", "callback_data" => "admin:remove_final_file:" . $gameId]];
    $rows[] = [["text" => "➕ افزودن سوال", "callback_data" => "admin:addq:" . $gameId]];
    $rows[] = [["text" => "↩️ مدیریت بازی", "callback_data" => "admin:game:" . $gameId]];
    $title = "❓ <b>سوالات " . escapeHtml($game['name']) . "</b>";
    $hint = $questions ? "\n\nبرای هر سوال دکمه ✏️ یا 🗑 را بزن." : "\n\nهنوز سوالی برای این بازی ثبت نشده.";
    sendMessage($chatId, $title . $hint, inlineKeyboard($rows));
}

function showAdminDiscounts($chatId)
{
    $items = getDiscounts();
    if (!$items) {
        sendMessage($chatId, "هیچ کد تخفیفی ساخته نشده.", adminDiscountMenu());
        return;
    }
    $rows = [];
    foreach ($items as $d) {
        $status = !empty($d['active']) ? '🟢' : '🔴';
        $rows[] = [["text" => $status . " " . $d['code'] . " | " . ($d['used_count'] ?? 0) . "/" . ($d['max_uses'] ?? '∞'), "callback_data" => "admin:discount_games:" . $d['id']]];
        $rows[] = [["text" => "فعال/غیرفعال: " . $d['code'], "callback_data" => "admin:discount:" . $d['id']], ["text" => "🗑 حذف", "callback_data" => "admin:del_discount:" . $d['id']]];
    }
    $rows[] = [["text" => "➕ ساخت کد تخفیف جدید", "callback_data" => "admin:add_discount"]];
    sendMessage($chatId, "🎟 <b>کدهای تخفیف</b>", inlineKeyboard($rows));
}

function showDiscountGameSelection($chatId, $discountId)
{
    $d = getDiscount($discountId);
    if (!$d) return;
    $selected = array_map('intval', $d['game_ids'] ?? []);
    $rows = [];
    foreach (getGames() as $game) {
        $mark = in_array((int)$game['id'], $selected, true) ? '✅' : '⬜';
        $rows[] = [["text" => $mark . " " . $game['name'], "callback_data" => "admin:discount_toggle_game:" . $discountId . ":" . $game['id']]];
    }
    $rows[] = [["text" => "✅ پایان انتخاب", "callback_data" => "admin:discount_done"]];
    sendMessage($chatId, "🎟 بازی‌هایی که کد <b>" . escapeHtml($d['code']) . "</b> روی آن‌ها اعمال می‌شود را انتخاب کن:", inlineKeyboard($rows));
}

function showSubmittedInfo($chatId, $gameId = null)
{
    if (!isOwner($chatId)) {
        $allowed = getAdminGameIds($chatId);
        if ($gameId === null) {
            if (count($allowed) === 1) $gameId = $allowed[0];
            elseif (!$allowed) { sendMessage($chatId, "⛔ بازی اختصاصی برای این ادمین تنظیم نشده است.", adminMenu($chatId)); return; }
            else {
                $rows = [];
                foreach ($allowed as $gid) { $g=getGame($gid); if($g) $rows[]=[['text'=>'🎮 '.$g['name'],'callback_data'=>'admin:submitted_info:game:'.$gid]]; }
                $rows[]=[['text'=>'↩️ پنل ادمین','callback_data'=>'admin:back']];
                sendMessage($chatId, '📋 <b>نمایش اطلاعات ارسال شده</b>\n\nبازی موردنظر را انتخاب کن:', inlineKeyboard($rows));
                return;
            }
        }
        if (!canManageGame($chatId, $gameId)) { sendMessage($chatId, "⛔ دسترسی به اطلاعات این بازی را نداری.", adminMenu($chatId)); return; }
    }

    $bookings = array_reverse(getBookings());
    if ($gameId !== null) $bookings = array_values(array_filter($bookings, fn($b) => (int)($b['game_id'] ?? 0) === (int)$gameId));
    $gameName = $gameId !== null ? (getGame($gameId)['name'] ?? 'بازی') : 'همه بازی‌ها';
    if (!$bookings) {
        sendMessage($chatId, "📭 هنوز اطلاعات ارسالی برای <b>" . escapeHtml($gameName) . "</b> ثبت نشده است.", adminMenu($chatId));
        return;
    }
    $total=count($bookings);
    $newCount=count(array_filter($bookings, fn($b)=>(($b['status']??'new')==='new')));
    $text="📋 <b>نمایش اطلاعات ارسال شده</b>\n🎮 بازی: <b>".escapeHtml($gameName)."</b>\n📊 تعداد: <b>{$total}</b> | 🆕 جدید: <b>{$newCount}</b>\n\nبرای دیدن اطلاعات کامل، روی مورد موردنظر بزن:";
    $rows=[];
    foreach(array_slice($bookings,0,30) as $b){
        $name=trim((string)($b['first_name']??'ندارد')); $date=(string)($b['created_at']??'');
        $label='👤 '.($name!==''?$name:'بدون نام'); if($date!=='') $label.=' — '.mb_substr($date,0,16);
        $rows[]=[['text'=>$label,'callback_data'=>'admin:submitted_info:booking:'.(int)($b['id']??0)]];
    }
    if($gameId!==null) $rows[]=[['text'=>'↩️ برگشت به بازی','callback_data'=>'admin:submitted_info']];
    $rows[]=[['text'=>'🏠 پنل ادمین','callback_data'=>'admin:back']];
    sendMessage($chatId,$text,inlineKeyboard($rows));
}

function showSubmittedBooking($chatId, $bookingId)
{
    $booking=null;
    foreach(getBookings() as $b){ if((int)($b['id']??0)===$bookingId){$booking=$b;break;} }
    if(!$booking){ sendMessage($chatId,'❌ این اطلاعات پیدا نشد.',adminMenu($chatId)); return; }
    $gameId=(int)($booking['game_id']??0);
    if(!isOwner($chatId) && !canManageGame($chatId,$gameId)){ sendMessage($chatId,'⛔ دسترسی به اطلاعات این بازی را نداری.',adminMenu($chatId)); return; }
    $g=getGame($gameId); $gameName=$g['name']??'نامشخص';
    $username=trim((string)($booking['username']??'')); $usernameText=($username!==''&&$username!=='ندارد')?'@'.$username:'ندارد';
    $text="📋 <b>اطلاعات ارسال شده</b>\n\n🎮 بازی: <b>".escapeHtml($gameName)."</b>\n🆔 شماره ثبت: <code>".escapeHtml((string)($booking['id']??'' ))."</code>\n🕐 تاریخ: ".escapeHtml((string)($booking['created_at']??''))."\n\n👤 نام: <b>".escapeHtml((string)($booking['first_name']??'ندارد'))."</b>\n🔗 یوزرنیم: ".escapeHtml($usernameText)."\n🆔 آیدی تلگرام: <code>".escapeHtml((string)($booking['chat_id']??''))."</code>\n📌 وضعیت: <b>".escapeHtml((string)($booking['status']??'new'))."</b>";
    if(!empty($booking['discount_id'])){ $d=getDiscount((int)$booking['discount_id']); if($d) $text.="\n🎟 کد تخفیف: <b>".escapeHtml((string)($d['code']??''))." — ".escapeHtml((string)($d['value']??0).(($d['type']??'percent')==='percent'?'%':' تومان'))."</b>"; }
    $answers=$booking['answers']??[];
    if(is_array($answers)&&$answers){ $text.="\n\n❓ <b>پاسخ‌ها</b>"; foreach($answers as $a){$text.="\n\n<b>❓ ".escapeHtml((string)($a['question']??''))."</b>\n💬 ".escapeHtml((string)($a['answer']??''))."";} }
    $rows=[
        [['text'=>'↩️ برگشت به اطلاعات ارسال شده','callback_data'=>'admin:submitted_info:game:'.$gameId]],
        [['text'=>'🏠 پنل ادمین','callback_data'=>'admin:back']]
    ];
    sendMessage($chatId,$text,inlineKeyboard($rows));
}

function showAdminBookings($chatId, $gameId = null)
{
    // Backward compatibility for old callbacks: route them to the renamed UI.
    showSubmittedInfo($chatId, $gameId);
}

function extractTelegramFile($message)
{
    if (!empty($message['photo']) && is_array($message['photo'])) {
        $photo = end($message['photo']);
        return ['type' => 'photo', 'file_id' => $photo['file_id'] ?? ''];
    }
    foreach (['video','document','audio','voice','animation','sticker'] as $type) {
        if (!empty($message[$type]['file_id'])) return ['type' => $type, 'file_id' => $message[$type]['file_id']];
    }
    return null;
}

function handleAdminState($message, $state)
{
    $chatId = $message['chat']['id'];
    $text = isset($message['text']) ? trim($message['text']) : '';
    $action = $state['action'];

    if ($action === 'add_owner_id') {
        if (!isFounder($chatId)) { clearAdminState($chatId); return true; }
        if (!ctype_digit($text)) { sendMessage($chatId, "❌ آیدی عددی معتبر نیست.", cancelButton()); return true; }
        $id = (int)$text;
        if ($id === getFounderId()) { sendMessage($chatId, "ℹ️ این آیدی خود Founder است.", cancelButton()); return true; }
        addOwner($id);
        // Ensure the new Owner is represented in admin store.
        $records = getAdminRecords();
        $exists = false; foreach ($records as $r) if ((int)$r['id'] === $id) { $exists = true; break; }
        if (!$exists) $records[] = ['id' => $id, 'role' => 'owner', 'game_ids' => []];
        saveAdminRecords($records);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ <code>{$id}</code> با رتبه 👑 Owner اضافه شد.", adminMenu($chatId));
        showOwnerManagement($chatId);
        return true;
    }

    if ($action === 'add_admin_id') {
        if (!isOwner($chatId)) { clearAdminState($chatId); return true; }
        if (!ctype_digit($text)) {
            sendMessage($chatId, "❌ آیدی عددی معتبر نیست. مثلا: <code>123456789</code>", cancelButton());
            return true;
        }
        $id = (int)$text;
        addAdmin($id);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ کاربر <code>{$id}</code> به عنوان 🛡 Admin اضافه شد.", adminMenu($chatId));
        showAdminManagement($chatId);
        return true;
    }

    if ($action === 'broadcast') {
        if ($text === '') return true;
        sendToAllUsers($text);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ پیام همگانی ارسال شد.", adminMenu($chatId));
        return true;
    }

    if ($action === 'single_user_id') {
        if (!ctype_digit($text)) {
            sendMessage($chatId, "❌ آیدی عددی معتبر نیست.", cancelButton());
            return true;
        }
        setAdminState($chatId, ["action" => "single_user_text", "target" => $text]);
        sendMessage($chatId, "پیامت را برای این کاربر بفرست:", cancelButton());
        return true;
    }

    if ($action === 'single_user_text') {
        if ($text === '') return true;
        @sendMessage($state['target'], $text);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ پیام ارسال شد.", adminMenu($chatId));
        return true;
    }

    if ($action === 'assign_game_admin_id') {
        if (!isOwner($chatId)) { clearAdminState($chatId); return true; }
        if (!ctype_digit($text)) { sendMessage($chatId, "❌ آیدی عددی معتبر نیست.", cancelButton()); return true; }
        $gameId = (int)$state['game_id'];
        if (assignAdminToGame((int)$text, $gameId)) {
            clearAdminState($chatId);
            sendMessage($chatId, "✅ ادمین بازی تنظیم شد.\n\nاین ادمین فقط همین بازی را می‌بیند و اطلاعات همین بازی برای او ارسال می‌شود.", adminMenu($chatId));
            showAdminGame($chatId, $gameId);
        } else {
            sendMessage($chatId, "❌ نتوانستم این ادمین را برای بازی تنظیم کنم.", cancelButton());
        }
        return true;
    }

    if ($action === 'edit_final_message') {
        $gameId = (int)$state['game_id'];
        if (!canManageGame($chatId, $gameId)) { clearAdminState($chatId); sendMessage($chatId, "⛔ دسترسی نداری.", adminMenu($chatId)); return true; }
        updateGame($gameId, ['final_message' => $text]);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ پیام پایانی ذخیره شد.");
        showAdminQuestions($chatId, $gameId);
        return true;
    }

    if ($action === 'set_final_file') {
        $gameId = (int)$state['game_id'];
        if (!canManageGame($chatId, $gameId)) { clearAdminState($chatId); sendMessage($chatId, "⛔ دسترسی نداری.", adminMenu($chatId)); return true; }
        $file = extractTelegramFile($message);
        if (!$file) {
            sendMessage($chatId, "❌ این پیام فایل قابل ذخیره‌ای ندارد. هر تعداد عکس، ویدیو، فایل، صدا، ویس، GIF یا استیکر که می‌خواهی یکی‌یکی بفرست.", inlineKeyboard([[
                ["text" => "✅ پایان افزودن فایل‌ها", "callback_data" => "admin:finish_final_files:" . $gameId]
            ]]));
            return true;
        }
        $game = getGame($gameId);
        $files = $game['final_files'] ?? [];
        if (!$files && !empty($game['final_file']['file_id'])) $files[] = $game['final_file'];
        $files[] = $file;
        updateGame($gameId, ['final_files' => $files, 'final_file' => $files[0] ?? null]);
        // Keep the state active so the admin can send any number of files.
        setAdminState($chatId, ['action' => 'set_final_file', 'game_id' => $gameId]);
        sendMessage($chatId, "✅ فایل " . count($files) . " ذخیره شد.

فایل بعدی را بفرست یا برای پایان روی دکمه زیر بزن.", inlineKeyboard([[
            ["text" => "✅ پایان افزودن فایل‌ها", "callback_data" => "admin:finish_final_files:" . $gameId]
        ]]));
        return true;
    }

    if ($action === 'add_game_photo' || $action === 'edit_game_poster') {
        if (isset($message['photo']) && is_array($message['photo'])) {
            $photo = end($message['photo']);
            $fileId = $photo['file_id'] ?? '';
            if ($action === 'edit_game_poster') {
                if (!canManageGame($chatId, $state['game_id'])) { clearAdminState($chatId); sendMessage($chatId, "⛔ دسترسی نداری.", adminMenu($chatId)); return true; }
                updateGame($state['game_id'], ['poster' => $fileId]);
                clearAdminState($chatId);
                if (isValidTelegramFileId($fileId)) {
                    sendMessage($chatId, "🖼 پوستر تغییر کرد و توسط تلگرام تأیید شد.", adminMenu($chatId));
                } else {
                    sendMessage($chatId, "⚠️ پوستر ذخیره شد، اما Telegram این file_id را معتبر تشخیص نداد. لطفاً عکس را دوباره به‌صورت Photo ارسال کن.", adminMenu($chatId));
                }
                showAdminGame($chatId, $state['game_id']);
            } else {
                $data = $state['data'] ?? [];
                $data['poster'] = $fileId;
                setAdminState($chatId, ["action" => "add_game_name", "data" => $data]);
                sendMessage($chatId, "اسم بازی را بفرست:", cancelButton());
            }
        } else {
            sendMessage($chatId, "لطفاً خودِ عکس پوستر را ارسال کن.", cancelButton());
        }
        return true;
    }

    if ($action === 'add_game_name') {
        if ($text === '') return true;
        $data = $state['data'] ?? [];
        $data['name'] = $text;
        setAdminState($chatId, ["action" => "add_game_desc", "data" => $data]);
        sendMessage($chatId, "توضیحات بازی را بفرست:", cancelButton());
        return true;
    }

    if ($action === 'add_game_desc') {
        $data = $state['data'] ?? [];
        $data['description'] = $text;
        setAdminState($chatId, ["action" => "add_game_phone", "data" => $data]);
        sendMessage($chatId, "شماره تماس بازی را بفرست (برای کد تخفیف و رزرو نمایش داده می‌شود):", cancelButton());
        return true;
    }

    if ($action === 'add_game_phone') {
        $data = $state['data'] ?? [];
        $data['phone'] = $text;
        setAdminState($chatId, ['action' => 'add_game_address', 'data' => $data]);
        sendMessage($chatId, "📍 آدرس مجموعه این بازی را بفرست:", cancelButton());
        return true;
    }

    if ($action === 'add_game_address') {
        $data = $state['data'] ?? [];
        $data['address'] = $text;
        $game = addGame($data + [
            'category' => 'all',
            'active' => true,
            'latest' => false,
            'going' => false,
            'reservation_enabled' => true,
            'reservation_message' => '',
        ]);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ بازی <b>" . escapeHtml($game['name']) . "</b> اضافه شد.\n\nحالا می‌تونی از مدیریت سوالات، سوال‌های مخصوص همین بازی را بسازی.", adminMenu($chatId));
        showAdminGame($chatId, $game['id']);
        return true;
    }

    if ($action === 'edit_game_name') {
        if (!canManageGame($chatId, $state['game_id'])) { clearAdminState($chatId); sendMessage($chatId, "⛔ دسترسی نداری.", adminMenu($chatId)); return true; }
        updateGame($state['game_id'], ['name' => $text]);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ نام تغییر کرد.");
        showAdminGame($chatId, $state['game_id']);
        return true;
    }
    if ($action === 'edit_game_desc') {
        if (!canManageGame($chatId, $state['game_id'])) { clearAdminState($chatId); sendMessage($chatId, "⛔ دسترسی نداری.", adminMenu($chatId)); return true; }
        updateGame($state['game_id'], ['description' => $text]);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ توضیحات تغییر کرد.");
        showAdminGame($chatId, $state['game_id']);
        return true;
    }
    if ($action === 'edit_game_phone') {
        if (!canManageGame($chatId, $state['game_id'])) { clearAdminState($chatId); sendMessage($chatId, "⛔ دسترسی نداری.", adminMenu($chatId)); return true; }
        updateGame($state['game_id'], ['phone' => $text]);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ شماره تماس تغییر کرد.");
        showAdminGame($chatId, $state['game_id']);
        return true;
    }
    if ($action === 'edit_game_address') {
        if (!canManageGame($chatId, $state['game_id'])) { clearAdminState($chatId); sendMessage($chatId, "⛔ دسترسی نداری.", adminMenu($chatId)); return true; }
        updateGame($state['game_id'], ['address' => $text]);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ آدرس تغییر کرد.");
        showAdminGame($chatId, $state['game_id']);
        return true;
    }
    if ($action === 'edit_reservation_message') {
        if (!canManageGame($chatId, $state['game_id'])) { clearAdminState($chatId); sendMessage($chatId, "⛔ دسترسی نداری.", adminMenu($chatId)); return true; }
        if ($text === '') {
            sendMessage($chatId, "❌ متن پیام نمی‌تواند خالی باشد.", cancelButton());
            return true;
        }
        updateGame($state['game_id'], ['reservation_message' => $text]);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ متن پیام رزرو تغییر کرد.");
        showAdminGame($chatId, $state['game_id']);
        return true;
    }

    if ($action === 'edit_question_text') {
        if ($text === '') return true;
        $q = getQuestion($state['question_id']);
        if ($q) {
            updateQuestion($q['id'], ['text' => $text]);
            clearAdminState($chatId);
            sendMessage($chatId, "✅ متن سوال تغییر کرد.");
            showAdminQuestion($chatId, $q['id']);
        }
        return true;
    }

    if ($action === 'add_question_text') {
        if ($text === '') return true;
        setAdminState($chatId, [
            'action' => 'choose_question_type',
            'game_id' => $state['game_id'],
            'question_text' => $text,
        ]);
        sendMessage($chatId, "نوع سوال را انتخاب کن:", inlineKeyboard([
            [["text" => "📝 متن آزاد", "callback_data" => "admin:qtype:" . $state['game_id'] . ":text"]],
            [["text" => "✅ بله / خیر", "callback_data" => "admin:qtype:" . $state['game_id'] . ":yesno"]],
            [["text" => "🎭 ژانر", "callback_data" => "admin:qtype:" . $state['game_id'] . ":genre"]],
        ]));
        return true;
    }

    // Discount creation wizard
    if ($action === 'discount_code') {
        if ($text === '') return true;
        if (findDiscountByCode($text)) {
            sendMessage($chatId, "❌ این کد قبلاً وجود دارد. یک کد دیگر بفرست:", cancelButton());
            return true;
        }
        $data = ['code' => strtoupper($text)];
        setAdminState($chatId, ['action' => 'discount_value', 'data' => $data]);
        sendMessage($chatId, "درصد تخفیف را وارد کن. مثال: <code>20</code>", cancelButton());
        return true;
    }
    if ($action === 'discount_value') {
        if (!is_numeric($text)) {
            sendMessage($chatId, "فقط عدد وارد کن. مثال: 20", cancelButton());
            return true;
        }
        $data = $state['data'];
        $data['type'] = 'percent';
        $data['value'] = (float)$text;
        setAdminState($chatId, ['action' => 'discount_max_uses', 'data' => $data]);
        sendMessage($chatId, "حداکثر چند بار قابل استفاده باشد؟\n0 = نامحدود", cancelButton());
        return true;
    }
    if ($action === 'discount_max_uses') {
        if (!ctype_digit($text)) {
            sendMessage($chatId, "یک عدد صحیح وارد کن. 0 یعنی نامحدود.", cancelButton());
            return true;
        }
        $data = $state['data'];
        $data['max_uses'] = (int)$text;
        $discount = createDiscount($data + ['game_ids' => []]);
        clearAdminState($chatId);
        sendMessage($chatId, "✅ کد <b>" . escapeHtml($discount['code']) . "</b> ساخته شد.\n\nحالا بازی‌هایی که شامل این کد هستند را انتخاب کن.", adminMenu($chatId));
        showDiscountGameSelection($chatId, $discount['id']);
        return true;
    }

    return false;
}
