# -*- coding: utf-8 -*-
"""
بات نماینده — کامل و حرفه‌ای
• مشتریان کیف پول مستقل در هر بات نمایندگی دارند
• شارژ از طریق کارت نماینده + تایید ادمین نماینده
• سفارش از موجودی مشتری کسر می‌شود
• هزینه تامین از موجودی نماینده در بات اصلی کسر می‌شود
• گرام و استارز دلخواه هم پشتیبانی می‌شود
• هیچ اشاره‌ای به بات اصلی وجود ندارد
"""

import logging
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ContextTypes
from telegram.constants import ParseMode

import database as db
from config import ADMIN_IDS

logger = logging.getLogger(__name__)

STATUS_FA = {"pending": "⏳ در انتظار", "done": "✅ تکمیل شده", "rejected": "❌ لغو شده"}
D = "─" * 30


def rid(ctx):  return ctx.application.bot_data.get("reseller_owner_id")
def adm(ctx):  return ctx.application.bot_data.get("reseller_admin_id")
def is_admin(uid, ctx): return uid == adm(ctx) or uid in ADMIN_IDS
def clr(ctx): ctx.user_data.pop("state", None); ctx.user_data.pop("temp", None)

def _s(ctx, key, default=""):
    v = db.get_reseller_setting(rid(ctx), key)
    return v if v else default

def bot_name(ctx):      return _s(ctx, "bot_name", "فروشگاه")
def card_number(ctx):   return _s(ctx, "card_number", "─── کارت ثبت نشده ───")
def card_holder(ctx):   return _s(ctx, "card_holder", "")
def welcome_text(ctx):
    c = _s(ctx, "welcome_text")
    return c if c else db.get_setting("welcome_text")
def support_text_msg(ctx):
    c = _s(ctx, "support_text")
    return c if c else "📬 پیام خود را ارسال کنید، در اسرع وقت پاسخ داده می‌شود."


# ══════════════════════════════════════
#  کیبوردها
# ══════════════════════════════════════

def main_menu(ctx):
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("🛍  سفارش خدمات",    callback_data="rm:order"),
         InlineKeyboardButton("👤  حساب کاربری",   callback_data="rm:account")],
        [InlineKeyboardButton("💳  افزایش موجودی", callback_data="rm:deposit"),
         InlineKeyboardButton("🔎  پیگیری سفارش",  callback_data="rm:track")],
        [InlineKeyboardButton("☎️  پشتیبانی",      callback_data="rm:support")],
    ])

def services_kb(ctx):
    t = db.get_setting
    return InlineKeyboardMarkup([
        [InlineKeyboardButton(t("btn_service_stars"),   callback_data="rs:stars"),
         InlineKeyboardButton(t("btn_service_premium"), callback_data="rs:premium")],
        [InlineKeyboardButton(t("btn_service_gift"),    callback_data="rs:gift"),
         InlineKeyboardButton("💎 خرید گرام",           callback_data="rs:gram")],
        [InlineKeyboardButton("↩️  بازگشت", callback_data="rm:back")],
    ])

def back(to="rm:back"):
    return InlineKeyboardMarkup([[InlineKeyboardButton("↩️  بازگشت", callback_data=to)]])

def admin_menu():
    return InlineKeyboardMarkup([
        [InlineKeyboardButton("📦  سفارشات در انتظار",    callback_data="ra:orders"),
         InlineKeyboardButton("🧾  رسیدهای در انتظار",   callback_data="ra:deposits")],
        [InlineKeyboardButton("💰  موجودی اعتباری",      callback_data="ra:balance"),
         InlineKeyboardButton("📊  آمار فروش",           callback_data="ra:stats")],
        [InlineKeyboardButton("🏆  لیدربورد",            callback_data="ra:leaderboard"),
         InlineKeyboardButton("💸  قیمت‌گذاری",         callback_data="ra:pricing")],
        [InlineKeyboardButton("🎟  کدهای تخفیف",        callback_data="ra:discounts"),
         InlineKeyboardButton("👥  مدیریت مشتریان",     callback_data="ra:customers")],
        [InlineKeyboardButton("⚙️  تنظیمات بات",        callback_data="ra:settings")],
    ])



# ══════════════════════════════════════
#  جوین اجباری
# ══════════════════════════════════════

async def check_force_join(update_or_query, ctx) -> bool:
    """True = عبور مجاز است، False = کاربر هنوز عضو نشده"""
    reseller_id = rid(ctx)
    channel = db.get_reseller_force_join(reseller_id)
    if not channel:
        return True
    uid = update_or_query.from_user.id
    try:
        member = await ctx.bot.get_chat_member(channel, uid)
        if member.status in ("member", "administrator", "creator"):
            return True
    except Exception:
        pass
    return False


async def send_force_join_message(update_or_query, ctx):
    channel = db.get_reseller_force_join(rid(ctx))
    kb2 = InlineKeyboardMarkup([[
        InlineKeyboardButton("📢  عضویت در کانال", url=f"https://t.me/{channel.lstrip('@')}"),
    ], [
        InlineKeyboardButton("✅  عضو شدم", callback_data="rm:check_join"),
    ]])
    text = f"⚠️  برای استفاده از بات ابتدا باید در کانال ما عضو شوید:\n📢  {channel}"
    if hasattr(update_or_query, "edit_message_text"):
        await update_or_query.edit_message_text(text, reply_markup=kb2)
    else:
        await update_or_query.message.reply_text(text, reply_markup=kb2)


# ══════════════════════════════════════
#  /start  و  /panel
# ══════════════════════════════════════

