<?php
declare(strict_types=1);

require_once __DIR__ . '/../app/bootstrap.php';

function bot_panel_url(array $config): string { return rtrim((string)$config['app_url'], '/') . '/index.php'; }
function role_fa(string $role): string { return $role === 'admin' ? 'ادمین' : ($role === 'reseller' ? 'نماینده' : 'مشتری'); }
function int_amount(string $text): int
{
    $text = strtr($text, [
        '۰'=>'0','۱'=>'1','۲'=>'2','۳'=>'3','۴'=>'4','۵'=>'5','۶'=>'6','۷'=>'7','۸'=>'8','۹'=>'9',
        '٠'=>'0','١'=>'1','٢'=>'2','٣'=>'3','٤'=>'4','٥'=>'5','٦'=>'6','٧'=>'7','٨'=>'8','٩'=>'9',
    ]);
    return (int)digits_only(str_replace([',','٬','،',' '], '', $text));
}

function main_inline_keyboard(array $config, array $user): array
{
    $panelUrl = bot_panel_url($config);
    $rows = [
        [['text' => '🌐 پنل من', 'web_app' => ['url' => $panelUrl]]],
        [['text' => '➕ افزودن ربات', 'callback_data' => 'add_bot'], ['text' => '🤖 ربات‌های من', 'callback_data' => 'my_bots']],
        [['text' => '📦 تعرفه‌ها', 'callback_data' => 'plans'], ['text' => '👤 حساب کاربری', 'callback_data' => 'account']],
        [['text' => '🆘 پشتیبانی', 'callback_data' => 'support']],
    ];
    if (in_array((string)($user['role'] ?? 'customer'), ['admin','reseller'], true)) {
        array_unshift($rows, [['text' => '⚙️ ورود به پنل مدیریت', 'web_app' => ['url' => $panelUrl]]]);
    }
    return ['inline_keyboard' => $rows];
}
function flow_keyboard(): array
{
    return ['inline_keyboard' => [
        [['text' => '⬅️ بازگشت به منوی قبل', 'callback_data' => 'main_menu']],
        [['text' => '❌ لغو عملیات', 'callback_data' => 'cancel_flow']],
    ]];
}
function account_keyboard(array $config): array
{
    return ['inline_keyboard' => [
        [['text' => '➕ افزایش موجودی', 'callback_data' => 'topup']],
        [['text' => '🌐 پنل من', 'web_app' => ['url' => bot_panel_url($config)]]],
        [['text' => '🏠 منوی اصلی', 'callback_data' => 'main_menu']],
    ]];
}
function add_bot_charge_keyboard(): array
{
    return ['inline_keyboard' => [
        [['text' => '➕ افزایش موجودی', 'callback_data' => 'topup']],
        [['text' => '👤 حساب کاربری', 'callback_data' => 'account']],
        [['text' => '🏠 منوی اصلی', 'callback_data' => 'main_menu']],
    ]];
}
function active_bot_plans(Repository $repo): array
{
    return array_values(array_filter($repo->listPlans(), fn($p) => ($p['status'] ?? '') === 'active'));
}
function add_bot_plan_keyboard(array $plans): array
{
    $rows = [];
    foreach ($plans as $p) {
        $title = trim((string)($p['title'] ?? 'پلن'));
        if (mb_strlen($title) > 28) $title = mb_substr($title, 0, 28) . '…';
        $rows[] = [[
            'text' => '📦 ' . $title . ' | ' . money_format_ir((int)($p['price'] ?? 0)),
            'callback_data' => 'addbot_plan_' . (int)$p['id'],
        ]];
    }
    $rows[] = [['text' => '➕ افزایش موجودی', 'callback_data' => 'topup']];
    $rows[] = [['text' => '🏠 منوی اصلی', 'callback_data' => 'main_menu']];
    return ['inline_keyboard' => $rows];
}
function add_bot_plans_message(array $plans): string
{
    $lines = [
        '➕ <b>افزودن ربات</b>',
        '',
        'اول پلن مورد نظرت را انتخاب کن. بعد از انتخاب، موجودی حساب بررسی می‌شود و اگر کافی باشد مرحله ارسال توکن شروع می‌شود.',
        '',
        '📦 <b>پلن‌های فعال:</b>',
    ];
    foreach ($plans as $p) {
        $lines[] = '• <b>' . h((string)$p['title']) . '</b> | ' . (int)$p['months'] . ' ماه | ' . money_format_ir((int)$p['price']);
    }
    return implode("\n", $lines);
}
function payment_method_keyboard(): array
{
    return ['inline_keyboard' => [
        [['text' => '💳 کارت به کارت', 'callback_data' => 'topup_card']],
        [['text' => '⬅️ بازگشت به حساب کاربری', 'callback_data' => 'account']],
        [['text' => '❌ لغو عملیات', 'callback_data' => 'cancel_flow']],
    ]];
}
function receipt_action_keyboard(): array
{
    return ['inline_keyboard' => [
        [['text' => '📤 ارسال تراکنش واریزی', 'callback_data' => 'topup_send_receipt']],
        [['text' => '⬅️ اصلاح مبلغ', 'callback_data' => 'topup_card']],
        [['text' => '❌ لغو عملیات', 'callback_data' => 'cancel_flow']],
    ]];
}
function admin_payment_keyboard(int $paymentId): array
{
    return ['inline_keyboard' => [
        [['text' => '✅ تایید و افزایش موجودی', 'callback_data' => 'pay_ok_' . $paymentId]],
        [['text' => '❌ رد رسید', 'callback_data' => 'pay_no_' . $paymentId]],
    ]];
}
function admin_user_keyboard(string|int $telegramId): array
{
    $tid = digits_only((string)$telegramId);
    return ['inline_keyboard' => [
        [
            ['text' => '⛔️ بن کردن از ربات', 'callback_data' => 'adm_ban_' . $tid],
            ['text' => '➕ افزایش موجودی', 'callback_data' => 'adm_add_' . $tid],
        ],
        [
            ['text' => '➖ کاهش موجودی', 'callback_data' => 'adm_sub_' . $tid],
            ['text' => '✉️ پیام به کاربر', 'callback_data' => 'adm_msg_' . $tid],
        ],
    ]];
}

