import asyncio
import logging
import sqlite3
import re
import httpx
from datetime import datetime
from telegram import (
    InlineKeyboardButton, 
    InlineKeyboardMarkup, 
    KeyboardButton, 
    ReplyKeyboardMarkup, 
    ReplyKeyboardRemove, 
    Update
)
from telegram.ext import (
    Application,
    CallbackQueryHandler,
    CommandHandler,
    ContextTypes,
    MessageHandler,
    filters,
)

# فعال‌سازی لاگ
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)

BOT_TOKEN = "8892257799:AAFURKmyz1FELpqur41m1h9AX9yAdzOVZR4"
GROUP_ID = -1003915035246
CHANNEL_USERNAME = "@priimenet"
CHANNEL_LINK = "https://t.me/iran_gozargah"

CARD_NUMBER = "6219861959485706"
CARD_NAME = "علی اصغر سجادی"
SUPPORT_USERNAME = "primenet_sup"

OWNER_ID = 6261657720

PANEL_URL = "https://p.tiptop-1.top:8000"
PANEL_USERNAME = "@primenet_sup"
PANEL_PASSWORD = "@primenet_sup$67hGVW4"

PRICE_PER_GB = 6000
FAKE_USERS_COUNT = 15420

V2RAY_ANDROID_LINK = "https://github.com/2dust/v2rayNG/releases"
V2BOX_IOS_LINK = "https://apps.apple.com/app/v2box-v2ray-client/id6446814190"

async def get_panel_token():
    try:
        url = f"{PANEL_URL}/api/admin/token"
        payload = {'username': PANEL_USERNAME, 'password': PANEL_PASSWORD}
        async with httpx.AsyncClient(verify=False, timeout=10.0) as client:
            response = await client.post(url, data=payload)
            if response.status_code == 200:
                return response.json().get("access_token")
    except Exception as e:
        logging.error(f"Panel Token Exception: {e}")
    return None

async def create_panel_user(username: str, data_limit_gb: int):
    token = await get_panel_token()
    if not token:
        return None, "خطا در برقراری ارتباط با API پنل"

    headers = {'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'}
    data_limit_bytes = data_limit_gb * 1024 * 1024 * 1024

    payload = {
        "username": username,
        "data_limit": data_limit_bytes,
        "expire": 0,
        "proxies": {"vmess": {}, "vless": {}},
        "inbounds": {}
    }

    try:
        url = f"{PANEL_URL}/api/user"
        async with httpx.AsyncClient(verify=False, timeout=12.0) as client:
            response = await client.post(url, json=payload, headers=headers)
            if response.status_code in [200, 201]:
                return response.json(), None
            else:
                return None, f"خطای پنل ({response.status_code}): {response.text}"
    except Exception as e:
        return None, f"خطای استثنا شبکه: {e}"

async def get_panel_user_info(username: str):
    token = await get_panel_token()
    if not token:
        return None
    headers = {'Authorization': f'Bearer {token}'}
    try:
        url = f"{PANEL_URL}/api/user/{username}"
        async with httpx.AsyncClient(verify=False, timeout=10.0) as client:
            response = await client.get(url, headers=headers)
            if response.status_code == 200:
                return response.json()
    except Exception as e:
        logging.error(f"Error fetching user info for {username}: {e}")
    return None