async def start(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    u = update.effective_user
    db.get_or_create_user(u.id, u.username or "", u.full_name or "")
    clr(ctx)

    ref = ctx.args[0] if ctx.args else None
    if ref and ref.isdigit():
        db.set_referrer(u.id, int(ref))

    if not await check_force_join(update, ctx):
        await send_force_join_message(update, ctx)
        return
    await update.message.reply_text(welcome_text(ctx), reply_markup=main_menu(ctx))


async def panel_command(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    if not is_admin(update.effective_user.id, ctx): return
    clr(ctx)
    await update.message.reply_text("🔧  پنل مدیریت", reply_markup=admin_menu())


async def panel_text(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    if not is_admin(update.effective_user.id, ctx): return
    clr(ctx)
    await update.message.reply_text("🔧  پنل مدیریت", reply_markup=admin_menu())


async def myid_command(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    u = update.effective_user
    await update.message.reply_text(
        f"🆔 آیدی عددی: `{u.id}`\n📛 یوزرنیم: @{u.username or '---'}",
        parse_mode=ParseMode.MARKDOWN,
    )


# ══════════════════════════════════════
#  Callback router
# ══════════════════════════════════════

async def cb(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    q = update.callback_query
    d = q.data
    uid = update.effective_user.id
    await q.answer()

    # ── منوی اصلی ──
    if   d == "rm:back":    clr(ctx); await q.edit_message_text(welcome_text(ctx), reply_markup=main_menu(ctx))
    elif d == "rm:order":   await q.edit_message_text("🛍  سرویس مورد نظر را انتخاب کنید:", reply_markup=services_kb(ctx))
    elif d == "rm:account": await show_account(q, uid, ctx)
    elif d == "rm:deposit": await start_deposit(q, ctx)
    elif d == "rm:track":   await show_tracking(q, uid, ctx)
    elif d == "rm:support": await start_support(q, ctx)
    elif d == "rm:check_join":
        if await check_force_join(q, ctx): await q.edit_message_text(welcome_text(ctx), reply_markup=main_menu(ctx))
        else: await send_force_join_message(q, ctx)

    # ── خدمات ──
    elif d.startswith("rs:"):
        cat = d.split(":")[1]
        if cat == "gram": await show_gram(q, ctx)
        else:             await show_products(q, ctx, cat)

    # ── سفارش ──
    elif d.startswith("ro:buy:"):    await select_product(q, ctx, int(d.split(":")[2]))
    elif d == "ro:self":             await self_recipient(q, ctx)
    elif d == "ro:confirm":          await confirm_order(q, ctx)
    elif d == "ro:cancel":           clr(ctx); await q.edit_message_text("سفارش لغو شد.", reply_markup=main_menu(ctx))
    elif d == "ro:custom_stars":     await ask_custom_stars(q, ctx)
    elif d == "ro:discount":         ctx.user_data["state"] = "awaiting_discount"; await q.edit_message_text("🎟  کد تخفیف را وارد کنید:", reply_markup=back("ro:skip_disc"))
    elif d == "ro:skip_disc":        ctx.user_data.pop("state", None); await show_order_summary(q, ctx)
    elif d == "gram:confirm":        await confirm_gram(q, ctx)
    elif d == "gram:cancel":         clr(ctx); await q.edit_message_text("سفارش لغو شد.", reply_markup=main_menu(ctx))

    # ── پنل ادمین ──
    elif d == "ra:back":             await q.edit_message_text("🔧  پنل مدیریت", reply_markup=admin_menu())
    elif d == "ra:orders":           await radmin_orders(q, ctx)
    elif d == "ra:deposits":         await radmin_deposits(q, ctx)
    elif d == "ra:balance":          await radmin_balance(q, ctx)
    elif d == "ra:stats":            await radmin_stats(q, ctx)
    elif d == "ra:leaderboard":      await radmin_leaderboard(q, ctx)
    elif d == "ra:pricing":          await radmin_pricing(q, ctx)
    elif d == "ra:discounts":        await radmin_discounts(q, ctx)
    elif d == "ra:customers":        await radmin_customers(q, ctx)
    elif d == "ra:settings":         await radmin_settings(q, ctx)
    elif d == "ra:add_discount":     ctx.user_data["state"] = "ra_disc_create"; await q.edit_message_text("➕  فرمت: کد,نوع,مقدار,تعداد\nمثال: SAVE10,percent,10,50", reply_markup=back("ra:discounts"))
    elif d == "ra:set_profit":       ctx.user_data["state"] = "ra_profit"; await q.edit_message_text("💸  درصد سود کلی را وارد کنید (مثلاً 15):", reply_markup=back("ra:pricing"))
    elif d == "ra:set_botname":      ctx.user_data["state"] = "ra_botname"; await q.edit_message_text("نام جدید بات را وارد کنید:", reply_markup=back("ra:settings"))
    elif d == "ra:set_card":         ctx.user_data["state"] = "ra_card"; await q.edit_message_text("شماره کارت جدید را وارد کنید:", reply_markup=back("ra:settings"))
    elif d == "ra:set_cardholder":   ctx.user_data["state"] = "ra_cardholder"; await q.edit_message_text("نام صاحب کارت را وارد کنید:", reply_markup=back("ra:settings"))
    elif d == "ra:set_welcome":      ctx.user_data["state"] = "ra_welcome"; await q.edit_message_text("متن خوش‌آمدگویی جدید را وارد کنید:", reply_markup=back("ra:settings"))
    elif d == "ra:set_support":      ctx.user_data["state"] = "ra_support_text"; await q.edit_message_text("متن بخش پشتیبانی را وارد کنید:", reply_markup=back("ra:settings"))
    elif d == "ra:set_force_join":    ctx.user_data["state"] = "ra_force_join"; await q.edit_message_text("یوزرنیم کانال جوین اجباری را وارد کنید (مثال: @mychannel)\nبرای غیرفعال کردن، عدد 0 ارسال کنید:", reply_markup=back("ra:settings"))
    elif d == "ra:toggle_force_join":
        cur = db.get_reseller_force_join(rid(ctx))
        if cur: db.set_reseller_force_join(rid(ctx), ""); await q.answer("جوین اجباری غیرفعال شد.", show_alert=True)
        else: await q.edit_message_text("یوزرنیم کانال را وارد کنید:", reply_markup=back("ra:settings")); ctx.user_data["state"] = "ra_force_join"; return
        await radmin_settings(q, ctx)

    elif d.startswith("ra:price:"):     await ask_product_price(q, ctx, int(d.split(":")[2]))
    elif d.startswith("ra:resetp:"):    db.clear_reseller_product_price(rid(ctx), int(d.split(":")[2])); await radmin_pricing(q, ctx)
    elif d.startswith("ra:dtoggle:"):   db.toggle_reseller_discount(rid(ctx), d.split(":")[1]); await radmin_discounts(q, ctx)
    elif d.startswith("ra:dep_ok:"):    await approve_deposit(q, ctx, int(d.split(":")[2]), None)
    elif d.startswith("ra:dep_no:"):    await reject_deposit(q, ctx, int(d.split(":")[2]))
    elif d.startswith("ra:dep_manual:"): ctx.user_data["state"] = "ra_dep_manual"; ctx.user_data["temp"] = {"dep_id": int(d.split(":")[2])}; await q.edit_message_text("مبلغ دستی تایید را وارد کنید (تومان):", reply_markup=back("ra:deposits"))
    elif d.startswith("ra:done:"):      await order_action(q, ctx, int(d.split(":")[2]), "done")
    elif d.startswith("ra:reject:"):    await order_action(q, ctx, int(d.split(":")[2]), "rejected")
    elif d.startswith("admin:order_done:") and is_admin(uid, ctx):   await order_action(q, ctx, int(d.split(":")[2]), "done")
    elif d.startswith("admin:order_reject:") and is_admin(uid, ctx): await order_action(q, ctx, int(d.split(":")[2]), "rejected")
    elif d.startswith("ra:user:"):      await show_customer_detail(q, ctx, int(d.split(":")[2]))
    elif d.startswith("ra:addbal:"):    ctx.user_data["state"] = "ra_addbal"; ctx.user_data["temp"] = {"cuid": int(d.split(":")[2])}; await q.edit_message_text("مبلغ افزایش موجودی مشتری (تومان):", reply_markup=back("ra:customers"))
    elif d.startswith("ra:subbal:"):    ctx.user_data["state"] = "ra_subbal"; ctx.user_data["temp"] = {"cuid": int(d.split(":")[2])}; await q.edit_message_text("مبلغ کاهش موجودی مشتری (تومان):", reply_markup=back("ra:customers"))


# ══════════════════════════════════════
#  حساب کاربری مشتری
# ══════════════════════════════════════

async def show_account(q, uid, ctx):
    reseller_id = rid(ctx)
    balance  = db.get_reseller_user_balance(reseller_id, uid)
    u        = db.get_or_create_user(uid, "", "")
    orders   = db.get_reseller_orders_by_user(reseller_id, uid, limit=5)
    done_cnt = sum(1 for o in orders if o["status"] == "done")
    total_sp = sum(o["price"] for o in orders if o["status"] == "done")
    await q.edit_message_text(
        f"👤  حساب کاربری\n{D}\n"
        f"🆔  آیدی: {uid}\n"
        f"📛  یوزرنیم: @{u['username'] or '---'}\n"
        f"💰  موجودی: {balance:,} تومان\n"
        f"📦  سفارشات انجام‌شده: {done_cnt}\n"
        f"💵  مجموع خرید: {total_sp:,} تومان\n"
        f"{D}",
        reply_markup=InlineKeyboardMarkup([
            [InlineKeyboardButton("💳  افزایش موجودی", callback_data="rm:deposit")],
            [InlineKeyboardButton("↩️  بازگشت", callback_data="rm:back")],
        ])
    )


# ══════════════════════════════════════
#  افزایش موجودی مشتری
# ══════════════════════════════════════

async def start_deposit(q, ctx):
    cn = card_number(ctx)
    ch = card_holder(ctx)
    if cn == "─── کارت ثبت نشده ───":
        await q.edit_message_text("⚠️  در حال حاضر امکان شارژ موجودی وجود ندارد.", reply_markup=back()); return
    ctx.user_data["state"] = "awaiting_deposit_amount"
    await q.edit_message_text(
        f"💳  افزایش موجودی\n{D}\n"
        f"مبلغ مورد نظر را (به تومان) وارد کنید:",
        reply_markup=back("rm:back")
    )


async def handle_deposit_amount(update, ctx, text):
    if not text.isdigit() or int(text) <= 0:
        await update.message.reply_text("⚠️  لطفاً یک عدد معتبر وارد کنید."); return
    amount = int(text)
    cn = card_number(ctx)
    ch = card_holder(ctx)
    ctx.user_data["temp"] = {"amount": amount}
    ctx.user_data["state"] = "awaiting_deposit_receipt"
    await update.message.reply_text(
        f"💳  افزایش موجودی\n{D}\n"
        f"💰  مبلغ: {amount:,} تومان\n\n"
        f"لطفاً این مبلغ را به شماره کارت زیر واریز کنید:\n\n"
        f"💳  `{cn}`\n"
        f"👤  {ch}\n\n"
        "پس از واریز، عکس رسید را ارسال کنید:",
        parse_mode=ParseMode.MARKDOWN,
        reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("❌  انصراف", callback_data="rm:back")]])
    )


async def handle_deposit_receipt(update, ctx):
    photo   = update.message.photo[-1]
    amount  = ctx.user_data["temp"]["amount"]
    user    = update.effective_user
    reseller_id = rid(ctx)

    dep_id = db.create_reseller_user_deposit(reseller_id, user.id, amount, photo.file_id, photo.file_unique_id)
    clr(ctx)

    await update.message.reply_text(
        f"✅  رسید شما با شماره #{dep_id} ثبت شد.\n"
        f"💰  مبلغ اعلامی: {amount:,} تومان\n\n"
        "پس از بررسی توسط پشتیبانی، موجودی به حساب شما افزوده می‌شود.",
        reply_markup=main_menu(ctx)
    )

    admin_id = adm(ctx)
    caption  = (
        f"🧾  رسید واریزی #{dep_id}\n"
        f"👤  {user.full_name} (@{user.username or '---'} | {user.id})\n"
        f"💰  مبلغ اعلامی: {amount:,} تومان"
    )
    dep_kb = InlineKeyboardMarkup([
        [InlineKeyboardButton("✅  تایید", callback_data=f"ra:dep_ok:{dep_id}"),
         InlineKeyboardButton("❌  رد",   callback_data=f"ra:dep_no:{dep_id}")],
        [InlineKeyboardButton("✏️  تایید با مبلغ دستی", callback_data=f"ra:dep_manual:{dep_id}")],
    ])
    if admin_id:
        try:
            await ctx.bot.send_photo(admin_id, photo.file_id, caption=caption, reply_markup=dep_kb)
        except Exception:
            pass


async def approve_deposit(q, ctx, dep_id, manual_amount):
    amount = db.approve_reseller_user_deposit(dep_id, manual_amount)
    if amount is False:
        await q.answer("قبلاً بررسی شده.", show_alert=True); return
    d = db.get_reseller_user_deposit(dep_id)
    try:
        await q.edit_message_caption(caption=f"✅  رسید #{dep_id} تایید شد. {amount:,} تومان افزوده شد.")
    except Exception:
        await q.edit_message_text(f"✅  رسید #{dep_id} تایید شد. {amount:,} تومان افزوده شد.")
    try:
        await ctx.bot.send_message(d["user_id"], f"✅  موجودی شما {amount:,} تومان افزایش یافت.")
    except Exception:
        pass


async def reject_deposit(q, ctx, dep_id):
    db.reject_reseller_user_deposit(dep_id)
    d = db.get_reseller_user_deposit(dep_id)
    try:
        await q.edit_message_caption(caption=f"❌  رسید #{dep_id} رد شد.")
    except Exception:
        await q.edit_message_text(f"❌  رسید #{dep_id} رد شد.")
    try:
        await ctx.bot.send_message(d["user_id"], "❌  رسید واریزی شما رد شد. در صورت نیاز با پشتیبانی تماس بگیرید.")
    except Exception:
        pass


# ══════════════════════════════════════
#  نمایش محصولات و سفارش
# ══════════════════════════════════════

async def show_products(q, ctx, category):
    clr(ctx)
    reseller_id = rid(ctx)
    products = db.get_products(active_only=True, category=category)
    label    = db.CATEGORY_LABELS.get(category, category)
    btns = []
    for p in products:
        price = db.get_reseller_price(reseller_id, p)
        btns.append([InlineKeyboardButton(f"{p['title']}  ─  {price:,} تومان", callback_data=f"ro:buy:{p['id']}")])
    if category == "stars":
        btns.append([InlineKeyboardButton("✏️  تعداد دلخواه استارز", callback_data="ro:custom_stars")])
    if not products:
        btns.append([InlineKeyboardButton("موجودی ندارد", callback_data="rm:order")])
    btns.append([InlineKeyboardButton("↩️  بازگشت", callback_data="rm:order")])
    await q.edit_message_text(f"✨  {label}\n\nپکیج مورد نظر را انتخاب کنید:", reply_markup=InlineKeyboardMarkup(btns))


async def select_product(q, ctx, product_id):
    reseller_id = rid(ctx)
    p = db.get_product(product_id)
    if not p or not p["is_active"]:
        await q.edit_message_text("⚠️  این محصول موجود نیست.", reply_markup=main_menu(ctx)); return

    price  = db.get_reseller_price(reseller_id, p)
    uid    = q.from_user.id
    u_bal  = db.get_reseller_user_balance(reseller_id, uid)
    r_bal  = db.get_user(reseller_id)["balance"] if db.get_user(reseller_id) else 0

    if u_bal < price:
        await q.edit_message_text(
            f"❌  موجودی کافی نیست.\n💰  موجودی شما: {u_bal:,} تومان\n🏷  قیمت: {price:,} تومان",
            reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("💳  شارژ موجودی", callback_data="rm:deposit"), InlineKeyboardButton("↩️", callback_data="rm:order")]])
        ); return

    ctx.user_data["state"] = "awaiting_recipient"
    ctx.user_data["temp"]  = {"product_id": product_id, "price": price, "orig_price": price}
    has_uname = bool(q.from_user.username)
    btns = []
    if has_uname: btns.append([InlineKeyboardButton("👤  برای خودم", callback_data="ro:self")])
    btns.append([InlineKeyboardButton("❌  انصراف", callback_data="rm:order")])
    await q.edit_message_text(
        f"📦  {p['title']}\n💰  {price:,} تومان\n\n"
        "آیدی (یوزرنیم) گیرنده را وارد کنید:\nمثال: @username",
        reply_markup=InlineKeyboardMarkup(btns)
    )