function join_required_keyboard(Repository $repo): array
{
    $rows = [];
    foreach ($repo->listRequiredJoins(true) as $j) {
        $url = trim((string)($j['invite_url'] ?? ''));
        if ($url === '') {
            $chat = trim((string)$j['chat_id']);
            if (str_starts_with($chat, '@')) $url = 'https://t.me/' . ltrim($chat, '@');
        }
        if ($url !== '') $rows[] = [['text' => 'عضویت در ' . (string)$j['title'], 'url' => $url]];
    }
    $rows[] = [['text' => '✅ بررسی عضویت', 'callback_data' => 'check_join']];
    return ['inline_keyboard' => $rows];
}
function missing_required_joins(Repository $repo, Telegram $tg, string|int $telegramId): array
{
    $missing = [];
    foreach ($repo->listRequiredJoins(true) as $join) {
        try {
            $member = $tg->getChatMember((string)$join['chat_id'], (string)$telegramId);
            $status = (string)($member['status'] ?? 'left');
            if (in_array($status, ['left','kicked'], true)) $missing[] = $join;
        } catch (Throwable $e) {
            app_log('required join check failed', ['join_id' => $join['id'] ?? null, 'error' => $e->getMessage()]);
            $missing[] = $join;
        }
    }
    return $missing;
}
function send_join_required(Telegram $tg, Repository $repo, int|string $chatId): void
{
    $tg->sendMessage($chatId, "🔒 برای استفاده از ربات، اول داخل کانال/گروه‌های زیر عضو شو و بعد روی «بررسی عضویت» بزن.", join_required_keyboard($repo));
}
function account_message(Repository $repo, array $user): string
{
    $details = $repo->accountDetails((int)$user['id']);
    $u = $details['user'] ?: $user;
    $username = !empty($u['username']) ? '@' . h((string)$u['username']) : '-';
    $name = h(user_display_name($u));
    $last = $details['last_purchase'];
    $lastText = '-';
    if ($last) {
        $lastText = '@' . h((string)($last['bot_username'] ?: '-')) . ' | ' . h((string)($last['plan_title'] ?: 'دلخواه')) . ' | تا ' . h(fa_date((string)$last['expires_at']));
    }
    $lines = [
        '👤 <b>حساب کاربری</b>','',
        'یوزر عددی: <code>' . h((string)$u['telegram_id']) . '</code>',
        'یوزرنیم: <b>' . $username . '</b>',
        'اسم اکانت: <b>' . $name . '</b>',
        'نقش: <b>' . role_fa((string)$u['role']) . '</b>',
        'موجودی حساب: <b>' . money_format_ir((int)$u['balance']) . '</b>',
        'تاریخ ثبت‌نام: <b>' . h(fa_date((string)$u['created_at'])) . '</b>',
        'آخرین خرید: <b>' . $lastText . '</b>','',
        '📌 <b>پلن‌های فعال</b>',
    ];
    if (!$details['active_plans']) $lines[] = 'فعلاً پلن فعالی ثبت نشده است.';
    foreach ($details['active_plans'] as $p) {
        $lines[] = '• ربات #' . (int)$p['bot_id'] . ' @' . h((string)($p['bot_username'] ?: '-')) . ' | پلن: ' . h((string)($p['plan_title'] ?: 'دلخواه')) . ' | قیمت: ' . money_format_ir((int)$p['price']) . ' | وضعیت: ' . h((string)$p['bot_status']) . ' | انقضا: ' . h(fa_date((string)$p['expires_at']));
    }
    return implode("\n", $lines);
}
function topup_start_message(Repository $repo): string
{
    $s = $repo->paymentSettings();
    return "➕ <b>افزایش موجودی</b>\n\nروش پرداخت را انتخاب کن.\nحداقل مبلغ شارژ: <b>" . money_format_ir((int)$s['topup_min_amount']) . "</b>\nحداکثر مبلغ شارژ: <b>" . money_format_ir((int)$s['topup_max_amount']) . "</b>";
}
function topup_card_message(Repository $repo): string
{
    $s = $repo->paymentSettings();
    $card = $s['card'];
    if (!$card) return "❌ هنوز کارت پرداخت توسط ادمین ثبت نشده است.";
    return "💳 <b>پرداخت کارت به کارت</b>\n\n" .
        "شماره کارت:\n<code>" . h((string)$card['card_number']) . "</code>\n" .
        "به نام: <b>" . h((string)$card['holder']) . "</b>\n" .
        (!empty($card['iban']) ? "شبا: <code>" . h((string)$card['iban']) . "</code>\n" : '') .
        "\nمبلغ مورد نظر را به تومان وارد کن.\nحداقل: <b>" . money_format_ir((int)$s['topup_min_amount']) . "</b>\nحداکثر: <b>" . money_format_ir((int)$s['topup_max_amount']) . "</b>";
}
function send_my_bots(Telegram $tg, Repository $repo, array $config, int|string $chatId, array $user): void
{
    $bots = $repo->listBots((int)$user['id'], (string)$user['role'], 20);
    if (!$bots) { $tg->sendMessage($chatId, 'هنوز رباتی ثبت نشده است.', main_inline_keyboard($config, $user)); return; }
    $lines = ['🤖 <b>ربات‌های شما</b>'];
    foreach ($bots as $b) $lines[] = '• #' . (int)$b['id'] . ' @' . h((string)($b['bot_username'] ?: '-')) . ' | ' . h((string)$b['status']) . ' | پلن: ' . h((string)($b['plan_title'] ?: 'دلخواه')) . ' | تا ' . h(fa_date((string)($b['expires_at'] ?: '')));
    $tg->sendMessage($chatId, implode("\n", $lines), main_inline_keyboard($config, $user));
}
function send_plans(Telegram $tg, Repository $repo, array $config, int|string $chatId, array $user): void
{
    $plans = active_bot_plans($repo); $lines = ['📦 <b>تعرفه‌ها</b>'];
    if (!$plans) $lines[] = 'فعلاً پلن فعالی ثبت نشده است.';
    foreach ($plans as $p) $lines[] = '• #' . (int)$p['id'] . ' ' . h((string)$p['title']) . ' | ' . (int)$p['months'] . ' ماه | ' . money_format_ir((int)$p['price']);
    $tg->sendMessage($chatId, implode("\n", $lines), main_inline_keyboard($config, $user));
}
function notify_admins_payment(Telegram $tg, Repository $repo, array $config, array $payment): void
{
    $user = $repo->findUserById((int)$payment['user_id']) ?: [];
    $msg = "🧾 <b>رسید افزایش موجودی جدید</b>\n" .
        "شناسه درخواست: <b>#" . (int)$payment['id'] . "</b>\n" .
        "کاربر: " . format_user_for_log($user) . "\n" .
        "مبلغ: <b>" . money_format_ir((int)$payment['amount']) . "</b>\n" .
        "وضعیت: <b>در انتظار بررسی</b>";
    $targets = array_filter(array_unique(array_map('strval', $config['super_admin_ids'] ?? [])));
    $logChat = trim((string)($repo->setting('activity_log_chat_id', (string)($config['activity_log_chat_id'] ?? '')) ?? ''));
    if ($logChat !== '') $targets[] = $logChat;
    foreach (array_unique($targets) as $target) {
        try {
            if (($payment['receipt_type'] ?? '') === 'photo') {
                $tg->sendPhoto($target, (string)$payment['receipt_file_id'], $msg, admin_payment_keyboard((int)$payment['id']));
            } elseif (($payment['receipt_type'] ?? '') === 'document') {
                $tg->sendDocument($target, (string)$payment['receipt_file_id'], $msg, admin_payment_keyboard((int)$payment['id']));
            } else {
                $tg->sendMessage($target, $msg . "\nرسید: <code>" . h((string)$payment['receipt_file_id']) . "</code>", admin_payment_keyboard((int)$payment['id']));
            }
        } catch (Throwable $e) { app_log('payment notify failed', ['target' => $target, 'error' => $e->getMessage()]); }
    }
}
function notify_admins_user_start(Telegram $tg, Repository $repo, array $config, array $startedUser, bool $wasNew): void
{
    // استارت ادمین‌ها به خودشان گزارش داده نمی‌شود تا اعلان مدیریتی بی‌دلیل شلوغ نشود.
    if (($startedUser['role'] ?? '') === 'admin') return;

    $telegramId = digits_only((string)($startedUser['telegram_id'] ?? ''));
    if ($telegramId === '') return;

    $targets = array_merge(
        array_map('strval', $config['super_admin_ids'] ?? []),
        $repo->listAdminTelegramIds()
    );
    $targets = array_values(array_unique(array_filter(array_map(
        static fn($id) => digits_only((string)$id),
        $targets
    ))));

    $username = !empty($startedUser['username']) ? '@' . h((string)$startedUser['username']) : '-';
    $msg = ($wasNew ? "🆕 <b>کاربر جدید ربات مادر را استارت زد</b>" : "🔔 <b>کاربر ربات مادر را دوباره استارت زد</b>") . "\n\n" .
        "نام: <b>" . h(user_display_name($startedUser)) . "</b>\n" .
        "آیدی عددی: <code>" . h($telegramId) . "</code>\n" .
        "یوزرنیم: <b>" . $username . "</b>\n" .
        "نقش: <b>" . role_fa((string)($startedUser['role'] ?? 'customer')) . "</b>\n" .
        "موجودی: <b>" . money_format_ir((int)($startedUser['balance'] ?? 0)) . "</b>\n" .
        "وضعیت: <b>" . h((string)($startedUser['status'] ?? 'active')) . "</b>\n" .
        "زمان: <code>" . h(now()) . "</code>";

    foreach ($targets as $target) {
        if ($target === $telegramId) continue;
        try {
            $tg->sendMessage($target, $msg, admin_user_keyboard($telegramId));
        } catch (Throwable $e) {
            app_log('user start admin notify failed', ['target' => $target, 'user' => $telegramId, 'error' => $e->getMessage()]);
        }
    }
}
function can_admin(array $user): bool { return ($user['role'] ?? '') === 'admin'; }