def init_db():
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS users (
            user_id INTEGER PRIMARY KEY,
            full_name TEXT,
            username TEXT,
            phone_number TEXT,
            balance INTEGER DEFAULT 0,
            is_banned INTEGER DEFAULT 0,
            join_date TEXT
        )
    """)
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS pending_receipts (
            receipt_id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER,
            config_name TEXT,
            gb INTEGER,
            price INTEGER,
            type TEXT DEFAULT 'buy_plan'
        )
    """)
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS orders (
            order_id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER,
            config_name TEXT,
            plan_name TEXT,
            price INTEGER,
            sub_url TEXT,
            date_time TEXT
        )
    """)
    
    try:
        cursor.execute("ALTER TABLE users ADD COLUMN is_banned INTEGER DEFAULT 0")
    except sqlite3.OperationalError:
        pass

    conn.commit()
    conn.close()

init_db()

def register_user(user_id, full_name, username, phone_number=None):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    if phone_number:
        cursor.execute("INSERT INTO users (user_id, full_name, username, phone_number, join_date) VALUES (?, ?, ?, ?, ?) ON CONFLICT(user_id) DO UPDATE SET phone_number=excluded.phone_number",
                       (user_id, full_name, username, phone_number, datetime.now().strftime("%Y-%m-%d %H:%M")))
    else:
        cursor.execute("INSERT OR IGNORE INTO users (user_id, full_name, username, join_date) VALUES (?, ?, ?, ?)",
                       (user_id, full_name, username, datetime.now().strftime("%Y-%m-%d %H:%M")))
    conn.commit()
    conn.close()

def is_user_banned(user_id):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("SELECT is_banned FROM users WHERE user_id = ?", (user_id,))
    row = cursor.fetchone()
    conn.close()
    return row[0] if row and row[0] else 0

def toggle_ban_user(user_id, status: int):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("UPDATE users SET is_banned = ? WHERE user_id = ?", (status, user_id))
    conn.commit()
    conn.close()

def get_user_balance(user_id):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("SELECT balance FROM users WHERE user_id = ?", (user_id,))
    row = cursor.fetchone()
    conn.close()
    return row[0] if row and row[0] else 0

def update_user_balance(user_id, amount_toman):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("UPDATE users SET balance = balance + ? WHERE user_id = ?", (amount_toman, user_id))
    conn.commit()
    conn.close()

def get_user_phone(user_id):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("SELECT phone_number FROM users WHERE user_id = ?", (user_id,))
    row = cursor.fetchone()
    conn.close()
    return row[0] if row else None

def save_pending_receipt(user_id, config_name, gb, price, r_type='buy_plan'):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("INSERT INTO pending_receipts (user_id, config_name, gb, price, type) VALUES (?, ?, ?, ?, ?)",
                   (user_id, config_name, gb, price, r_type))
    receipt_id = cursor.lastrowid
    conn.commit()
    conn.close()
    return receipt_id

def get_pending_receipt(receipt_id):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("SELECT user_id, config_name, gb, price, type FROM pending_receipts WHERE receipt_id = ?", (receipt_id,))
    row = cursor.fetchone()
    conn.close()
    return row

def add_order(user_id, config_name, plan_name, price, sub_url):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("""
        INSERT INTO orders (user_id, config_name, plan_name, price, sub_url, date_time) 
        VALUES (?, ?, ?, ?, ?, ?)
    """, (user_id, config_name, plan_name, price, sub_url, datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
    conn.commit()
    conn.close()

def get_user_orders(user_id):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("SELECT config_name, plan_name, sub_url, date_time FROM orders WHERE user_id = ? ORDER BY order_id DESC", (user_id,))
    rows = cursor.fetchall()
    conn.close()
    return rows

def get_all_user_ids():
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("SELECT user_id FROM users WHERE is_banned = 0")
    rows = cursor.fetchall()
    conn.close()
    return [r[0] for r in rows]

async def check_membership(update: Update, context: ContextTypes.DEFAULT_TYPE) -> bool:
    user_id = update.effective_user.id
    try:
        member = await context.bot.get_chat_member(chat_id=CHANNEL_USERNAME, user_id=user_id)
        if member.status in ["member", "administrator", "creator"]:
            return True
    except Exception:
        pass
    return False

def channel_keyboard():
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("📢 عضویت در کانال اطلاع‌رسانی", url=CHANNEL_LINK)],
        [InlineKeyboardButton("🟢 عضو شدم / تایید", callback_data="check_join")],
    ])

def main_menu_keyboard(user_id):
    conn = sqlite3.connect("bot_database.db")
    cursor = conn.cursor()
    cursor.execute("SELECT COUNT(*) FROM users")
    real_users = cursor.fetchone()[0]
    conn.close()
    total = FAKE_USERS_COUNT + real_users

    buttons = [
        [InlineKeyboardButton(f"👥 تعداد کاربران: {total:,} نفر", callback_data="none")],
        [InlineKeyboardButton("🟢 خرید اشتراک دلخواه", callback_data="buy_custom_start")],
        [InlineKeyboardButton("💰 کیف پول", callback_data="wallet_menu"), InlineKeyboardButton("🛍️ کانفیگ‌های من", callback_data="user_configs")],
        [InlineKeyboardButton("🎓 آموزش اتصال", callback_data="tutorial_menu"), InlineKeyboardButton("📞 پشتیبانی", callback_data="support_menu")]
    ]

    # فقط اگر آیدی کاربر برابر با OWNER_ID باشد دکمه پنل مدیریت اضافه می‌شود
    if user_id == OWNER_ID:
        buttons.append([InlineKeyboardButton("⚙️ پنل مدیریت ادمین", callback_data="admin_panel_menu")])

    return InlineKeyboardMarkup(buttons)

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    if is_user_banned(user.id):
        await update.message.reply_text("❌ حساب کاربری شما در ربات مسدود شده است.")
        return

    register_user(user.id, user.full_name, user.username)

    phone = get_user_phone(user.id)
    if not phone:
        contact_keyboard = ReplyKeyboardMarkup(
            [[KeyboardButton("📱 ارسال و تایید شماره تلفن", request_contact=True)]],
            resize_keyboard=True,
            one_time_keyboard=True
        )
        text = f"👋 سلام {user.first_name} عزیز!\n\n🔒 **جهت ادامه، لطفاً شماره تلفن خود را تایید کنید:شماره شما نزد ما محفوظ میباشد**"
        await update.message.reply_text(text, parse_mode="Markdown", reply_markup=contact_keyboard)
        return

    if not await check_membership(update, context):
        await update.message.reply_text("👋 جهت استفاده از ربات، در کانال ما عضو شوید:", reply_markup=channel_keyboard())
    else:
        await update.message.reply_text(f"👋 سلام {user.first_name} خوش آمدید!", reply_markup=main_menu_keyboard(user.id))

async def contact_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    contact = update.message.contact
    user = update.effective_user
    if contact and contact.user_id == user.id:
        phone = contact.phone_number
        register_user(user.id, user.full_name, user.username, phone)
        await update.message.reply_text("✅ شماره تلفن تایید شد.", reply_markup=ReplyKeyboardRemove())
        await update.message.reply_text("منوی اصلی ربات:", reply_markup=main_menu_keyboard(user.id))

async def admin_charge_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    if user.id != OWNER_ID:
        return
    try:
        target_user_id = int(context.args[0])
        amount_toman = int(context.args[1])
        update_user_balance(target_user_id, amount_toman)
        await update.message.reply_text(f"✅ کیف پول کاربر `{target_user_id}` به میزان **{amount_toman:,} تومان** شارژ شد.")
    except Exception:
        await update.message.reply_text("❌ نحوه استفاده درست:\n`/charge <user_id> <amount_toman>`", parse_mode="Markdown")

async def handle_callbacks(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    user_id = query.from_user.id
    data = query.data

    if is_user_banned(user_id):
        await query.answer("❌ حساب کاربری شما مسدود است.", show_alert=True)
        return

    # --- بخش مدیریت (ADMIN) ---
    if data == "admin_panel_menu":
        if user_id != OWNER_ID:
            await query.answer("❌ دسترسی غیرمجاز!", show_alert=True)
            return

        admin_text = (
            "⚙️ **پنل مدیریت پیشرفته ربات**\n\n"
            "لطفاً یکی از بخش‌های زیر را انتخاب کنید:"
        )
        keyboard = [
            [InlineKeyboardButton("📊 گزارش مالی و فروش", callback_data="admin_sales_report")],
            [InlineKeyboardButton("➕ افزایش / کسر موجودی", callback_data="admin_charge_user_start")],
            [InlineKeyboardButton("📢 ارسال پیام همگانی", callback_data="admin_broadcast_start")],
            [InlineKeyboardButton("🚫 بن / آن‌بن کاربر", callback_data="admin_ban_user_start")],
            [InlineKeyboardButton("🔴 بازگشت به منوی اصلی", callback_data="back_to_main")]
        ]
        await query.edit_message_text(admin_text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode="Markdown")
        return

    elif data == "admin_sales_report":
        if user_id != OWNER_ID: return
        conn = sqlite3.connect("bot_database.db")
        cursor = conn.cursor()
        cursor.execute("SELECT COUNT(*), SUM(price) FROM orders")
        orders_count, total_sales = cursor.fetchone()
        total_sales = total_sales if total_sales else 0

        cursor.execute("SELECT COUNT(*), SUM(balance) FROM users")
        users_count, total_balance = cursor.fetchone()
        total_balance = total_balance if total_balance else 0
        conn.close()

        report_text = (
            "📊 **گزارش کامل مالی و فروش**\n\n"
            f"👥 **تعداد کل کاربران ثبت‌شده:** `{users_count:,}` نفر\n"
            f"🛒 **تعداد کل خریدها:** `{orders_count:,}` عدد\n"
            f"💰 **مجموع درآمد کل:** `{total_sales:,}` تومان\n"
            f"💳 **مجموع موجودی کیف‌‌پول کاربران:** `{total_balance:,}` تومان\n"
        )
        keyboard = [[InlineKeyboardButton("🔙 بازگشت به پنل مدیریت", callback_data="admin_panel_menu")]]
        await query.edit_message_text(report_text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode="Markdown")
        return

    elif data == "admin_charge_user_start":
        if user_id != OWNER_ID: return
        context.user_data["adm_waiting_charge"] = True
        await query.edit_message_text(
            "➕ **افزایش / کاهش موجودی کاربر**\n\n"
            "لطفاً آیدی عددی کاربر و مبلغ را به تومان مانند الگوی زیر بفرستید:\n\n"
            "`USER_ID AMOUNT`\n\n"
            "مثال شارژ (مثبت): `6261657720 50000`\n"
            "مثال کسر (منفی): `6261657720 -20000`",
            parse_mode="Markdown"
        )
        return

    elif data == "admin_broadcast_start":
        if user_id != OWNER_ID: return
        context.user_data["adm_waiting_broadcast"] = True
        await query.edit_message_text(
            "📢 **ارسال پیام همگانی به تمام کاربران**\n\n"
            "لطفاً پیام خود را (متن یا تصویر به همراه متن) بفرستید تا برای همه ارسال شود:",
            parse_mode="Markdown"
        )
        return

    elif data == "admin_ban_user_start":
        if user_id != OWNER_ID: return
        context.user_data["adm_waiting_ban"] = True
        await query.edit_message_text(
            "🚫 **مدیریت مسدودی (Ban/Unban)**\n\n"
            "آیدی عددی کاربر را بفرستید تا وضعیت مسدودی او تغییر کند:",
            parse_mode="Markdown"
        )
        return

    # --- بخش تاییدیه‌های رسید ادمین ---
    if data.startswith("adm_ok_"):
        await query.answer("در حال پردازش...")
        receipt_id = int(data.split("_")[2])
        pending = get_pending_receipt(receipt_id)

        if not pending:
            await query.edit_message_caption(caption=f"{query.message.caption}\n\n❌ **خطا: اطلاعات رسید یافت نشد!**")
            return

        buyer_id, cfg_name, gb, price, r_type = pending

        if r_type == 'wallet_charge':
            update_user_balance(buyer_id, price)
            new_bal = get_user_balance(buyer_id)
            await query.edit_message_caption(caption=f"{query.message.caption}\n\n✅ **کیف پول کاربر به مبلغ {price:,} تومان شارژ شد.**")
            try:
                await context.bot.send_message(
                    chat_id=buyer_id,
                    text=f"🎉 **رسید واریزی شما تایید شد!**\n\n💳 مبلغ **{price:,} تومان** به کیف پول شما اضافه شد.\n💰 موجودی جدید: **{new_bal:,} تومان**"
                )
            except Exception:
                pass
            return

        res, err = await create_panel_user(cfg_name, gb)
        if res:
            sub_url = res.get("subscription_url", "")
            add_order(buyer_id, cfg_name, f"اشتراک {gb} گیگ", price, sub_url)

            user_msg = (
                f"🎉 **پرداخت شما تایید شد! کانفیگ شما آماده است.**\n\n"
                f"🏷️ نام کانفیگ: `{cfg_name}`\n"
                f"📊 حجم: **{gb} گیگابایت**\n"
                f"⏰ زمان انقضا: **نامحدود**\n\n"
                f"🌐 **لینک سابسکریپشن:**\n`{sub_url}`"
            )

            await query.edit_message_caption(caption=f"{query.message.caption}\n\n✅ **کانفیگ ساخته و برای کاربر ارسال شد.**")
            try:
                await context.bot.send_message(chat_id=buyer_id, text=user_msg, parse_mode="Markdown")
            except Exception:
                await query.edit_message_caption(caption=f"{query.message.caption}\n\n⚠️ **خطا در ارسال به کاربر!**\nلینک: `{sub_url}`")
        else:
            await query.edit_message_caption(caption=f"{query.message.caption}\n\n❌ **خطای پنل:**\n{err}")
        return

    elif data.startswith("adm_reject_"):
        await query.answer()
        receipt_id = int(data.split("_")[2])
        pending = get_pending_receipt(receipt_id)
        if pending:
            buyer_id = pending[0]
            try:
                await context.bot.send_message(chat_id=buyer_id, text="❌ رسید واریزی شما توسط مدیریت رد شد.")
            except Exception:
                pass
        await query.edit_message_caption(caption=f"{query.message.caption}\n\n❌ **رسید رد شد.**")
        return

    # --- سایر منوها ---
    elif data == "user_configs":
        await query.answer("در حال دریافت اطلاعات از سرور...")
        orders = get_user_orders(user_id)

        if not orders:
            await query.edit_message_text(
                "🛍️ **شما هنوز هیچ کانفیگی خریداری نکرده‌اید!**",
                reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🔴 بازگشت", callback_data="back_to_main")]])
            )
            return

        msg_text = "🛍️ **لیست کانفیگ‌های خریداری‌شده شما:**\n\n"

        for idx, order in enumerate(orders, 1):
            cfg_name, plan_name, sub_url, date_time = order
            p_info = await get_panel_user_info(cfg_name)

            if p_info:
                used_bytes = p_info.get("used_traffic", 0)
                limit_bytes = p_info.get("data_limit", 0)
                status = p_info.get("status", "")

                used_gb = round(used_bytes / (1024 ** 3), 2)
                limit_gb = round(limit_bytes / (1024 ** 3), 2) if limit_bytes else 0

                if used_bytes >= limit_bytes and limit_bytes > 0 or status == "expired":
                    badge = "❌ **(حجم تمام شده)**"
                else:
                    badge = "🟢 **(در حال استفاده / فعال)**"

                msg_text += (
                    f"{idx}. {badge}\n"
                    f"🏷️ **نام:** `{cfg_name}`\n"
                    f"📊 **مصرف شده:** {used_gb} GB از {limit_gb} GB\n"
                    f"🌐 **لینک سابسکریپشن:**\n`{sub_url}`\n"
                    f"───────────────────\n"
                )
            else:
                msg_text += (
                    f"{idx}. 🟢 **(فعال)**\n"
                    f"🏷️ **نام:** `{cfg_name}`\n"
                    f"🌐 **لینک سابسکریپشن:**\n`{sub_url}`\n"
                    f"───────────────────\n"
                )

        keyboard = [[InlineKeyboardButton("🔴 بازگشت به منوی اصلی", callback_data="back_to_main")]]
        await query.edit_message_text(msg_text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode="Markdown")

    elif data == "wallet_menu":
        await query.answer()
        bal = get_user_balance(user_id)
        text = (
            f"💰 **بخش کیف پول**\n\n"
            f"💵 **موجودی فعلی شما:** `{bal:,}` تومان\n\n"
            f"با شارژ کیف پول می‌توانید بدون نیاز به ارسال رسید، خرید‌های خود را آنی انجام دهید."
        )
        keyboard = [
            [InlineKeyboardButton("💳 شارژ کیف پول", callback_data="prompt_charge_amount")],
            [InlineKeyboardButton("🔴 بازگشت به منوی اصلی", callback_data="back_to_main")]
        ]
        await query.edit_message_text(text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode="Markdown")

    elif data == "prompt_charge_amount":
        await query.answer()
        context.user_data["waiting_for_charge_rial"] = True
        await query.edit_message_text(
            "🔴 **لطفاً مبلغ مورد نظر برای شارژ را به «ریال» وارد کنید:**\n\n"
            "مثال: برای شارژ ۳۰۰,۰۰۰ تومان، عدد `3000000` را بفرستید.\n"
            "⚠️ *حداقل مبلغ شارژ: ۳,۰۰۰,۰۰۰ ریال (۳۰۰,۰۰۰ تومان)*",
            parse_mode="Markdown"
        )

    elif data == "buy_custom_start":
        await query.answer()
        context.user_data["waiting_for_gb"] = True
        await query.edit_message_text(
            f"📊 **خرید اشتراک دلخواه**\n\n"
            f"💵 قیمت هر گیگابایت: **{PRICE_PER_GB:,} تومان**\n\n"
            f"👇 لطفاً **حجم مورد نظر خود را به گیگابایت** وارد کنید (فقط عدد):\n"
            f"⚠️ *حداقل حجم قابل سفارش: ۲ گیگابایت*",
            parse_mode="Markdown"
        )

    elif data == "pay_custom_wallet":
        await query.answer()
        gb = context.user_data.get("custom_gb")
        cfg_name = context.user_data.get("custom_name")
        price = context.user_data.get("custom_price")
        bal = get_user_balance(user_id)

        if not gb or not cfg_name or not price:
            await query.edit_message_text("❌ اطلاعات خرید یافت نشد.")
            return

        if bal < price:
            await query.edit_message_text(
                f"❌ **موجودی کیف پول شما کافی نیست!**\n\n"
                f"💰 موجودی شما: {bal:,} تومان\n"
                f"💵 مبلغ فاکتور: {price:,} تومان",
                reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("💰 منوی کیف پول", callback_data="wallet_menu")]])
            )
            return

        update_user_balance(user_id, -price)
        await query.edit_message_text("⏳ در حال ساخت کانفیگ و کسر از کیف پول...")

        res, err = await create_panel_user(cfg_name, gb)
        if res:
            sub_url = res.get("subscription_url", "")
            add_order(user_id, cfg_name, f"اشتراک دلخواه {gb} گیگ", price, sub_url)
            
            user_msg = (
                f"🎉 **خرید با موفقیت از کیف پول انجام شد!**\n\n"
                f"🏷️ نام کانفیگ: `{cfg_name}`\n"
                f"📊 حجم: **{gb} گیگابایت**\n"
                f"💵 مبلغ کسر شده: **{price:,} تومان**\n"
                f"💰 موجودی باقیمانده: **{get_user_balance(user_id):,} تومان**\n\n"
                f"🌐 **لینک سابسکریپشن:**\n`{sub_url}`"
            )
            await query.edit_message_text(user_msg, parse_mode="Markdown", reply_markup=main_menu_keyboard(user_id))
        else:
            update_user_balance(user_id, price)
            await query.edit_message_text(f"❌ خطایی در ساخت کانفیگ رخ داد و مبلغ به کیف پول برگشت داده شد.\nعلت: {err}")

    elif data == "tutorial_menu":
        await query.answer()
        text = (
            "🎓 **راهنمای اتصال و دانلود نرم‌افزارها**\n\n"
            "📱 **اندروید (Android):**\n"
            "برنامه پیشنهادی: **v2rayNG**\n\n"
            "🍏 **آیفون (iOS):**\n"
            "برنامه پیشنهادی: **V2Box**\n\n"
            "💻 **ویندوز و لینوکس:**\n"
            "لینک دانلود برنامه‌های مخصوص ویندوز و لینوکس درون صفحه اختصاصی لینک سابسکریپشن شما قرار دارد."
        )
        keyboard = [
            [InlineKeyboardButton("🤖 دانلود v2rayNG (اندروید)", url=V2RAY_ANDROID_LINK)],
            [InlineKeyboardButton("🍏 دانلود V2Box (آیفون)", url=V2BOX_IOS_LINK)],
            [InlineKeyboardButton("🔴 بازگشت", callback_data="back_to_main")]
        ]
        await query.edit_message_text(text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode="Markdown")

    elif data == "support_menu":
        await query.answer()
        text = (
            "📞 **پشتیبانی و ارتباط با ما**\n\n"
            f"👤 آیدی پشتیبانی: @{SUPPORT_USERNAME}\n"
            f"📢 کانال اطلاع‌رسانی: {CHANNEL_USERNAME}\n"
        )
        keyboard = [
            [InlineKeyboardButton("💬 پیام به پشتیبانی", url=f"https://t.me/{SUPPORT_USERNAME}")],
            [InlineKeyboardButton("❓ سوالات متداول (FAQ)", callback_data="faq_menu")],
            [InlineKeyboardButton("🔴 بازگشت به منوی اصلی", callback_data="back_to_main")]
        ]
        await query.edit_message_text(text, reply_markup=InlineKeyboardMarkup(keyboard))

    elif data == "faq_menu":
        await query.answer()
        text = (
            "❓ **سوالات متداول (FAQ)**\n\n"
            "❓ **آیا کانفیگ‌ها زمان نامحدود دارند؟**\n🔹 بله، تمام کانفیگ‌ها بدون محدودیت زمانی هستند.\n\n"
            "❓ **آیا قابلیت TUN فعال است؟**\n🔹 بله، قابلیت TUN کاملاً فعال و پشتیبانی می‌شود.\n\n"
            "❓ **آیا آی‌پی ثابت است؟**\n🔹 بله، تمامی سرویس‌ها دارای IP اختصاصی و ثابت هستند.\n\n"
            "❓ **آیا پشتیبانی پس از فروش دارید؟**\n🔹 بله، پشتیبانی برای بررسی و حل مشکلات شما فعال است.\n\n"
            "❓ **آیا امکان عودت کانفیگ وجود دارد؟**\n🔹 بله، در صورت عودت، حجم استفاده شده کسر شده و مابقی مبلغ به **کیف پول** شما اضافه خواهد شد."
        )
        keyboard = [[InlineKeyboardButton("🔙 بازگشت به پشتیبانی", callback_data="support_menu")]]
        await query.edit_message_text(text, reply_markup=InlineKeyboardMarkup(keyboard))

    elif data == "send_receipt_mode":
        await query.answer()
        context.user_data["waiting_for_receipt"] = True
        await query.edit_message_text("📸 لطفاً تصویر رسید واریزی خود را ارسال کنید:")

    elif data == "back_to_main":
        await query.answer()
        for k in ["waiting_for_gb", "waiting_for_name", "waiting_for_charge_rial", "waiting_for_receipt", "waiting_for_charge_receipt", "adm_waiting_charge", "adm_waiting_broadcast", "adm_waiting_ban"]:
            context.user_data.pop(k, None)
        await query.edit_message_text("🎯 منوی اصلی ربات:", reply_markup=main_menu_keyboard(user_id))

async def text_and_photo_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    if is_user_banned(user.id):
        return

    # ۱. فرآیند همگانی ادمین
    if user.id == OWNER_ID and context.user_data.get("adm_waiting_broadcast"):
        context.user_data["adm_waiting_broadcast"] = False
        user_ids = get_all_user_ids()
        success = 0
        failed = 0

        await update.message.reply_text(f"⏳ در حال ارسال پیام به `{len(user_ids)}` کاربر...", parse_mode="Markdown")

        for u_id in user_ids:
            try:
                if update.message.photo:
                    photo_id = update.message.photo[-1].file_id
                    caption = update.message.caption or ""
                    await context.bot.send_photo(chat_id=u_id, photo=photo_id, caption=caption)
                else:
                    await context.bot.send_message(chat_id=u_id, text=update.message.text)
                success += 1
                await asyncio.sleep(0.05)
            except Exception:
                failed += 1

        await update.message.reply_text(
            f"✅ **ارسال پیام همگانی به پایان رسید.**\n\n"
            f"🟢 موفق: `{success}`\n"
            f"🔴 ناموفق/بلاک‌شده: `{failed}`",
            parse_mode="Markdown"
        )
        return

    # ۲. فرآیند افزایش/کاهش موجودی توسط ادمین
    if user.id == OWNER_ID and context.user_data.get("adm_waiting_charge") and update.message.text:
        context.user_data["adm_waiting_charge"] = False
        try:
            parts = update.message.text.split()
            target_id = int(parts[0])
            amount = int(parts[1])

            update_user_balance(target_id, amount)
            new_bal = get_user_balance(target_id)

            await update.message.reply_text(
                f"✅ **عملیات با موفقیت انجام شد.**\n\n"
                f"👤 کاربر: `{target_id}`\n"
                f"💵 مبلغ تغییر یافته: `{amount:,}` تومان\n"
                f"💰 موجودی جدید: `{new_bal:,}` تومان",
                parse_mode="Markdown"
            )
            try:
                await context.bot.send_message(
                    chat_id=target_id,
                    text=f"🎁 **موجودی کیف پول شما به میزان {amount:,} تومان تغییر کرد!**\nموجودی جدید: {new_bal:,} تومان"
                )
            except Exception:
                pass
        except Exception as e:
            await update.message.reply_text(f"❌ ورودی نامعتبر بود. نمونه صحیح: `6261657720 50000`\nخطا: {e}")
        return

    # ۳. فرآیند مسدود کردن کاربر توسط ادمین
    if user.id == OWNER_ID and context.user_data.get("adm_waiting_ban") and update.message.text:
        context.user_data["adm_waiting_ban"] = False
        try:
            target_id = int(update.message.text.strip())
            current_status = is_user_banned(target_id)
            new_status = 0 if current_status else 1
            toggle_ban_user(target_id, new_status)

            status_text = "مسدود (Ban)" if new_status == 1 else "آزاد (Unban)"
            await update.message.reply_text(f"✅ وضعیت کاربر `{target_id}` به **{status_text}** تغییر یافت.", parse_mode="Markdown")
        except Exception:
            await update.message.reply_text("❌ لطفاً یک آیدی عددی معتبر بفرستید.")
        return

    # --- فرآیندهای کاربران عادی ---
    phone = get_user_phone(user.id)

    if context.user_data.get("waiting_for_gb") and update.message.text:
        text_val = update.message.text.strip()
        if not text_val.isdigit() or int(text_val) <= 1:
            await update.message.reply_text("❌ لطفاً حجم را به صورت عدد و **بزرگتر از ۱ گیگابایت** وارد کنید:")
            return

        gb = int(text_val)
        context.user_data["waiting_for_gb"] = False
        context.user_data["custom_gb"] = gb
        context.user_data["waiting_for_name"] = True

        await update.message.reply_text(
            f"✅ حجم انتخاب شده: **{gb} گیگابایت**\n\n"
            f"✏️ حالا **نام دلخواه برای کانفیگ** خود را وارد کنید:\n"
            f"⚠️ *تنها از حروف انگلیسی، اعداد و خط زیر (_) استفاده کنید*",
            parse_mode="Markdown"
        )
        return

    if context.user_data.get("waiting_for_name") and update.message.text:
        cfg_name = update.message.text.strip()
        if not re.match(r'^[a-zA-Z0-9_]+$', cfg_name):
            await update.message.reply_text("❌ نام کانفیگ نامعتبر است! لطفاً فقط از **حروف انگلیسی، اعداد و _** استفاده کنید:")
            return

        gb = context.user_data.get("custom_gb")
        price = gb * PRICE_PER_GB

        context.user_data["waiting_for_name"] = False
        context.user_data["custom_name"] = cfg_name
        context.user_data["custom_price"] = price

        text = (
            f"💳 **فاکتور خرید اشتراک دلخواه**\n\n"
            f"🏷️ نام کانفیگ: `{cfg_name}`\n"
            f"📊 حجم: **{gb} گیگابایت**\n"
            f"💵 مبلغ فاکتور: `{price:,}` تومان\n\n"
            f"💳 شماره کارت جهت کارت‌به‌کارت:\n`{CARD_NUMBER}`\n"
            f"👤 به نام: **{CARD_NAME}**\n\n"
            f"👇 روش پرداخت مورد نظر را انتخاب کنید:"
        )
        keyboard = [
            [InlineKeyboardButton("⚡ پرداخت سریع از کیف پول", callback_data="pay_custom_wallet")],
            [InlineKeyboardButton("📸 پرداخت کارت به کارت (ارسال رسید)", callback_data="send_receipt_mode")],
            [InlineKeyboardButton("🔴 انصراف", callback_data="back_to_main")]
        ]
        await update.message.reply_text(text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode="Markdown")
        return

    if context.user_data.get("waiting_for_charge_rial") and update.message.text:
        text_val = update.message.text.strip()
        if not text_val.isdigit():
            await update.message.reply_text("❌ لطفاً مبلغ را فقط به صورت عدد (به ریال) وارد کنید:")
            return

        amount_rial = int(text_val)
        amount_toman = amount_rial // 10

        if amount_toman < 300000:
            await update.message.reply_text("❌ حداقل مبلغ برای شارژ کیف پول ۳۰۰,۰۰۰ تومان (۳,۰۰۰,۰۰۰ ریال) است:")
            return

        context.user_data["waiting_for_charge_rial"] = False
        context.user_data["charge_amount_toman"] = amount_toman
        context.user_data["waiting_for_charge_receipt"] = True

        fact_text = (
            f"💳 **فاکتور شارژ کیف پول**\n\n"
            f"👤 کاربر: **{user.full_name}**\n"
            f"💵 مبلغ وارد شده: `{amount_rial:,}` ریال\n"
            f"💰 معادل تومان: **{amount_toman:,} تومان**\n\n"
            f"💳 شماره کارت جهت واریز:\n`{CARD_NUMBER}`\n"
            f"👤 به نام: **{CARD_NAME}**\n\n"
            f"📸 پس از واریز، عکس رسید را بفرستید."
        )
        await update.message.reply_text(fact_text, parse_mode="Markdown")
        return

    if update.message.photo:
        photo_id = update.message.photo[-1].file_id

        if context.user_data.get("waiting_for_charge_receipt"):
            amount_toman = context.user_data.get("charge_amount_toman")
            receipt_id = save_pending_receipt(user.id, "CHARGE_WALLET", 0, amount_toman, r_type='wallet_charge')

            keyboard = [[
                InlineKeyboardButton("🟢 تایید و شارژ کیف پول", callback_data=f"adm_ok_{receipt_id}"),
                InlineKeyboardButton("🔴 رد رسید", callback_data=f"adm_reject_{receipt_id}")
            ]]

            report_text = (
                f"💳 **درخواست شارژ کیف پول جدید!** (ID: {receipt_id})\n───────────────────\n"
                f"👤 کاربر: {user.full_name}\n"
                f"🆔 آیدی عددی: <code>{user.id}</code>\n"
                f"🔤 آیدی تلگرام: @{user.username if user.username else 'ندارد'}\n"
                f"📱 تلفن: <code>{phone}</code>\n"
                f"💰 مبلغ شارژ: **{amount_toman:,} تومان**"
            )
            try:
                await context.bot.send_photo(chat_id=GROUP_ID, photo=photo_id, caption=report_text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode="HTML")
                context.user_data["waiting_for_charge_receipt"] = False
                await update.message.reply_text("✅ رسید شارژ کیف پول ارسال شد.")
            except Exception as e:
                await update.message.reply_text(f"❌ خطا در ارسال رسید به گروه: {e}")
            return

        if context.user_data.get("waiting_for_receipt"):
            gb = context.user_data.get("custom_gb")
            cfg_name = context.user_data.get("custom_name")
            price = context.user_data.get("custom_price")

            if not gb or not cfg_name or not price:
                await update.message.reply_text("❌ خطایی رخ داد.")
                return

            receipt_id = save_pending_receipt(user.id, cfg_name, gb, price, r_type='buy_plan')

            keyboard = [[
                InlineKeyboardButton("🟢 تایید رسید و ساخت کانفیگ", callback_data=f"adm_ok_{receipt_id}"),
                InlineKeyboardButton("🔴 رد رسید", callback_data=f"adm_reject_{receipt_id}")
            ]]

            report_text = (
                f"💰 **رسید واریزی خرید کانفیگ!** (ID: {receipt_id})\n───────────────────\n"
                f"👤 کاربر: {user.full_name}\n"
                f"🆔 آیدی عددی: <code>{user.id}</code>\n"
                f"🔤 آیدی تلگرام: @{user.username if user.username else 'ندارد'}\n"
                f"📱 تلفن: <code>{phone}</code>\n"
                f"🏷️ کانفیگ: <code>{cfg_name}</code>\n"
                f"📊 حجم: {gb} گیگابایت ({price:,} تومان)"
            )
            try:
                await context.bot.send_photo(chat_id=GROUP_ID, photo=photo_id, caption=report_text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode="HTML")
                context.user_data["waiting_for_receipt"] = False
                await update.message.reply_text("✅ رسید شما ارسال شد.")
            except Exception as e:
                await update.message.reply_text(f"❌ خطا در ارسال رسید به گروه: {e}")

def main():
    application = Application.builder().token(BOT_TOKEN).build()
    
    application.add_handler(CommandHandler("start", start))
    application.add_handler(CommandHandler("charge", admin_charge_command))
    application.add_handler(CallbackQueryHandler(handle_callbacks))
    application.add_handler(MessageHandler(filters.CONTACT, contact_handler))
    application.add_handler(MessageHandler((filters.PHOTO | filters.TEXT) & filters.ChatType.PRIVATE, text_and_photo_handler))

    print("ربات آنلاین شد...")
    application.run_polling()

if __name__ == "__main__":
    main()