async def self_recipient(q, ctx):
    if not q.from_user.username:
        await q.answer("آیدی تلگرام ندارید. از تنظیمات تلگرام یوزرنیم تعریف کنید.", show_alert=True); return
    ctx.user_data["temp"]["recipient"] = f"@{q.from_user.username}"
    ctx.user_data.pop("state", None)
    await show_order_summary(q, ctx)


async def ask_custom_stars(q, ctx):
    reseller_id = rid(ctx)
    r = db.get_reseller(reseller_id) or {}
    # محاسبه قیمت هر استارز از ارزان‌ترین پکیج
    products = db.get_products(active_only=True, category="stars")
    pps = float(db.get_setting("stars_price_per_star") or "0")
    if pps <= 0 and products:
        p0  = products[0]
        bp  = db.get_reseller_price(reseller_id, p0)
        pps = bp / (p0["stars_amount"] or 1)

    ctx.user_data["state"] = "awaiting_custom_stars"
    ctx.user_data["temp"]  = {"pps": pps}
    await q.edit_message_text(
        f"⭐  سفارش تعداد دلخواه استارز\n{D}\n"
        f"💰  قیمت هر استارز: {pps:,.0f} تومان\n\n"
        "تعداد استارز مورد نظر را وارد کنید (حداقل ۱۵):",
        reply_markup=back("rm:order")
    )