try {
    $secret = (string)($_GET['secret'] ?? '');
    $expected = (string)($config['main_webhook_secret'] ?? '');
    $headerSecret = $_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] ?? '';
    if ($expected !== '' && !hash_equals($expected, $secret) && !hash_equals($expected, $headerSecret)) { http_response_code(403); exit('forbidden'); }

    $update = json_decode(file_get_contents('php://input') ?: '{}', true) ?: [];
    $tg = new Telegram((string)$config['main_bot_token']);
    $service = new BotService($repo, $security, $config);
    $callback = $update['callback_query'] ?? null;
    $message = $update['message'] ?? ($callback['message'] ?? null);
    $from = $callback['from'] ?? ($message['from'] ?? []);
    $chatId = (int)($message['chat']['id'] ?? 0);
    $text = trim((string)($message['text'] ?? ($message['caption'] ?? '')));
    if ($chatId <= 0 || !$from) json_response(['ok' => true]);

    $telegramId = (string)($from['id'] ?? '');
    $wasNew = !$repo->findUserByTelegramId($telegramId);
    $user = $repo->upsertUser([
        'telegram_id' => $telegramId,
        'username' => $from['username'] ?? null,
        'first_name' => $from['first_name'] ?? null,
        'last_name' => $from['last_name'] ?? null,
    ]);

    if (($user['status'] ?? 'active') === 'blocked') {
        $tg->sendMessage($chatId, '⛔️ دسترسی شما به ربات توسط مدیریت مسدود شده است.');
        json_response(['ok' => true]);
    }

    if ($callback) {
        $data = (string)($callback['data'] ?? '');
        $callbackId = (string)($callback['id'] ?? '');
        if ($callbackId !== '') $tg->answerCallbackQuery($callbackId);

        if (preg_match('/^pay_ok_(\d+)$/', $data, $m)) {
            if (!can_admin($user)) { $tg->sendMessage($chatId, 'دسترسی ادمین لازم است.'); json_response(['ok'=>true]); }
            $payment = $repo->approveTopup((int)$m[1], (int)$user['id']);
            $tg->sendMessage($chatId, '✅ رسید تایید شد و موجودی کاربر افزایش پیدا کرد.');
            $tg->sendMessage((string)$payment['telegram_id'], "✅ رسید واریزی شما تایید شد.\nمبلغ <b>" . money_format_ir((int)$payment['amount']) . "</b> به حساب کاربری شما اضافه شد.", account_keyboard($config));
            activity_notify($repo, $config, "✅ <b>رسید تایید شد</b>\nدرخواست: #" . (int)$payment['id'] . "\nمبلغ: " . money_format_ir((int)$payment['amount']) . "\nادمین: " . format_user_for_log($user));
            json_response(['ok'=>true]);
        }
        if (preg_match('/^pay_no_(\d+)$/', $data, $m)) {
            if (!can_admin($user)) { $tg->sendMessage($chatId, 'دسترسی ادمین لازم است.'); json_response(['ok'=>true]); }
            $repo->setState((int)$user['id'], 'awaiting_payment_reject_reason', ['payment_id' => (int)$m[1]]);
            $tg->sendMessage($chatId, "❌ برای رد کردن رسید #" . (int)$m[1] . " دلیل رد را بنویس.", flow_keyboard());
            json_response(['ok'=>true]);
        }

        if (preg_match('/^adm_(ban|add|sub|msg)_(\d+)$/', $data, $m)) {
            if (!can_admin($user)) {
                $tg->sendMessage($chatId, '⛔️ فقط ادمین اجازه استفاده از این دکمه را دارد.');
                json_response(['ok'=>true]);
            }

            $action = (string)$m[1];
            $targetTelegramId = digits_only((string)$m[2]);
            $targetUser = $repo->findUserByTelegramId($targetTelegramId);
            if (!$targetUser) {
                $tg->sendMessage($chatId, '❌ کاربر موردنظر پیدا نشد.');
                json_response(['ok'=>true]);
            }

            if ($action === 'ban') {
                if ((int)$targetUser['id'] === (int)$user['id'] || ($targetUser['role'] ?? '') === 'admin') {
                    $tg->sendMessage($chatId, '⛔️ بن کردن حساب ادمین از این بخش مجاز نیست.');
                    json_response(['ok'=>true]);
                }
                if (($targetUser['status'] ?? '') === 'blocked') {
                    $tg->sendMessage($chatId, 'ℹ️ این کاربر از قبل بن شده است.');
                    json_response(['ok'=>true]);
                }
                $updated = $repo->updateUserStatusByTelegramId($targetTelegramId, 'blocked', (int)$user['id']);
                $repo->clearState((int)$updated['id']);
                $tg->sendMessage($chatId, "✅ کاربر " . format_user_for_log($updated) . " از ربات بن شد.");
                try {
                    $tg->sendMessage($targetTelegramId, '⛔️ دسترسی شما به ربات توسط مدیریت مسدود شد.');
                } catch (Throwable $e) {
                    app_log('blocked user notification failed', ['user' => $targetTelegramId, 'error' => $e->getMessage()]);
                }
                json_response(['ok'=>true]);
            }

            if ($action === 'add' || $action === 'sub') {
                $stateName = $action === 'add' ? 'awaiting_admin_balance_add' : 'awaiting_admin_balance_sub';
                $repo->setState((int)$user['id'], $stateName, ['target_telegram_id' => $targetTelegramId]);
                $verb = $action === 'add' ? 'افزایش' : 'کاهش';
                $tg->sendMessage(
                    $chatId,
                    "💰 مبلغ <b>{$verb} موجودی</b> برای کاربر زیر را به تومان و فقط به‌صورت عدد ارسال کن:\n" .
                    format_user_for_log($targetUser) . "\n\nمثال: <code>250000</code>",
                    flow_keyboard()
                );
                json_response(['ok'=>true]);
            }

            if ($action === 'msg') {
                $repo->setState((int)$user['id'], 'awaiting_admin_user_message', ['target_telegram_id' => $targetTelegramId]);
                $tg->sendMessage(
                    $chatId,
                    "✉️ متن پیامی که باید برای کاربر زیر ارسال شود را بنویس:\n" . format_user_for_log($targetUser),
                    flow_keyboard()
                );
                json_response(['ok'=>true]);
            }
        }

        if ($data === 'check_join') {
            if (missing_required_joins($repo, $tg, $user['telegram_id'])) send_join_required($tg, $repo, $chatId);
            else $tg->sendMessage($chatId, '✅ عضویت تأیید شد. از منوی زیر استفاده کن.', main_inline_keyboard($config, $user));
            json_response(['ok' => true]);
        }
        if (missing_required_joins($repo, $tg, $user['telegram_id'])) { send_join_required($tg, $repo, $chatId); json_response(['ok' => true]); }

        if ($data === 'main_menu') { $repo->clearState((int)$user['id']); $tg->sendMessage($chatId, '🏠 منوی اصلی', main_inline_keyboard($config, $user)); json_response(['ok'=>true]); }
        if ($data === 'cancel_flow') { $repo->clearState((int)$user['id']); $tg->sendMessage($chatId, '❌ عملیات لغو شد.', main_inline_keyboard($config, $user)); json_response(['ok'=>true]); }
        if ($data === 'account') { $repo->clearState((int)$user['id']); $tg->sendMessage($chatId, account_message($repo, $user), account_keyboard($config)); json_response(['ok'=>true]); }
        if ($data === 'topup') { $repo->clearState((int)$user['id']); $tg->sendMessage($chatId, topup_start_message($repo), payment_method_keyboard()); json_response(['ok'=>true]); }
        if ($data === 'topup_card') {
            $repo->setState((int)$user['id'], 'awaiting_topup_amount');
            $tg->sendMessage($chatId, topup_card_message($repo), flow_keyboard());
            json_response(['ok'=>true]);
        }
        if ($data === 'topup_send_receipt') {
            $state = $repo->getState((int)$user['id']);
            $amount = (int)($state['payload_decoded']['amount'] ?? 0);
            if (($state['state'] ?? '') !== 'awaiting_topup_receipt_button' || $amount <= 0) {
                $repo->setState((int)$user['id'], 'awaiting_topup_amount');
                $tg->sendMessage($chatId, 'اول مبلغ واریزی را وارد کن.', flow_keyboard());
                json_response(['ok'=>true]);
            }
            $repo->setState((int)$user['id'], 'awaiting_topup_receipt', ['amount' => $amount]);
            $tg->sendMessage($chatId, "📤 حالا رسید واریزی را به صورت عکس یا فایل ارسال کن.\nمبلغ ثبت‌شده: <b>" . money_format_ir($amount) . "</b>", flow_keyboard());
            json_response(['ok'=>true]);
        }
        if ($data === 'add_bot') {
            $plans = active_bot_plans($repo);
            if (!$plans) {
                $tg->sendMessage($chatId, "❌ هنوز هیچ پلن فعالی توسط ادمین ثبت نشده است. لطفاً بعداً دوباره امتحان کن.", main_inline_keyboard($config, $user));
                json_response(['ok'=>true]);
            }
            $repo->clearState((int)$user['id']);
            $tg->sendMessage($chatId, add_bot_plans_message($plans), add_bot_plan_keyboard($plans));
            json_response(['ok'=>true]);
        }
        if (preg_match('/^addbot_plan_(\d+)$/', $data, $m)) {
            $plan = $repo->getPlan((int)$m[1]);
            if (!$plan || ($plan['status'] ?? '') !== 'active') {
                $plans = active_bot_plans($repo);
                $tg->sendMessage($chatId, "❌ این پلن دیگر فعال نیست. لطفاً یک پلن جدید انتخاب کن.", $plans ? add_bot_plan_keyboard($plans) : main_inline_keyboard($config, $user));
                json_response(['ok'=>true]);
            }
            $price = (int)$plan['price'];
            $fresh = $repo->findUserById((int)$user['id']) ?: $user;
            if ((int)$fresh['balance'] < $price) {
                $need = max(0, $price - (int)$fresh['balance']);
                $tg->sendMessage($chatId, "➕ <b>افزودن ربات</b>\n\nپلن انتخابی: <b>" . h((string)$plan['title']) . "</b>\nقیمت پلن: <b>" . money_format_ir($price) . "</b>\nموجودی فعلی شما: <b>" . money_format_ir((int)$fresh['balance']) . "</b>\nمبلغ مورد نیاز برای شارژ: <b>" . money_format_ir($need) . "</b>\n\nبرای ادامه اول موجودی را افزایش بده.", add_bot_charge_keyboard());
                json_response(['ok'=>true]);
            }
            $repo->setState((int)$user['id'], 'awaiting_child_token', ['plan_id' => (int)$plan['id']]);
            $tg->sendMessage($chatId, "✅ پلن انتخاب شد: <b>" . h((string)$plan['title']) . "</b>\nمدت: <b>" . (int)$plan['months'] . " ماه</b>\nهزینه بعد از ثبت موفق: <b>" . money_format_ir($price) . "</b>\n\nحالا توکن رباتی که از BotFather گرفتی را ارسال کن.\nبعد از توکن، آیدی عددی مالک ربات را جداگانه می‌گیرم و دقیقاً همان آیدی مالک ربات وبهوک‌شده می‌شود.\nنمونه توکن:\n<code>123456789:AA...</code>", flow_keyboard());
            json_response(['ok'=>true]);
        }
        if ($data === 'my_bots') { send_my_bots($tg, $repo, $config, $chatId, $user); json_response(['ok'=>true]); }
        if ($data === 'plans') { send_plans($tg, $repo, $config, $chatId, $user); json_response(['ok'=>true]); }
        if ($data === 'support') { $repo->setState((int)$user['id'], 'awaiting_support_message'); $tg->sendMessage($chatId, "🆘 پیام پشتیبانی‌ات را ارسال کن.\n\nبرای برگشت یا لغو از دکمه‌های زیر استفاده کن.", flow_keyboard()); json_response(['ok'=>true]); }
        $tg->sendMessage($chatId, 'دکمه نامعتبر است. از منوی زیر استفاده کن.', main_inline_keyboard($config, $user)); json_response(['ok'=>true]);
    }

    if ($text === '/start' || $text === 'شروع') {
        $repo->clearState((int)$user['id']);
        if ($wasNew) { $repo->audit((int)$user['id'], 'new_user_start', ['telegram_id'=>$user['telegram_id']]); activity_notify($repo, $config, "👤 <b>کاربر جدید ربات را استارت زد</b>\n" . format_user_for_log($user) . "\nزمان: <code>" . h(now()) . "</code>"); }
        else $repo->audit((int)$user['id'], 'user_start', ['telegram_id'=>$user['telegram_id']]);
        $freshStartedUser = $repo->findUserById((int)$user['id']) ?: $user;
        notify_admins_user_start($tg, $repo, $config, $freshStartedUser, $wasNew);
        if (missing_required_joins($repo, $tg, $user['telegram_id'])) { send_join_required($tg, $repo, $chatId); json_response(['ok'=>true]); }
        $tg->sendMessage($chatId, "👋 به <b>ربات ساز میرزا احسان نت</b> خوش آمدی.\n\nنقش شما: <b>" . role_fa((string)$user['role']) . "</b>\nاز دکمه‌های شیشه‌ای زیر استفاده کن.", main_inline_keyboard($config, $user));
        json_response(['ok'=>true]);
    }
    if (missing_required_joins($repo, $tg, $user['telegram_id'])) { send_join_required($tg, $repo, $chatId); json_response(['ok'=>true]); }
    if ($text === '/panel') { $tg->sendMessage($chatId, 'برای ورود به پنل روی دکمه زیر بزن:', ['inline_keyboard'=>[[['text'=>'🌐 باز کردن پنل','web_app'=>['url'=>bot_panel_url($config)]]]]]); json_response(['ok'=>true]); }
    if ($text === '/cancel' || $text === 'لغو') { $repo->clearState((int)$user['id']); $tg->sendMessage($chatId, '❌ عملیات لغو شد.', main_inline_keyboard($config, $user)); json_response(['ok'=>true]); }

    $state = $repo->getState((int)$user['id']);
    if ($state && in_array((string)$state['state'], ['awaiting_admin_balance_add','awaiting_admin_balance_sub','awaiting_admin_user_message'], true)) {
        if (!can_admin($user)) {
            $repo->clearState((int)$user['id']);
            json_response(['ok'=>true]);
        }

        $targetTelegramId = digits_only((string)($state['payload_decoded']['target_telegram_id'] ?? ''));
        $targetUser = $targetTelegramId !== '' ? $repo->findUserByTelegramId($targetTelegramId) : null;
        if (!$targetUser) {
            $repo->clearState((int)$user['id']);
            $tg->sendMessage($chatId, '❌ کاربر موردنظر دیگر پیدا نشد.', main_inline_keyboard($config, $user));
            json_response(['ok'=>true]);
        }

        if ($state['state'] === 'awaiting_admin_user_message') {
            if ($text === '') {
                $tg->sendMessage($chatId, 'متن پیام را ارسال کن یا عملیات را لغو کن.', flow_keyboard());
                json_response(['ok'=>true]);
            }
            try {
                $tg->sendMessage($targetTelegramId, "📩 <b>پیام مدیریت</b>\n\n" . h($text));
                $repo->audit((int)$user['id'], 'admin_message_user', [
                    'telegram_id' => $targetTelegramId,
                    'message' => mb_substr($text, 0, 500),
                ]);
                $repo->clearState((int)$user['id']);
                $tg->sendMessage($chatId, "✅ پیام برای " . format_user_for_log($targetUser) . " ارسال شد.", main_inline_keyboard($config, $user));
            } catch (Throwable $e) {
                app_log('admin message to user failed', ['admin' => $user['telegram_id'], 'user' => $targetTelegramId, 'error' => $e->getMessage()]);
                $tg->sendMessage($chatId, "❌ ارسال پیام انجام نشد: " . h($e->getMessage()) . "\nدوباره تلاش کن یا عملیات را لغو کن.", flow_keyboard());
            }
            json_response(['ok'=>true]);
        }

        $amount = int_amount($text);
        if ($amount <= 0) {
            $tg->sendMessage($chatId, '❌ مبلغ نامعتبر است. فقط یک عدد بزرگ‌تر از صفر بفرست.', flow_keyboard());
            json_response(['ok'=>true]);
        }

        $isAdd = $state['state'] === 'awaiting_admin_balance_add';
        $signedAmount = $isAdd ? $amount : -$amount;
        try {
            $updated = $repo->chargeUser(
                (int)$user['id'],
                $targetTelegramId,
                $signedAmount,
                $isAdd ? 'افزایش موجودی از دکمه مدیریتی تلگرام' : 'کاهش موجودی از دکمه مدیریتی تلگرام'
            );
            $repo->clearState((int)$user['id']);
            $verb = $isAdd ? 'افزایش' : 'کاهش';
            $tg->sendMessage(
                $chatId,
                "✅ {$verb} موجودی انجام شد.\nکاربر: " . format_user_for_log($updated) . "\nمبلغ: <b>" . money_format_ir($amount) . "</b>\nموجودی جدید: <b>" . money_format_ir((int)$updated['balance']) . "</b>",
                main_inline_keyboard($config, $user)
            );
            try {
                $userText = $isAdd
                    ? "✅ مبلغ <b>" . money_format_ir($amount) . "</b> توسط مدیریت به موجودی شما اضافه شد."
                    : "➖ مبلغ <b>" . money_format_ir($amount) . "</b> توسط مدیریت از موجودی شما کسر شد.";
                $tg->sendMessage($targetTelegramId, $userText . "\nموجودی جدید: <b>" . money_format_ir((int)$updated['balance']) . "</b>", account_keyboard($config));
            } catch (Throwable $e) {
                app_log('balance change user notification failed', ['user' => $targetTelegramId, 'error' => $e->getMessage()]);
            }
        } catch (Throwable $e) {
            $tg->sendMessage($chatId, "❌ عملیات انجام نشد: " . h($e->getMessage()) . "\nمبلغ دیگری بفرست یا عملیات را لغو کن.", flow_keyboard());
        }
        json_response(['ok'=>true]);
    }
    if ($state && $state['state'] === 'awaiting_payment_reject_reason' && $text !== '') {
        if (!can_admin($user)) { $repo->clearState((int)$user['id']); json_response(['ok'=>true]); }
        $paymentId = (int)($state['payload_decoded']['payment_id'] ?? 0);
        $payment = $repo->rejectTopup($paymentId, (int)$user['id'], $text);
        $repo->clearState((int)$user['id']);
        $tg->sendMessage($chatId, '❌ رسید رد شد و دلیل برای کاربر ارسال شد.', main_inline_keyboard($config, $user));
        $tg->sendMessage((string)$payment['telegram_id'], "❌ رسید واریزی شما رد شد.\nدلیل: <b>" . h($text) . "</b>\nلطفاً دوباره از بخش افزایش موجودی اقدام کن.", account_keyboard($config));
        activity_notify($repo, $config, "❌ <b>رسید رد شد</b>\nدرخواست: #" . $paymentId . "\nدلیل: " . h($text) . "\nادمین: " . format_user_for_log($user));
        json_response(['ok'=>true]);
    }
    if ($state && $state['state'] === 'awaiting_topup_amount' && $text !== '') {
        $amount = int_amount($text); $s = $repo->paymentSettings();
        if ($amount < (int)$s['topup_min_amount'] || $amount > (int)$s['topup_max_amount']) {
            $tg->sendMessage($chatId, "❌ مبلغ باید بین <b>" . money_format_ir((int)$s['topup_min_amount']) . "</b> تا <b>" . money_format_ir((int)$s['topup_max_amount']) . "</b> باشد.", flow_keyboard());
            json_response(['ok'=>true]);
        }
        $repo->setState((int)$user['id'], 'awaiting_topup_receipt_button', ['amount'=>$amount]);
        $tg->sendMessage($chatId, "✅ مبلغ ثبت شد: <b>" . money_format_ir($amount) . "</b>\n\nبعد از کارت به کارت، روی دکمه «ارسال تراکنش واریزی» بزن.", receipt_action_keyboard());
        json_response(['ok'=>true]);
    }
    if ($state && $state['state'] === 'awaiting_topup_receipt') {
        $amount = (int)($state['payload_decoded']['amount'] ?? 0);
        $receiptType = ''; $fileId = '';
        if (!empty($message['photo'])) { $receiptType = 'photo'; $photos = $message['photo']; $fileId = (string)end($photos)['file_id']; }
        elseif (!empty($message['document'])) { $receiptType = 'document'; $fileId = (string)$message['document']['file_id']; }
        elseif ($text !== '') { $receiptType = 'text'; $fileId = $text; }
        if ($amount <= 0 || $fileId === '') {
            $tg->sendMessage($chatId, '❌ رسید دریافت نشد. رسید را به صورت عکس یا فایل ارسال کن.', flow_keyboard()); json_response(['ok'=>true]);
        }
        $payment = $repo->createTopupRequest((int)$user['id'], $amount, $receiptType, $fileId, $text ?: null);
        $repo->clearState((int)$user['id']);
        $tg->sendMessage($chatId, "✅ رسید شما ثبت شد و جهت بررسی برای ادمین ارسال شد.\nشناسه پیگیری: <b>#" . (int)$payment['id'] . "</b>", main_inline_keyboard($config, $user));
        notify_admins_payment($tg, $repo, $config, $payment);
        json_response(['ok'=>true]);
    }
    if ($state && $state['state'] === 'awaiting_child_token') {
        if (!Telegram::isValidTokenFormat($text)) { $tg->sendMessage($chatId, "❌ فرمت توکن درست نیست. توکن کامل را از BotFather کپی کن و دوباره بفرست.", flow_keyboard()); json_response(['ok'=>true]); }
        $planId = (int)($state['payload_decoded']['plan_id'] ?? 0);
        $plan = $planId > 0 ? $repo->getPlan($planId) : null;
        if (!$plan || ($plan['status'] ?? '') !== 'active') {
            $repo->clearState((int)$user['id']);
            $plans = active_bot_plans($repo);
            $tg->sendMessage($chatId, "❌ پلن انتخاب‌شده حذف یا غیرفعال شده است. لطفاً دوباره افزودن ربات را بزن و پلن جدید انتخاب کن.", $plans ? add_bot_plan_keyboard($plans) : main_inline_keyboard($config, $user));
            json_response(['ok'=>true]);
        }
        $repo->setState((int)$user['id'], 'awaiting_child_owner_id', [
            'plan_id' => (int)$plan['id'],
            'child_token' => $text,
        ]);
        $tg->sendMessage($chatId, "✅ توکن ربات دریافت شد.\n\nحالا <b>آیدی عددی مالک ربات</b> را ارسال کن؛ دقیقاً همین آیدی داخل رباتی که وبهوک می‌شود به عنوان مالک/ادمین اصلی با دسترسی کامل ثبت می‌شود.\n\nنمونه:\n<code>123456789</code>", flow_keyboard());
        json_response(['ok'=>true]);
    }

    if ($state && $state['state'] === 'awaiting_child_owner_id') {
        $ownerTelegramId = digits_only($text);
        if ($ownerTelegramId === '') { $tg->sendMessage($chatId, "❌ آیدی عددی مالک معتبر نیست. فقط عدد آیدی تلگرام مالک را بفرست.\nنمونه: <code>123456789</code>", flow_keyboard()); json_response(['ok'=>true]); }
        $planId = (int)($state['payload_decoded']['plan_id'] ?? 0);
        $childToken = trim((string)($state['payload_decoded']['child_token'] ?? ''));
        if (!Telegram::isValidTokenFormat($childToken)) {
            $repo->clearState((int)$user['id']);
            $tg->sendMessage($chatId, "❌ توکن ذخیره‌شده معتبر نبود. لطفاً دوباره از افزودن ربات شروع کن.", main_inline_keyboard($config, $user));
            json_response(['ok'=>true]);
        }
        $plan = $planId > 0 ? $repo->getPlan($planId) : null;
        if (!$plan || ($plan['status'] ?? '') !== 'active') {
            $repo->clearState((int)$user['id']);
            $plans = active_bot_plans($repo);
            $tg->sendMessage($chatId, "❌ پلن انتخاب‌شده حذف یا غیرفعال شده است. لطفاً دوباره افزودن ربات را بزن و پلن جدید انتخاب کن.", $plans ? add_bot_plan_keyboard($plans) : main_inline_keyboard($config, $user));
            json_response(['ok'=>true]);
        }
        $price = (int)$plan['price'];
        $months = max(1, (int)$plan['months']);
        try {
            $fresh = $repo->findUserById((int)$user['id']) ?: $user;
            if ((int)$fresh['balance'] < $price) {
                $need = max(0, $price - (int)$fresh['balance']);
                $repo->clearState((int)$user['id']);
                $tg->sendMessage($chatId, "❌ موجودی کافی نیست.\nپلن: <b>" . h((string)$plan['title']) . "</b>\nهزینه: <b>" . money_format_ir($price) . "</b>\nموجودی شما: <b>" . money_format_ir((int)$fresh['balance']) . "</b>\nکسری موجودی: <b>" . money_format_ir($need) . "</b>", add_bot_charge_keyboard());
                json_response(['ok'=>true]);
            }
            $tg->sendMessage($chatId, "⏳ ربات شما درحال آماده سازی و وبهوک شدن میباشد.\nمالک ثبت‌شونده: <code>" . h($ownerTelegramId) . "</code>\nاز صبر و شکیبایی شما سپاسگذاریم.");
            @set_time_limit(0);
            @ignore_user_abort(true);
            $debited = false;
            if ($price > 0) {
                $repo->debitUserBalance((int)$user['id'], $price, 'هزینه ساخت ربات با پلن ' . (string)$plan['title']);
                $debited = true;
            }
            try {
                $bot = $service->registerChildBot((int)$user['id'], $ownerTelegramId, $childToken, (int)$plan['id'], $months, $price);
            } catch (Throwable $e) {
                if ($debited && $price > 0) {
                    try { $repo->chargeUser((int)$user['id'], (string)$user['telegram_id'], $price, 'برگشت وجه ساخت ربات ناموفق'); }
                    catch (Throwable $refundError) { app_log('telegram bot create refund failed', ['user_id'=>$user['id'], 'amount'=>$price, 'error'=>$refundError->getMessage()]); }
                }
                throw $e;
            }
            $repo->clearState((int)$user['id']);
            $tg->sendMessage($chatId, "✅ ربات ثبت شد و وبهوک آن روی سورس ربات میرزا ساز احسان نت فعال شد.\n\nنام ربات: @" . h((string)$bot['bot_username']) . "\nشماره: <b>" . (int)$bot['id'] . "</b>\nمالک ربات: <code>" . h($ownerTelegramId) . "</code>\nپلن: <b>" . h((string)$plan['title']) . "</b>\nهزینه کسر شده: <b>" . money_format_ir($price) . "</b>\nاعتبار تا: <b>" . h(fa_date((string)$bot['expires_at'])) . '</b>', main_inline_keyboard($config, $repo->findUserById((int)$user['id']) ?: $user));
            activity_notify($repo, $config, "🤖 <b>ربات جدید با سورس ربات میرزا ساز احسان نت ثبت شد</b>\nمجری: " . format_user_for_log($user) . "\nمالک ربات: <code>" . h($ownerTelegramId) . "</code>\nربات: @" . h((string)$bot['bot_username']) . "\nپلن: <b>" . h((string)$plan['title']) . "</b>\nهزینه: " . money_format_ir($price) . "\nانقضا: <code>" . h((string)$bot['expires_at']) . "</code>");
        } catch (Throwable $e) { $tg->sendMessage($chatId, "❌ ثبت ربات انجام نشد:\n" . h($e->getMessage()) . "\n\nآیدی مالک را دوباره بفرست یا عملیات را لغو کن.", flow_keyboard()); }
        json_response(['ok'=>true]);
    }

    if ($state && $state['state'] === 'awaiting_support_message' && $text !== '') {
        $repo->createTicket((int)$user['id'], 'پیام تلگرام', $text); $repo->audit((int)$user['id'], 'support_ticket_telegram', ['message'=>mb_substr($text,0,120)]); $repo->clearState((int)$user['id']);
        $tg->sendMessage($chatId, '✅ پیام شما ثبت شد. پشتیبانی بررسی می‌کند.', main_inline_keyboard($config, $user));
        activity_notify($repo, $config, "🆘 <b>پیام پشتیبانی جدید</b>\nکاربر: " . format_user_for_log($user) . "\nمتن: " . h(mb_substr($text,0,500))); json_response(['ok'=>true]);
    }
    if ($text === '/health') { $s = $repo->stats((int)$user['id'], (string)$user['role']); $tg->sendMessage($chatId, "✅ اتصال ربات، دیتابیس و پنل برقرار است.\nتعداد ربات‌ها: <b>" . (int)$s['bots'] . '</b>', main_inline_keyboard($config, $user)); json_response(['ok'=>true]); }
    $tg->sendMessage($chatId, 'از دکمه‌های شیشه‌ای زیر استفاده کن.', main_inline_keyboard($config, $user)); json_response(['ok'=>true]);
} catch (Throwable $e) {
    app_log('main bot error', ['error' => $e->getMessage()]);
    http_response_code(200); echo 'ok';
}