async def show_order_summary(q, ctx):
    temp  = ctx.user_data.get("temp", {})
    p     = db.get_product(temp.get("product_id", 0)) if temp.get("product_id") else None
    title = temp.get("custom_title") or (p["title"] if p else "سفارش")
    price = temp.get("price", 0)
    rec   = temp.get("recipient", "")
    disc  = temp.get("disc_label", "")

    btns = []
    if not disc: btns.append([InlineKeyboardButton("🎟  دارم کد تخفیف", callback_data="ro:discount")])
    btns.append([InlineKeyboardButton("✅  تأیید سفارش", callback_data="ro:confirm"),
                 InlineKeyboardButton("❌  انصراف",      callback_data="ro:cancel")])
    await q.edit_message_text(
        f"📋  تأیید سفارش\n{D}\n"
        f"📦  {title}\n"
        f"📨  گیرنده: {rec}\n"
        f"💰  مبلغ: {price:,} تومان"
        + (f"\n🎟  تخفیف: {disc}" if disc else "") + f"\n{D}",
        reply_markup=InlineKeyboardMarkup(btns)
    )


async def confirm_order(q, ctx):
    temp = ctx.user_data.get("temp", {})
    product_id   = temp.get("product_id")
    custom_title = temp.get("custom_title")
    custom_stars = temp.get("custom_stars")
    rec   = temp.get("recipient")
    price = temp.get("price", 0)
    p = db.get_product(product_id) if product_id else None
    title     = custom_title or (p["title"] if p else "سفارش")
    stars_amt = custom_stars or (p["stars_amount"] if p else None)
    category  = (p["category"] if p else "stars")
    uid       = q.from_user.id
    reseller_id = rid(ctx)

    u_bal = db.get_reseller_user_balance(reseller_id, uid)
    r_bal = db.get_user(reseller_id)["balance"] if db.get_user(reseller_id) else 0

    # قیمت پایه (هزینه برای نماینده)
    if p:
        cost = db.get_effective_price(p)
    else:
        # استارز دلخواه — هزینه بر اساس قیمت پایه
        pps_base = float(db.get_setting("stars_price_per_star") or "0")
        products = db.get_products(active_only=True, category="stars")
        if pps_base <= 0 and products:
            p0 = products[0]
            pps_base = db.get_effective_price(p0) / (p0["stars_amount"] or 1)
        cost = int(pps_base * (stars_amt or 0))

    if u_bal < price:
        await q.edit_message_text("❌  موجودی کافی نیست.", reply_markup=main_menu(ctx)); clr(ctx); return
    if r_bal < cost:
        await q.edit_message_text("⏸  این خدمت موقتاً در دسترس نیست.", reply_markup=main_menu(ctx))
        try: await ctx.bot.send_message(reseller_id, f"⚠️  موجودی اعتباری برای انجام سفارش کافی نیست!\nنیاز: {cost:,} تومان | موجودی: {r_bal:,} تومان")
        except: pass
        clr(ctx); return

    db.update_reseller_user_balance(reseller_id, uid, -price)
    db.update_balance(reseller_id, -cost)
    db.add_reseller_sale(reseller_id, price)

    disc_code = temp.get("disc_code")
    if disc_code: db.use_reseller_discount(reseller_id, disc_code)

    order_id = db.create_order(uid, title, cost, rec, category=category, stars_amount=stars_amt, reseller_id=reseller_id)
    clr(ctx)

    await q.edit_message_text(
        f"✅  سفارش با موفقیت ثبت شد!\n{D}\n"
        f"🔖  شماره پیگیری: #{order_id}\n"
        f"📦  {title}\n"
        f"📨  گیرنده: {rec}\n"
        f"💰  مبلغ پرداختی: {price:,} تومان\n{D}\n"
        "🚀  سفارش در صف پردازش قرار گرفت.",
        reply_markup=main_menu(ctx)
    )
    # ارسال سفارش به ادمین اصلی از طریق بات اصلی (نه بات نماینده)
    master_bot = ctx.application.bot_data.get("master_bot") or ctx.bot
    for aid in ADMIN_IDS:
        try:
            await master_bot.send_message(
                aid,
                f"🆕  سفارش از نماینده #{order_id}\n🏪  نماینده: @{db.get_reseller(reseller_id)['bot_username'] if db.get_reseller(reseller_id) else reseller_id}\n"
                f"👤  مشتری: {uid}\n{title} | {cost:,}T | {rec}",
                reply_markup=InlineKeyboardMarkup([[
                    InlineKeyboardButton("✅  انجام شد", callback_data=f"admin:order_done:{order_id}"),
                    InlineKeyboardButton("❌  رد",       callback_data=f"admin:order_reject:{order_id}"),
                ]])
            )
        except Exception as e:
            pass


# ══════════════════════════════════════
#  گرام در نماینده
# ══════════════════════════════════════

async def show_gram(q, ctx):
    clr(ctx)
    try:
        gram_usd = await db.fetch_gram_price_usd()
    except Exception:
        gram_usd = 0
    rate     = db.get_setting("usdt_rate") or "0"
    if gram_usd <= 0 or float(rate) <= 0:
        await q.edit_message_text("⚠️  قیمت گرام در دسترس نیست. کمی بعد امتحان کنید.", reply_markup=main_menu(ctx)); return

    reseller_id = rid(ctx)
    r = db.get_reseller(reseller_id) or {}
    # قیمت پایه + سود نماینده
    base_price  = db.calc_gram_price_toman(gram_usd, 1)
    profit_pct  = r.get("profit_percent", 0)
    final_price = int(base_price * (1 + profit_pct / 100))
    min_order   = db.get_setting("gram_min_order") or "0.1"
    desc        = db.get_setting("gram_description") or ""

    ctx.user_data["state"] = "awaiting_gram_amount"
    ctx.user_data["temp"]  = {"gram_usd": gram_usd, "gram_price": final_price}
    await q.edit_message_text(
        f"💎  خرید گرام (GRAM)\n{D}\n"
        f"{desc}\n\n"
        f"💰  قیمت هر گرام: {final_price:,} تومان\n"
        f"❗️  حداقل سفارش: {min_order} GRAM\n{D}\n\n"
        "⬅️  مقدار GRAM مورد نظر را وارد کنید:\nمثال: 1 یا 2.5",
        reply_markup=back("rm:order")
    )


async def confirm_gram(q, ctx):
    temp   = ctx.user_data.get("temp", {})
    amount = temp.get("gram_amount")
    price  = temp.get("price")
    wallet = temp.get("wallet")
    uid    = q.from_user.id
    reseller_id = rid(ctx)

    u_bal = db.get_reseller_user_balance(reseller_id, uid)
    r_obj = db.get_user(reseller_id)
    r_bal = r_obj["balance"] if r_obj else 0
    cost  = db.calc_gram_price_toman(temp.get("gram_usd", 0), amount)

    if u_bal < price:
        await q.edit_message_text("❌  موجودی کافی نیست.", reply_markup=main_menu(ctx)); clr(ctx); return
    if r_bal < cost:
        await q.edit_message_text("⏸  این خدمت موقتاً در دسترس نیست.", reply_markup=main_menu(ctx)); clr(ctx); return

    db.update_reseller_user_balance(reseller_id, uid, -price)
    db.update_balance(reseller_id, -cost)
    db.add_reseller_sale(reseller_id, price)
    title    = f"💎 {amount} گرام"
    order_id = db.create_order(uid, title, cost, wallet, category="gram", reseller_id=reseller_id)
    clr(ctx)

    await q.edit_message_text(
        f"✅  سفارش گرام ثبت شد!\n{D}\n"
        f"🔖  #{order_id}\n💎  {amount} گرام\n📬  {wallet}\n{D}\n"
        "🚀  در صف پردازش قرار گرفت.",
        reply_markup=main_menu(ctx)
    )
    master_bot = ctx.application.bot_data.get("master_bot") or ctx.bot
    for aid in ADMIN_IDS:
        try:
            await master_bot.send_message(aid, f"💎  گرام از نماینده #{order_id}\n🏪  {reseller_id}\n{amount} GRAM | {cost:,}T\n📬  {wallet}",
                reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("✅  انجام شد", callback_data=f"admin:order_done:{order_id}"), InlineKeyboardButton("❌  رد", callback_data=f"admin:order_reject:{order_id}")]]))
        except Exception: pass


# ══════════════════════════════════════
#  پیگیری / پشتیبانی
# ══════════════════════════════════════

async def show_tracking(q, uid, ctx):
    reseller_id = rid(ctx)
    orders = db.get_reseller_orders_by_user(reseller_id, uid)
    deps   = db.get_reseller_user_deposits(reseller_id, uid, 5)
    if not orders and not deps:
        await q.edit_message_text("📭  تاریخچه‌ای یافت نشد.", reply_markup=main_menu(ctx)); return
    lines = [f"🔎  تاریخچه شما\n{D}"]
    if orders:
        lines.append("📦  سفارشات:")
        for o in orders: lines.append(f"  #{o['id']} {o['title']} | {STATUS_FA.get(o['status'])}")
    if deps:
        lines.append(f"\n🧾  واریزی‌ها:")
        for d in deps: lines.append(f"  #{d['id']} {d['amount']:,}T | {STATUS_FA.get(d['status'])}")
    await q.edit_message_text("\n".join(lines), reply_markup=main_menu(ctx))


async def start_support(q, ctx):
    ctx.user_data["state"] = "awaiting_support"
    await q.edit_message_text(f"☎️  {support_text_msg(ctx)}", reply_markup=back("rm:back"))


# ══════════════════════════════════════
#  پنل ادمین — توابع
# ══════════════════════════════════════

async def radmin_orders(q, ctx):
    reseller_id = rid(ctx)
    with db.get_conn() as conn:
        rows = conn.execute("SELECT * FROM orders WHERE reseller_id=? AND status='pending' ORDER BY id", (reseller_id,)).fetchall()
    if not rows:
        await q.edit_message_text("📭  سفارش در انتظاری ندارید.", reply_markup=back("ra:back")); return
    await q.edit_message_text(f"📦  {len(rows)} سفارش در انتظار:", reply_markup=back("ra:back"))
    for o in rows:
        await ctx.bot.send_message(q.from_user.id,
            f"#{o['id']}  {o['title']}\n👤  {o['user_id']}  📨  {o['recipient_username']}",
            reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("✅  انجام شد", callback_data=f"ra:done:{o['id']}"),
                InlineKeyboardButton("❌  رد",       callback_data=f"ra:reject:{o['id']}"),
            ]]))


async def radmin_deposits(q, ctx):
    reseller_id = rid(ctx)
    deps = db.get_pending_reseller_user_deposits(reseller_id)
    if not deps:
        await q.edit_message_text("📭  رسید در انتظاری ندارید.", reply_markup=back("ra:back")); return
    await q.edit_message_text(f"🧾  {len(deps)} رسید در انتظار:", reply_markup=back("ra:back"))
    for d in deps:
        cap = f"رسید #{d['id']}\n👤  {d['user_id']}\n💰  {d['amount']:,} تومان"
        kb2 = InlineKeyboardMarkup([[
            InlineKeyboardButton("✅  تایید",         callback_data=f"ra:dep_ok:{d['id']}"),
            InlineKeyboardButton("❌  رد",            callback_data=f"ra:dep_no:{d['id']}"),
            InlineKeyboardButton("✏️  مبلغ دستی",    callback_data=f"ra:dep_manual:{d['id']}"),
        ]])
        try:    await ctx.bot.send_photo(q.from_user.id, d["receipt_file_id"], caption=cap, reply_markup=kb2)
        except: await ctx.bot.send_message(q.from_user.id, cap, reply_markup=kb2)


async def order_action(q, ctx, order_id, status):
    o = db.get_order(order_id)
    if not o or o["status"] != "pending":
        await q.edit_message_text("این سفارش قبلاً بررسی شده است."); return
    if status == "rejected":
        # برگشت هزینه به نماینده
        db.update_balance(rid(ctx), o["price"])
        # برگشت مبلغ به مشتری
        db.update_reseller_user_balance(rid(ctx), o["user_id"], o["price"])
    db.update_order_status(order_id, status)
    await q.edit_message_text(f"سفارش #{order_id}: {STATUS_FA[status]} ✅")
    try: await ctx.bot.send_message(o["user_id"], f"🔔  سفارش #{order_id} شما {STATUS_FA[status]}.")
    except: pass


async def radmin_balance(q, ctx):
    reseller_id = rid(ctx)
    r = db.get_user(reseller_id)
    bal = r["balance"] if r else 0
    await q.edit_message_text(
        f"💰  موجودی اعتباری شما در سیستم:\n\n  {bal:,} تومان\n\n"
        "این موجودی برای تامین سفارشات مشتریان استفاده می‌شود.\n"
        "برای شارژ از طریق بات اصلی اقدام کنید.",
        reply_markup=back("ra:back")
    )


async def radmin_stats(q, ctx):
    reseller_id = rid(ctx)
    r = db.get_reseller(reseller_id) or {}
    u = db.get_user(reseller_id) or {"balance": 0}
    with db.get_conn() as conn:
        total = conn.execute("SELECT COUNT(*) AS c FROM orders WHERE reseller_id=?", (reseller_id,)).fetchone()["c"]
        done  = conn.execute("SELECT COUNT(*) AS c FROM orders WHERE reseller_id=? AND status='done'", (reseller_id,)).fetchone()["c"]
        rev   = conn.execute("SELECT SUM(price) AS s FROM orders WHERE reseller_id=? AND status='done'", (reseller_id,)).fetchone()["s"] or 0
        custs = conn.execute("SELECT COUNT(DISTINCT user_id) AS c FROM reseller_balances WHERE reseller_id=?", (reseller_id,)).fetchone()["c"]
    await q.edit_message_text(
        f"📊  آمار فروش\n{D}\n"
        f"👥  تعداد مشتریان: {custs}\n"
        f"📦  کل سفارشات:   {total}\n"
        f"✅  انجام‌شده:    {done}\n"
        f"💵  حجم فروش:    {rev:,} تومان\n"
        f"💸  سود تنظیم‌شده: {r.get('profit_percent', 0)}٪\n"
        f"💰  موجودی اعتباری: {u['balance']:,} تومان",
        reply_markup=back("ra:back")
    )


async def radmin_leaderboard(q, ctx):
    board  = db.get_leaderboard(10)
    medals = ["🥇","🥈","🥉","4️⃣","5️⃣","6️⃣","7️⃣","8️⃣","9️⃣","🔟"]
    if not board:
        await q.edit_message_text("هنوز داده‌ای نیست.", reply_markup=back("ra:back")); return
    lines = [f"🏆  لیدربورد نمایندگان\n{D}"]
    for i, r in enumerate(board):
        m = medals[i] if i < len(medals) else f"{i+1}."
        lines.append(f"{m}  @{r['bot_username']}  ─  {r['total_sales']:,}T  ({r['order_count']} سفارش)")
    await q.edit_message_text("\n".join(lines), reply_markup=back("ra:back"))


async def radmin_pricing(q, ctx):
    reseller_id = rid(ctx)
    r = db.get_reseller(reseller_id) or {}
    profit = r.get("profit_percent", 0)
    products = db.get_products(active_only=False)
    btns = [[InlineKeyboardButton(f"💸  سود کلی: {profit}٪  ← تغییر", callback_data="ra:set_profit")]]
    for p in products:
        price = db.get_reseller_price(reseller_id, p)
        btns.append([
            InlineKeyboardButton(f"{p['title']}: {price:,}T", callback_data=f"ra:price:{p['id']}"),
            InlineKeyboardButton("↩️ ریست", callback_data=f"ra:resetp:{p['id']}"),
        ])
    btns.append([InlineKeyboardButton("↩️  بازگشت", callback_data="ra:back")])
    await q.edit_message_text(
        f"💸  قیمت‌گذاری\n{D}\nسود کلی {profit}٪ روی قیمت پایه اعمال می‌شود.\nبرای قیمت اختصاصی روی محصول بزنید:",
        reply_markup=InlineKeyboardMarkup(btns)
    )


async def ask_product_price(q, ctx, product_id):
    p = db.get_product(product_id)
    if not p: return
    ctx.user_data["state"] = "ra_product_price"
    ctx.user_data["temp"]  = {"product_id": product_id}
    base = db.get_effective_price(p)
    await q.edit_message_text(
        f"📦  {p['title']}\nقیمت پایه: {base:,} تومان\n\nقیمت اختصاصی خود را وارد کنید:",
        reply_markup=back("ra:pricing")
    )


async def radmin_discounts(q, ctx):
    reseller_id = rid(ctx)
    codes = db.list_reseller_discounts(reseller_id)
    btns  = []
    for c in codes:
        st = "🟢" if c["is_active"] else "🔴"
        vt = "%" if c["type"] == "percent" else "T"
        us = f"{c['used_count']}/{c['max_uses']}" if c["max_uses"] else f"{c['used_count']}/∞"
        btns.append([InlineKeyboardButton(f"{st}  {c['code']}  ({c['value']}{vt})  {us}", callback_data=f"ra:dtoggle:{c['code']}")])
    btns.append([InlineKeyboardButton("➕  کد جدید", callback_data="ra:add_discount"),
                 InlineKeyboardButton("↩️  بازگشت",  callback_data="ra:back")])
    await q.edit_message_text("🎟  کدهای تخفیف اختصاصی:", reply_markup=InlineKeyboardMarkup(btns))


async def radmin_customers(q, ctx):
    reseller_id = rid(ctx)
    with db.get_conn() as conn:
        rows = conn.execute(
            "SELECT rb.user_id, rb.balance, u.username, u.full_name "
            "FROM reseller_balances rb LEFT JOIN users u ON u.user_id=rb.user_id "
            "WHERE rb.reseller_id=? ORDER BY rb.balance DESC LIMIT 20",
            (reseller_id,)
        ).fetchall()
    if not rows:
        await q.edit_message_text("👥  هنوز مشتری ثبت‌نامی ندارید.", reply_markup=back("ra:back")); return
    btns = []
    for r in rows:
        uname = r["username"] or str(r["user_id"])
        btns.append([InlineKeyboardButton(f"@{uname}  ─  {r['balance']:,}T", callback_data=f"ra:user:{r['user_id']}")])
    btns.append([InlineKeyboardButton("↩️  بازگشت", callback_data="ra:back")])
    await q.edit_message_text("👥  مشتریان (مرتب بر اساس موجودی):", reply_markup=InlineKeyboardMarkup(btns))


async def show_customer_detail(q, ctx, cuid):
    reseller_id = rid(ctx)
    u   = db.get_user(cuid)
    bal = db.get_reseller_user_balance(reseller_id, cuid)
    orders = db.get_reseller_orders_by_user(reseller_id, cuid, 3)
    done_cnt = sum(1 for o in orders if o["status"] == "done")
    tot_sp   = sum(o["price"] for o in orders if o["status"] == "done")
    await q.edit_message_text(
        f"👤  مشتری\n{D}\n"
        f"🆔  {cuid}\n"
        f"📛  @{u['username'] if u else '---'}\n"
        f"💰  موجودی: {bal:,} تومان\n"
        f"📦  سفارشات انجام‌شده: {done_cnt}\n"
        f"💵  مجموع خرید: {tot_sp:,} تومان",
        reply_markup=InlineKeyboardMarkup([
            [InlineKeyboardButton("➕  افزایش موجودی", callback_data=f"ra:addbal:{cuid}"),
             InlineKeyboardButton("➖  کاهش موجودی",  callback_data=f"ra:subbal:{cuid}")],
            [InlineKeyboardButton("↩️  بازگشت", callback_data="ra:customers")],
        ])
    )


async def radmin_settings(q, ctx):
    reseller_id = rid(ctx)
    name = db.get_reseller_setting(reseller_id, "bot_name") or "─"
    card = db.get_reseller_setting(reseller_id, "card_number") or "─"
    await q.edit_message_text(
        f"⚙️  تنظیمات بات\n{D}\nنام بات: {name}\nشماره کارت: {card}",
        reply_markup=InlineKeyboardMarkup([
            [InlineKeyboardButton("✏️  نام بات",         callback_data="ra:set_botname"),
             InlineKeyboardButton("💳  شماره کارت",     callback_data="ra:set_card")],
            [InlineKeyboardButton("👤  نام صاحب کارت",  callback_data="ra:set_cardholder")],
            [InlineKeyboardButton("📝  متن خوش‌آمدگویی", callback_data="ra:set_welcome"),
             InlineKeyboardButton("☎️  متن پشتیبانی",  callback_data="ra:set_support")],
            [InlineKeyboardButton("📢  تنظیم جوین اجباری", callback_data="ra:set_force_join"),
             InlineKeyboardButton("🔄  روشن/خاموش جوین",   callback_data="ra:toggle_force_join")],
            [InlineKeyboardButton("↩️  بازگشت", callback_data="ra:back")],
        ])
    )


# ══════════════════════════════════════
#  روتر متن / عکس
# ══════════════════════════════════════

async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    u    = update.effective_user
    db.get_or_create_user(u.id, u.username or "", u.full_name or "")
    text  = update.message.text.strip() if update.message.text else ""
    state = ctx.user_data.get("state")

    if text.lower() == "panel": await panel_text(update, ctx); return

    # ── ادمین ──
    if is_admin(u.id, ctx):
        if state == "ra_profit":
            if not text.replace(".", "").isdigit(): await update.message.reply_text("⚠️  فقط عدد."); return
            db.set_reseller_profit(rid(ctx), float(text)); clr(ctx)
            await update.message.reply_text(f"✅  سود کلی {text}٪ ذخیره شد.", reply_markup=admin_menu()); return
        if state == "ra_product_price":
            if not text.isdigit(): await update.message.reply_text("⚠️  فقط عدد."); return
            pid = ctx.user_data.get("temp", {}).get("product_id")
            db.set_reseller_product_price(rid(ctx), pid, int(text)); clr(ctx)
            await update.message.reply_text("✅  قیمت ذخیره شد.", reply_markup=admin_menu()); return
        if state == "ra_disc_create":
            parts = [p.strip() for p in text.split(",")]
            if len(parts) < 3: await update.message.reply_text("فرمت اشتباه."); return
            code = parts[0].upper(); dtype = parts[1] if parts[1] in ("percent","fixed") else "percent"
            try: value = int(parts[2])
            except: await update.message.reply_text("مقدار باید عدد باشد."); return
            max_u = int(parts[3]) if len(parts) > 3 and parts[3] else None
            db.create_reseller_discount(rid(ctx), code, dtype, value, max_u); clr(ctx)
            await update.message.reply_text(f"✅  کد «{code}» ساخته شد.", reply_markup=admin_menu()); return
        if state == "ra_force_join":
            val = "" if text.strip() == "0" else text.strip()
            db.set_reseller_force_join(rid(ctx), val); clr(ctx)
            msg = "✅  جوین اجباری غیرفعال شد." if not val else f"✅  جوین اجباری برای {val} فعال شد."
            await update.message.reply_text(msg, reply_markup=admin_menu()); return
        for k, setting_key in [("ra_botname","bot_name"),("ra_card","card_number"),("ra_cardholder","card_holder"),("ra_welcome","welcome_text"),("ra_support_text","support_text")]:
            if state == k:
                db.set_reseller_setting(rid(ctx), setting_key, text); clr(ctx)
                await update.message.reply_text("✅  ذخیره شد.", reply_markup=admin_menu()); return
        if state == "ra_dep_manual":
            if not text.isdigit(): await update.message.reply_text("⚠️  فقط عدد."); return
            dep_id = ctx.user_data.get("temp", {}).get("dep_id")
            amount = db.approve_reseller_user_deposit(dep_id, int(text)); clr(ctx)
            await update.message.reply_text(f"✅  رسید تایید شد. {amount:,} تومان افزوده شد.", reply_markup=admin_menu())
            d = db.get_reseller_user_deposit(dep_id)
            try: await ctx.bot.send_message(d["user_id"], f"✅  موجودی شما {amount:,} تومان افزایش یافت.")
            except: pass
            return
        if state in ("ra_addbal","ra_subbal"):
            if not text.isdigit(): await update.message.reply_text("⚠️  فقط عدد."); return
            cuid = ctx.user_data.get("temp", {}).get("cuid")
            delta = int(text) if state == "ra_addbal" else -int(text)
            db.update_reseller_user_balance(rid(ctx), cuid, delta); clr(ctx)
            await update.message.reply_text("✅  موجودی مشتری به‌روزرسانی شد.", reply_markup=admin_menu()); return

    # ── مشتری ──
    if state == "awaiting_deposit_amount":
        await handle_deposit_amount(update, ctx, text); return
    if state == "awaiting_recipient":
        rec = text if text.startswith("@") else "@"+text
        ctx.user_data["temp"]["recipient"] = rec
        ctx.user_data.pop("state", None)
        p     = db.get_product(ctx.user_data["temp"].get("product_id",0))
        title = ctx.user_data["temp"].get("custom_title") or (p["title"] if p else "")
        price = ctx.user_data["temp"].get("price",0)
        btns  = [[InlineKeyboardButton("🎟  کد تخفیف دارم", callback_data="ro:discount")],
                 [InlineKeyboardButton("✅  تأیید", callback_data="ro:confirm"), InlineKeyboardButton("❌  انصراف", callback_data="ro:cancel")]]
        await update.message.reply_text(
            f"📋  تأیید سفارش\n{D}\n📦  {title}\n📨  {rec}\n💰  {price:,} تومان",
            reply_markup=InlineKeyboardMarkup(btns)); return
    if state == "awaiting_custom_stars":
        if not text.strip().isdigit() or int(text.strip()) < 15:
            await update.message.reply_text("⚠️  حداقل ۱۵ استارز. عدد صحیح وارد کنید."); return
        amt   = int(text.strip())
        pps   = ctx.user_data["temp"].get("pps", 0)
        price = int(amt * pps)
        reseller_id = rid(ctx)
        u_bal = db.get_reseller_user_balance(reseller_id, u.id)
        if u_bal < price:
            await update.message.reply_text(f"❌  موجودی کافی نیست. {price:,} تومان نیاز است.", reply_markup=main_menu(ctx)); clr(ctx); return
        ctx.user_data["temp"].update({"custom_stars": amt, "custom_title": f"⭐ {amt} استارز (دلخواه)", "price": price, "orig_price": price})
        ctx.user_data["state"] = "awaiting_recipient"
        has_uname = bool(u.username)
        btns = []
        if has_uname: btns.append([InlineKeyboardButton("👤  برای خودم", callback_data="ro:self")])
        btns.append([InlineKeyboardButton("❌  انصراف", callback_data="rm:order")])
        await update.message.reply_text(
            f"⭐  {amt} استارز — {price:,} تومان\n\nآیدی گیرنده را وارد کنید:",
            reply_markup=InlineKeyboardMarkup(btns)); return
    if state == "awaiting_gram_amount":
        text2 = text.replace(",","").strip()
        try: amount = float(text2); assert amount > 0
        except: await update.message.reply_text("⚠️  عدد معتبر وارد کنید."); return
        try: min_o = float(db.get_setting("gram_min_order") or "0.1")
        except: min_o = 0.1
        if amount < min_o: await update.message.reply_text(f"⚠️  حداقل {min_o} گرام."); return
        gram_usd  = ctx.user_data["temp"].get("gram_usd", 0)
        reseller_id = rid(ctx)
        r = db.get_reseller(reseller_id) or {}
        base_price  = db.calc_gram_price_toman(gram_usd, amount)
        profit_pct  = r.get("profit_percent", 0)
        price       = int(base_price * (1 + profit_pct / 100))
        u_bal       = db.get_reseller_user_balance(reseller_id, u.id)
        if u_bal < price:
            await update.message.reply_text(f"❌  موجودی کافی نیست.\n💎  {amount} گرام = {price:,} تومان\n💰  موجودی: {u_bal:,} تومان", reply_markup=main_menu(ctx)); clr(ctx); return
        ctx.user_data["temp"].update({"gram_amount": amount, "price": price})
        ctx.user_data["state"] = "awaiting_gram_wallet"
        await update.message.reply_text(
            f"✅  {amount} گرام — {price:,} تومان\n\n📬  آدرس ولت گرام را وارد کنید:\nاگه کامنت دارد: آدرس | کامنت",
            reply_markup=back("rm:order")); return
    if state == "awaiting_gram_wallet":
        ctx.user_data["temp"]["wallet"] = text; ctx.user_data.pop("state", None)
        temp = ctx.user_data["temp"]
        await update.message.reply_text(
            f"📋  تأیید گرام\n{D}\n💎  {temp['gram_amount']} گرام\n💰  {temp['price']:,} تومان\n📬  {text}",
            reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("✅  تأیید", callback_data="gram:confirm"), InlineKeyboardButton("❌  انصراف", callback_data="gram:cancel")]])); return
    if state == "awaiting_discount":
        code_row = db.validate_reseller_discount(rid(ctx), text)
        if not code_row: await update.message.reply_text("❌  این کد معتبر نیست."); return
        orig  = ctx.user_data["temp"]["orig_price"]
        price = db.apply_discount(orig, code_row)
        ctx.user_data["temp"].update({"price": price, "disc_code": text.upper(), "disc_label": f"{code_row['value']}{'٪' if code_row['type']=='percent' else 'T'}"})
        ctx.user_data.pop("state", None)
        await update.message.reply_text(f"✅  تخفیف اعمال شد! قیمت جدید: {price:,} تومان")
        # نمایش خلاصه بدون callback_query (پیام ارسالی)
        temp  = ctx.user_data["temp"]
        p     = db.get_product(temp.get("product_id",0))
        title = temp.get("custom_title") or (p["title"] if p else "")
        await update.message.reply_text(
            f"📋  تأیید سفارش\n{D}\n📦  {title}\n📨  {temp['recipient']}\n💰  {price:,} تومان\n🎟  تخفیف: {temp['disc_label']}",
            reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("✅  تأیید", callback_data="ro:confirm"), InlineKeyboardButton("❌  انصراف", callback_data="ro:cancel")]])); return
    if state == "awaiting_support":
        clr(ctx)
        await update.message.reply_text("✅  پیام شما ارسال شد.", reply_markup=main_menu(ctx))
        admin_id = adm(ctx)
        if admin_id:
            try: await ctx.bot.send_message(admin_id, f"☎️  پشتیبانی:\n{u.full_name} ({u.id})\n\n{text}")
            except: pass
        return

    await update.message.reply_text("از منوی زیر انتخاب کنید 👇", reply_markup=main_menu(ctx))


async def handle_photo(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
    if ctx.user_data.get("state") == "awaiting_deposit_receipt":
        await handle_deposit_receipt(update, ctx)
    else:
        await update.message.reply_text("اگه رسید واریزی است، ابتدا «💳 افزایش موجودی» را بزنید.", reply_markup=main_menu(ctx))
