# -*- coding: utf-8 -*-
"""
هندلرهای مربوط به کاربر عادی (مشتری)
"""

import re

from telegram import Update
from telegram.ext import ContextTypes
from telegram.constants import ParseMode

import database as db
import keyboards as kb
from notifications import notify_admins
from config import ADMIN_IDS, SUPPORT_USERNAME, MIN_DEPOSIT_AMOUNT, MAX_DEPOSIT_AMOUNT, MIN_TRANSFER_AMOUNT

STATUS_LABELS = {
    "pending": "⏳ در انتظار بررسی",
    "done": "✅ انجام شد",
    "rejected": "❌ رد شده",
}

USERNAME_PATTERN = re.compile(r"^@?[A-Za-z][A-Za-z0-9_]{4,31}$")

RECIPIENT_PROMPTS = {
    "stars": "لطفاً آیدی (یوزرنیم) حساب گیرنده استارز رو به همراه @ ارسال کن.",
    "premium": "لطفاً آیدی (یوزرنیم) حسابی که می‌خوای پریمیومش فعال شه رو به همراه @ ارسال کن.",
    "gift": "لطفاً آیدی (یوزرنیم) حساب گیرنده گیفت رو به همراه @ ارسال کن.",
}


def is_admin(user_id: int) -> bool:
    return user_id in ADMIN_IDS


def clear_state(context: ContextTypes.DEFAULT_TYPE):
    context.user_data.pop("state", None)
    context.user_data.pop("temp", None)


def normalize_username(text: str) -> str:
    text = text.strip()
    if not text.startswith("@"):
        text = "@" + text
    return text


def is_valid_username(text: str) -> bool:
    return bool(USERNAME_PATTERN.match(text.strip()))


# ---------------- /start و /myid ----------------

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


# ---------------- /start ----------------

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    db.get_or_create_user(user.id, user.username or "", user.full_name or "")
    clear_state(context)

    if context.args:
        arg = context.args[0]
        if arg.startswith("ref_") and arg[4:].isdigit():
            db.set_referrer(user.id, int(arg[4:]))

    text = db.get_setting("welcome_text")
    await update.message.reply_text(text, reply_markup=kb.main_menu())


# ---------------- Callback Query Router ----------------

async def handle_user_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    data = query.data
    user = update.effective_user
    db_user = db.get_or_create_user(user.id, user.username or "", user.full_name or "")

    if db_user["is_blocked"]:
        await query.answer("⛔️ دسترسی شما به بات مسدود شده است.", show_alert=True)
        return

    if db_user["kyc_required_pending"] and not db_user["kyc_verified"]:
        await query.answer(
            "🪪 لطفاً ابتدا عکس کارت بانکی خود را برای احراز هویت ارسال کنید.", show_alert=True
        )
        return

    await query.answer()

    if data == "menu:back":
        clear_state(context)
        db.clear_activity_flow(user.id)
        await query.edit_message_text("منوی اصلی 👇", reply_markup=kb.main_menu())

    elif data == "menu:order":
        await show_services_menu(query, context)

    elif data.startswith("service:"):
        category = data.split(":")[1]
        if category == "ton":
            await show_gram_service(query, context)
        else:
            await show_products(query, context, category)

    elif data == "order:custom_stars":
        await start_custom_stars(query, context)

    elif data == "order:self":
        await handle_self_recipient(query, context)

    elif data == "menu:account":
        await show_account(query, context, db_user)

    elif data == "menu:deposit":
        await start_deposit(query, context)

    elif data == "menu:transfer":
        await start_transfer(query, context)

    elif data == "menu:rules":
        text = db.get_setting("rules_text")
        await query.edit_message_text(text, reply_markup=kb.back_to_menu())

    elif data == "menu:tracking":
        await show_tracking_menu(query, context)

    elif data == "menu:support":
        await start_support(query, context)

    elif data == "menu:reseller":
        await show_reseller_info(query, context)
    elif data == "reseller:signup":
        await start_reseller_signup(query, context)

    elif data.startswith("order:buy:"):
        product_id = int(data.split(":")[2])
        await select_product(query, context, product_id)

    elif data == "order:has_code":
        await ask_discount_code(query, context)
    elif data == "order:no_code":
        await show_order_confirmation(query, context)

    elif data == "order:confirm":
        await confirm_order(query, context)
    elif data == "order:cancel":
        await cancel_order(query, context)

    elif data == "transfer:confirm":
        await confirm_transfer(query, context)
    elif data == "transfer:cancel":
        await cancel_transfer(query, context)

    elif data == "gram:confirm":
        await confirm_gram_order(query, context)
    elif data == "gram:cancel":
        clear_state(context)
        await query.edit_message_text("سفارش لغو شد.", reply_markup=kb.main_menu())

    elif data == "rules:accept":
        db.set_rules_accepted(user.id)
        await ask_deposit_amount(query, context, note="✅ شما قوانین را تایید کردید.")
    elif data == "rules:read":
        text = db.get_setting("rules_text")
        await query.edit_message_text(text, reply_markup=kb.rules_read_back_kb())
    elif data == "rules:back":
        await show_deposit_rules_gate(query, context)

    elif data == "tracking:orders":
        await show_order_tracking(query, user.id)
    elif data == "tracking:deposits":
        await show_deposit_tracking(query, user.id)

    elif data.startswith("rate:"):
        _, order_id_str, rating_str = data.split(":")
        await handle_rating(query, context, int(order_id_str), int(rating_str))


# ---------------- سفارش خدمات ----------------

async def show_services_menu(query, context):
    clear_state(context)
    await query.edit_message_text(
        "🛍 سرویس مورد نظر خود را انتخاب کنید:\n\n"
        "🚀 تمامی سفارشات در سریع‌ترین زمان ممکن و کاملاً مطمئن انجام خواهند شد.",
        reply_markup=kb.services_menu_kb(),
    )


async def show_products(query, context, category):
    clear_state(context)
    products = db.get_products(active_only=True, category=category)
    label = db.CATEGORY_LABELS.get(category, category)
    text = f"{label}\n\nیکی از پکیج‌های زیر رو انتخاب کن 👇"
    if not products:
        text = f"{label}\n\nدر حال حاضر هیچ محصولی در این بخش ثبت نشده. بعداً دوباره سر بزن."
    await query.edit_message_text(text, reply_markup=kb.products_keyboard(products))


# ---------------- گرام ----------------

async def show_gram_service(query, context):
    clear_state(context)
    try:
        gram_usd = await db.fetch_gram_price_usd()
    except Exception:
        gram_usd = 0

    rate       = db.get_setting("usdt_rate") or "0"
    profit     = db.get_setting("gram_profit_percent") or "0"
    min_order  = db.get_setting("gram_min_order") or "0.1"
    description = db.get_setting("gram_description") or ""

    if gram_usd <= 0 or float(rate) <= 0:
        await query.edit_message_text(
            "💎 خرید گرام (GRAM)\n\n"
            "⚠️ در حال حاضر قیمت گرام در دسترس نیست.\n"
            "لطفاً کمی بعد دوباره امتحان کنید.",
            reply_markup=kb.cancel_kb("menu:order"),
        )
        return

    gram_price_toman = db.calc_gram_price_toman(gram_usd, 1)
    context.user_data["state"] = "awaiting_gram_amount"
    context.user_data["temp"]  = {"gram_usd": gram_usd, "gram_price_toman": gram_price_toman}

    await query.edit_message_text(
        f"💎 خرید گرام (GRAM)\n\n"
        f"{description}\n\n"
        f"{'─'*30}\n"
        f"💰 قیمت هر گرام: {gram_price_toman:,} تومان\n"
        f"❗️ حداقل سفارش: {min_order} GRAM\n"
        f"{'─'*30}\n\n"
        "⬅️ مقدار GRAM مورد نظر رو وارد کن:\n\n"
        "ℹ️ (می‌توانید اعشار هم وارد کنید؛ مثال: 1 یا 2.5)",
        reply_markup=kb.cancel_kb("menu:order"),
    )


async def handle_gram_amount(update, context, text):
    text = text.replace(",", "").strip()
    try:
        amount = float(text)
        if amount <= 0:
            raise ValueError
    except ValueError:
        await update.message.reply_text("⚠️ لطفاً یک عدد معتبر وارد کن. مثال: 5 یا 2.5")
        return

    try:
        min_order = float(db.get_setting("gram_min_order") or "0.1")
    except Exception:
        min_order = 0.1

    if amount < min_order:
        await update.message.reply_text(
            f"⚠️ حداقل مقدار سفارش {min_order} گرام است."
        )
        return

    gram_usd = context.user_data["temp"].get("gram_usd", 0)
    price    = db.calc_gram_price_toman(gram_usd, amount)
    if price <= 0:
        await update.message.reply_text("خطا در محاسبه قیمت. لطفاً دوباره تلاش کن.")
        return

    user    = update.effective_user
    db_user = db.get_user(user.id)
    if db_user["balance"] < price:
        await update.message.reply_text(
            f"❌ موجودی کافی نیست.\n"
            f"💎 {amount} گرام = {price:,} تومان\n"
            f"💰 موجودی شما: {db_user['balance']:,} تومان",
            reply_markup=kb.main_menu(),
        )
        clear_state(context)
        return

    context.user_data["temp"]["gram_amount"] = amount
    context.user_data["temp"]["price"]       = price
    context.user_data["state"] = "awaiting_gram_wallet"

    gram_price_one = context.user_data["temp"].get("gram_price_toman", 0)
    await update.message.reply_text(
        f"✅ قیمت محاسبه شد:\n\n"
        f"💎 مقدار: {amount} گرام\n"
        f"💰 مبلغ کل: {price:,} تومان\n"
        f"📊 نرخ هر گرام: {gram_price_one:,} تومان\n\n"
        "📬 آدرس ولت گرام (TON) گیرنده را وارد کنید.\n"
        "اگه کامنت نیاز داشت اینجوری بنویس:\n"
        "آدرس_ولت | کامنت\nمثال: UQBt...xyz | 123456",
        reply_markup=kb.cancel_kb("menu:order"),
    )


async def handle_gram_wallet(update, context, text):
    temp   = context.user_data.get("temp", {})
    amount = temp.get("gram_amount")
    price  = temp.get("price")
    context.user_data["temp"]["wallet"] = text
    context.user_data.pop("state", None)
    await update.message.reply_text(
        f"📋 تایید سفارش گرام\n"
        f"{'─'*30}\n"
        f"💎 مقدار: {amount} گرام\n"
        f"💰 مبلغ: {price:,} تومان\n"
        f"📬 ولت: {text}\n"
        f"{'─'*30}\n\nآیا اطلاعات بالا صحیح است؟",
        reply_markup=kb.confirm_kb("gram:confirm", "gram:cancel"),
    )


async def confirm_gram_order(query, context):
    temp   = context.user_data.get("temp", {})
    amount = temp.get("gram_amount")
    price  = temp.get("price")
    wallet = temp.get("wallet")
    user   = query.from_user

    db_user = db.get_user(user.id)
    if db_user["balance"] < price:
        await query.edit_message_text("❌ موجودی کافی نیست.", reply_markup=kb.main_menu())
        clear_state(context)
        return

    db.update_balance(user.id, -price)
    title    = f"💎 {amount} گرام"
    order_id = db.create_order(user.id, title, price, wallet, category="gram")
    clear_state(context)

    await query.edit_message_text(
        f"✅ سفارش با موفقیت ثبت شد!\n"
        f"{'─'*30}\n"
        f"🔖 شماره پیگیری: #{order_id}\n"
        f"💎 {amount} گرام\n"
        f"💰 {price:,} تومان\n"
        f"📬 {wallet}\n"
        f"{'─'*30}\n🚀 در صف پردازش قرار گرفت.",
        reply_markup=kb.main_menu(),
    )
    admin_text = (
        f"💎 سفارش گرام #{order_id}\n"
        f"👤 {user.full_name} (@{user.username or '---'} | {user.id})\n"
        f"مقدار: {amount} گرام | {price:,} تومان\n📬 {wallet}"
    )
    await notify_admins(context, text=admin_text, reply_markup=kb.order_admin_kb(order_id), order_notification=True)


# ---------------- تعداد دلخواه استارز ----------------

async def start_custom_stars(query, context):
    price_per_star = float(db.get_setting("stars_price_per_star") or "0")
    if price_per_star <= 0:
        products = db.get_products(active_only=True, category="stars")
        if products:
            p = products[0]
            price_per_star = db.get_effective_price(p) / (p["stars_amount"] or 1)

    context.user_data["state"] = "awaiting_custom_stars_amount"
    context.user_data["temp"] = {"price_per_star": price_per_star}

    per_star_text = f"قیمت هر استارز: {price_per_star:,.0f} تومان" if price_per_star > 0 else "قیمت از پکیج‌های موجود محاسبه می‌شود"
    await query.edit_message_text(
        f"⭐ سفارش تعداد دلخواه استارز\n\n"
        f"💰 {per_star_text}\n\n"
        "تعداد استارز مورد نظرت رو وارد کن (حداقل ۱۵):",
        reply_markup=kb.cancel_kb("menu:order"),
    )


async def handle_custom_stars_amount(update, context, text):
    if not text.strip().isdigit() or int(text.strip()) < 15:
        await update.message.reply_text("حداقل ۱۵ استارز می‌تونی سفارش بدی. لطفاً عدد صحیح وارد کن.")
        return

    amount = int(text.strip())
    price_per_star = context.user_data["temp"].get("price_per_star", 0)

    if price_per_star <= 0:
        await update.message.reply_text(
            "قیمت‌گذاری استارز دلخواه هنوز تنظیم نشده. لطفاً از پکیج‌های آماده استفاده کن.",
            reply_markup=kb.main_menu(),
        )
        clear_state(context)
        return

    price = int(amount * price_per_star)
    user = update.effective_user
    db_user = db.get_user(user.id)

    if db_user["balance"] < price:
        await update.message.reply_text(
            f"موجودی کافی نیست.\n"
            f"⭐ {amount} استارز: {price:,} تومان\n"
            f"کیف پول شما: {db_user['balance']:,} تومان",
            reply_markup=kb.main_menu(),
        )
        clear_state(context)
        return

    context.user_data["temp"]["custom_stars_amount"] = amount
    context.user_data["temp"]["price"] = price
    context.user_data["state"] = "awaiting_order_recipient"
    context.user_data["temp"]["custom_title"] = f"⭐ {amount} استارز (سفارش آزاد)"
    has_username = bool(user.username)
    await update.message.reply_text(
        f"⭐ {amount} استارز — {price:,} تومان\n\n"
        "آیدی (یوزرنیم) گیرنده استارز رو وارد کن:",
        reply_markup=kb.recipient_kb(has_username),
    )


# ---------------- دکمه «خودم» ----------------

async def handle_self_recipient(query, context):
    user = query.from_user
    if not user.username:
        await query.answer(
            "شما آیدی (یوزرنیم) تلگرام ندارید!\n"
            "برای ست کردن آیدی: تنظیمات تلگرام ← ویرایش پروفایل ← یوزرنیم",
            show_alert=True,
        )
        return
    # شبیه‌سازی ارسال متن برای ادامه فلو
    recipient = f"@{user.username}"
    context.user_data["temp"]["recipient"] = recipient
    temp = context.user_data.get("temp", {})
    product_id = temp.get("product_id")
    custom_title = temp.get("custom_title")

    if custom_title:
        price = temp.get("price", 0)
        title = custom_title
        stars = temp.get("custom_stars_amount")
    else:
        product = db.get_product(product_id)
        price = db.get_effective_price(product) if product else temp.get("price", 0)
        title = product["title"] if product else "سفارش"
        stars = product["stars_amount"] if product else None

    context.user_data.pop("state", None)
    await query.edit_message_text(
        f"📋 تایید سفارش:\n\n{title}\n💰 {price:,} تومان\n📨 گیرنده: {recipient}\n\nتایید می‌کنی؟",
        reply_markup=kb.confirm_kb("order:confirm", "order:cancel"),
    )


async def select_product(query, context, product_id):
    product = db.get_product(product_id)
    if not product or not product["is_active"]:
        await query.edit_message_text("این محصول دیگر در دسترس نیست.", reply_markup=kb.back_to_menu())
        return

    user_id = query.from_user.id
    db_user = db.get_user(user_id)
    price = db.get_effective_price(product)
    if db_user["balance"] < price:
        text = (
            f"{product['title']} — {price:,} تومان\n\n"
            f"💰 موجودی فعلی شما: {db_user['balance']:,} تومان\n"
            "موجودی کافی نیست. لطفاً ابتدا از بخش «افزایش موجودی» کیف پولت رو شارژ کن."
        )
        await query.edit_message_text(text, reply_markup=kb.back_to_menu())
        return

    context.user_data["state"] = "awaiting_order_recipient"
    context.user_data["temp"] = {"product_id": product_id, "price": price}
    db.set_activity_flow(user_id, "order")
    prompt = RECIPIENT_PROMPTS.get(product["category"], RECIPIENT_PROMPTS["stars"])
    has_username = bool(query.from_user.username)
    await query.edit_message_text(
        f"{product['title']} — {price:,} تومان\n\n"
        f"{prompt}\n"
        "مثال: @username",
        reply_markup=kb.recipient_kb(has_username),
    )


async def handle_order_recipient_input(update, context, text):
    recipient = normalize_username(text)
    if not is_valid_username(recipient):
        await update.message.reply_text(
            "❌ یوزرنیم وارد شده معتبر نیست. لطفاً به این شکل ارسال کن: @username"
        )
        return

    context.user_data["temp"]["recipient"] = recipient
    product_id = context.user_data["temp"]["product_id"]
    product = db.get_product(product_id)

    if not product or not product["is_active"]:
        await update.message.reply_text("این محصول دیگر در دسترس نیست.", reply_markup=kb.main_menu())
        clear_state(context)
        return

    context.user_data.pop("state", None)  # state کنار گذاشته می‌شود، منتظر تایید با دکمه هستیم
    price = context.user_data["temp"]["price"]
    text_out = (
        f"{product['title']}\n"
        f"💰 قیمت: {price:,} تومان\n"
        f"📨 گیرنده: {recipient}\n\n"
        "آیا کد تخفیف داری؟"
    )
    await update.message.reply_text(text_out, reply_markup=kb.discount_prompt_kb())


async def ask_discount_code(query, context):
    context.user_data["state"] = "awaiting_discount_code"
    await query.edit_message_text("🎟 کد تخفیف رو ارسال کن:", reply_markup=kb.cancel_kb("order:no_code"))


async def handle_discount_code_input(update, context, text):
    code_row = db.validate_discount_code(text.strip())
    if not code_row:
        await update.message.reply_text(
            "❌ این کد تخفیف معتبر نیست یا منقضی شده.",
            reply_markup=kb.cancel_kb("order:no_code"),
        )
        return

    price = context.user_data["temp"]["price"]
    discounted = db.apply_discount(price, code_row)
    context.user_data["temp"]["discount_code"] = code_row["code"]
    context.user_data["temp"]["final_price"] = discounted
    context.user_data.pop("state", None)

    await update.message.reply_text(f"✅ کد تخفیف اعمال شد! قیمت جدید: {discounted:,} تومان")
    await show_order_confirmation_message(update.message, context)


async def show_order_confirmation(query, context):
    price = context.user_data["temp"].get("final_price", context.user_data["temp"]["price"])
    product = db.get_product(context.user_data["temp"]["product_id"])
    recipient = context.user_data["temp"]["recipient"]
    text_out = (
        "📋 لطفاً سفارش زیر رو بررسی کن:\n\n"
        f"{product['title']}\n"
        f"💰 قیمت نهایی: {price:,} تومان\n"
        f"📨 گیرنده: {recipient}\n\n"
        "در صورت تایید، روی دکمه «✅ تایید» بزن."
    )
    await query.edit_message_text(text_out, reply_markup=kb.confirm_kb("order:confirm", "order:cancel"))


async def show_order_confirmation_message(message, context):
    price = context.user_data["temp"].get("final_price", context.user_data["temp"]["price"])
    product = db.get_product(context.user_data["temp"]["product_id"])
    recipient = context.user_data["temp"]["recipient"]
    text_out = (
        "📋 لطفاً سفارش زیر رو بررسی کن:\n\n"
        f"{product['title']}\n"
        f"💰 قیمت نهایی: {price:,} تومان\n"
        f"📨 گیرنده: {recipient}\n\n"
        "در صورت تایید، روی دکمه «✅ تایید» بزن."
    )
    await message.reply_text(text_out, reply_markup=kb.confirm_kb("order:confirm", "order:cancel"))


async def confirm_order(query, context):
    temp = context.user_data.get("temp", {})
    product_id = temp.get("product_id")
    recipient = temp.get("recipient")
    discount_code = temp.get("discount_code")
    price = temp.get("final_price", temp.get("price"))
    user = query.from_user

    product = db.get_product(product_id) if product_id else None
    if not product or not product["is_active"] or not recipient or price is None:
        await query.edit_message_text("این سفارش دیگر معتبر نیست. لطفاً دوباره از منو اقدام کن.", reply_markup=kb.main_menu())
        clear_state(context)
        db.clear_activity_flow(user.id)
        return

    db_user = db.get_user(user.id)
    if db_user["balance"] < price:
        await query.edit_message_text(
            "موجودی کافی نیست، سفارش ثبت نشد. لطفاً ابتدا کیف پولت رو شارژ کن.",
            reply_markup=kb.main_menu(),
        )
        clear_state(context)
        db.clear_activity_flow(user.id)
        return

    db.update_balance(user.id, -price)
    reseller_id = context.application.bot_data.get("reseller_owner_id") if hasattr(context, "application") else None
    order_id = db.create_order(
        user.id, product["title"], price, recipient,
        category=product["category"], stars_amount=product["stars_amount"],
        reseller_id=reseller_id,
    )
    if discount_code:
        db.increment_discount_usage(discount_code)

    if db_user["referred_by"]:
        bonus = db.calc_referral_bonus(price)
        if bonus > 0:
            db.add_referral_earning(db_user["referred_by"], bonus)
            try:
                await context.bot.send_message(
                    db_user["referred_by"],
                    f"🎉 یکی از زیرمجموعه‌های شما خرید کرد و {bonus:,} تومان به کیف پولت اضافه شد!",
                )
            except Exception:
                pass

    clear_state(context)
    db.clear_activity_flow(user.id)

    await query.edit_message_text(
        f"✅ سفارش شما با شماره #{order_id} با موفقیت ثبت شد.\n"
        f"{product['title']}\n"
        f"👤 گیرنده: {recipient}\n\n"
        "سفارش شما به زودی توسط ادمین انجام می‌شود. وضعیت سفارش رو می‌توانی از «پیگیری سفارشات» ببینی.",
        reply_markup=kb.main_menu(),
    )

    reseller_label = f"\n🏪 از بات نماینده: {reseller_id}" if reseller_id else ""
    admin_text = (
        f"🆕 سفارش جدید #{order_id}{reseller_label}\n"
        f"👤 از طرف: {user.full_name} (@{user.username or '---'} | {user.id})\n"
        f"{product['title']}\n"
        f"💰 قیمت: {price:,} تومان"
        + (f" (با کد {discount_code})" if discount_code else "") + "\n"
        f"📨 گیرنده: {recipient}"
    )
    # سفارشات همیشه به ادمین اصلی می‌رن (order_notification=True)
    await notify_admins(context, text=admin_text, reply_markup=kb.order_admin_kb(order_id), order_notification=True)


async def cancel_order(query, context):
    db.clear_activity_flow(query.from_user.id)
    clear_state(context)
    await query.edit_message_text("سفارش لغو شد.", reply_markup=kb.main_menu())


# ---------------- حساب کاربری ----------------

async def show_account(query, context, db_user):
    order_count = db.get_user_order_count(db_user["user_id"])
    total_spent = db.get_user_total_spent(db_user["user_id"])
    ref_count = db.get_referral_count(db_user["user_id"])
    ref_link = f"https://t.me/{context.bot.username}?start=ref_{db_user['user_id']}"
    text = (
        "👤 حساب کاربری شما\n\n"
        f"🆔 آیدی عددی: {db_user['user_id']}\n"
        f"📛 یوزرنیم: @{db_user['username'] or '---'}\n"
        f"💰 موجودی کیف پول: {db_user['balance']:,} تومان\n"
        f"🛍 تعداد سفارشات: {order_count} بار\n"
        f"💵 مجموع خرید از بات: {total_spent:,} تومان\n"
        f"📅 تاریخ عضویت: {db_user['joined_at']}\n\n"
        f"🔗 لینک زیرمجموعه‌گیری شما:\n{ref_link}\n"
        f"👥 تعداد زیرمجموعه: {ref_count} نفر\n"
        f"💸 درآمد از زیرمجموعه: {db_user['referral_earnings']:,} تومان"
    )
    await query.edit_message_text(text, reply_markup=kb.back_to_menu())


# ---------------- افزایش موجودی ----------------

async def start_deposit(query, context):
    db_user = db.get_user(query.from_user.id)
    if not db_user["rules_accepted"]:
        await show_deposit_rules_gate(query, context)
        return
    await ask_deposit_amount(query, context)


async def show_deposit_rules_gate(query, context):
    clear_state(context)
    text = db.get_setting("deposit_warning_text")
    await query.edit_message_text(text, reply_markup=kb.rules_gate_kb())


async def ask_deposit_amount(query, context, note=""):
    context.user_data["state"] = "awaiting_deposit_amount"
    context.user_data["temp"] = {}
    db.set_activity_flow(query.from_user.id, "deposit")
    prefix = f"{note}\n\n" if note else ""
    await query.edit_message_text(
        prefix +
        "💰 لطفاً مبلغی که می‌خوای به کیف پولت اضافه کنی رو به تومان و فقط با عدد ارسال کن.\n"
        f"(حداقل {MIN_DEPOSIT_AMOUNT:,} و حداکثر {MAX_DEPOSIT_AMOUNT:,} تومان)\n"
        "مثال: 100000",
        reply_markup=kb.cancel_kb("menu:back"),
    )


async def handle_deposit_amount(update, context, text):
    if not text.isdigit():
        await update.message.reply_text("لطفاً فقط یک عدد معتبر ارسال کن.")
        return

    amount = int(text)
    if amount < MIN_DEPOSIT_AMOUNT or amount > MAX_DEPOSIT_AMOUNT:
        await update.message.reply_text(
            f"مبلغ باید بین {MIN_DEPOSIT_AMOUNT:,} تا {MAX_DEPOSIT_AMOUNT:,} تومان باشد."
        )
        return
    context.user_data["temp"]["amount"] = amount
    context.user_data["state"] = "awaiting_receipt_photo"

    card_number = db.get_setting("card_number")
    card_holder = db.get_setting("card_holder")
    text_out = (
        f"💳 لطفاً مبلغ {amount:,} تومان رو به شماره کارت زیر واریز کن:\n\n"
        f"شماره کارت: `{card_number}`\n"
        f"به نام: {card_holder}\n\n"
        "بعد از واریز، عکس رسید پرداخت رو همینجا برام بفرست تا برای ادمین ارسال شود."
    )
    await update.message.reply_text(text_out, parse_mode=ParseMode.MARKDOWN, reply_markup=kb.cancel_kb("menu:back"))


async def handle_receipt_photo(update, context):
    photo = update.message.photo[-1]
    amount = context.user_data["temp"]["amount"]
    user = update.effective_user

    duplicate = db.find_approved_deposit_by_file(photo.file_unique_id)
    deposit_id = db.create_deposit(user.id, amount, photo.file_id, photo.file_unique_id)
    clear_state(context)
    db.clear_activity_flow(user.id)

    await update.message.reply_text(
        f"✅ رسید شما با شماره #{deposit_id} ثبت شد و برای بررسی ادمین ارسال شد.\n"
        "پس از تایید، موجودی کیف پولت به‌روزرسانی می‌شود.",
        reply_markup=kb.main_menu(),
    )

    caption = (
        f"🧾 رسید واریزی جدید #{deposit_id}\n"
        f"👤 از طرف: {user.full_name} (@{user.username or '---'} | {user.id})\n"
        f"💰 مبلغ اعلامی: {amount:,} تومان"
    )
    if duplicate:
        caption += f"\n\n⚠️ هشدار: این دقیقاً همان عکسیه که قبلاً در رسید تایید‌شده #{duplicate['id']} استفاده شده بود!"
    await notify_admins(context, photo_file_id=photo.file_id, caption=caption, reply_markup=kb.deposit_admin_kb(deposit_id))


# ---------------- انتقال موجودی ----------------

async def start_transfer(query, context):
    context.user_data["state"] = "awaiting_transfer_recipient"
    context.user_data["temp"] = {}
    db.set_activity_flow(query.from_user.id, "transfer")
    await query.edit_message_text(
        "🔵 لطفاً یوزرنیم کاربری که می‌خوای موجودی رو به حسابش منتقل کنی رو ارسال کن.\n"
        "مثال: @username\n\n"
        "⚠️ کاربر گیرنده باید قبلاً حداقل یک بار بات رو استارت کرده باشد.",
        reply_markup=kb.cancel_kb("menu:back"),
    )


async def handle_transfer_recipient(update, context, text):
    candidate = normalize_username(text)
    if not is_valid_username(candidate):
        await update.message.reply_text("❌ یوزرنیم وارد شده معتبر نیست. به این شکل ارسال کن: @username")
        return

    target = db.find_user_by_username(candidate)
    if not target:
        await update.message.reply_text(
            "❌ کاربری با این یوزرنیم در بات پیدا نشد. مطمئن شو یوزرنیم درست است و آن کاربر قبلاً بات رو استارت کرده."
        )
        return

    if target["user_id"] == update.effective_user.id:
        await update.message.reply_text("نمی‌توانی موجودی رو به خودت منتقل کنی.")
        return

    context.user_data["temp"]["target_id"] = target["user_id"]
    context.user_data["temp"]["target_username"] = target["username"]
    context.user_data["state"] = "awaiting_transfer_amount"
    await update.message.reply_text(
        f"گیرنده: @{target['username']}\n"
        f"لطفاً مبلغی که می‌خوای انتقال بدی رو به تومان ارسال کن (حداقل {MIN_TRANSFER_AMOUNT:,} تومان)."
    )


async def handle_transfer_amount(update, context, text):
    if not text.isdigit():
        await update.message.reply_text("لطفاً فقط یک عدد معتبر ارسال کن.")
        return

    amount = int(text)
    if amount < MIN_TRANSFER_AMOUNT:
        await update.message.reply_text(f"حداقل مبلغ قابل انتقال {MIN_TRANSFER_AMOUNT:,} تومان است.")
        return

    sender_db = db.get_user(update.effective_user.id)
    if sender_db["balance"] < amount:
        await update.message.reply_text(
            f"موجودی کافی نیست. موجودی فعلی شما: {sender_db['balance']:,} تومان",
            reply_markup=kb.main_menu(),
        )
        clear_state(context)
        return

    context.user_data["temp"]["amount"] = amount
    context.user_data.pop("state", None)  # منتظر تایید با دکمه هستیم
    target_username = context.user_data["temp"]["target_username"]
    await update.message.reply_text(
        "📋 لطفاً انتقال زیر رو بررسی کن:\n\n"
        f"👤 گیرنده: @{target_username}\n"
        f"💰 مبلغ: {amount:,} تومان\n\n"
        "در صورت تایید، روی دکمه «✅ تایید» بزن.",
        reply_markup=kb.confirm_kb("transfer:confirm", "transfer:cancel"),
    )


async def confirm_transfer(query, context):
    temp = context.user_data.get("temp", {})
    target_id = temp.get("target_id")
    target_username = temp.get("target_username")
    amount = temp.get("amount")
    sender = query.from_user

    if not target_id or not amount:
        await query.edit_message_text("این انتقال دیگر معتبر نیست. لطفاً دوباره از منو اقدام کن.", reply_markup=kb.main_menu())
        clear_state(context)
        return

    sender_db = db.get_user(sender.id)
    if sender_db["balance"] < amount:
        await query.edit_message_text(
            f"موجودی کافی نیست. موجودی فعلی شما: {sender_db['balance']:,} تومان",
            reply_markup=kb.main_menu(),
        )
        clear_state(context)
        return

    db.update_balance(sender.id, -amount)
    db.update_balance(target_id, amount)
    db.create_transfer(sender.id, target_id, amount)
    clear_state(context)
    db.clear_activity_flow(sender.id)

    await query.edit_message_text(
        f"✅ مبلغ {amount:,} تومان با موفقیت به @{target_username} منتقل شد.",
        reply_markup=kb.main_menu(),
    )
    try:
        await context.bot.send_message(
            target_id,
            f"💸 مبلغ {amount:,} تومان از طرف @{sender.username or sender.full_name} به کیف پول شما واریز شد.",
        )
    except Exception:
        pass


async def cancel_transfer(query, context):
    clear_state(context)
    await query.edit_message_text("انتقال لغو شد.", reply_markup=kb.main_menu())


# ---------------- پیگیری سفارشات ----------------

async def show_tracking_menu(query, context):
    clear_state(context)
    await query.edit_message_text(
        "🔎 جهت پیگیری سفارشات یا واریزی‌ها، یکی از گزینه‌های زیر را انتخاب کنید:",
        reply_markup=kb.tracking_menu_kb(),
    )


async def show_order_tracking(query, user_id):
    orders = db.get_user_orders(user_id, limit=10)
    if not orders:
        await query.edit_message_text("هنوز هیچ سفارشی ثبت نکرده‌اید.", reply_markup=kb.tracking_menu_kb())
        return

    lines = ["🔍 آخرین سفارشات شما:\n"]
    for o in orders:
        status = STATUS_LABELS.get(o["status"], o["status"])
        lines.append(f"#{o['id']} | {o['title']} | {o['price']:,} تومان | {status}")
    await query.edit_message_text("\n".join(lines), reply_markup=kb.tracking_menu_kb())


async def show_deposit_tracking(query, user_id):
    deposits = db.get_user_deposits(user_id, limit=10)
    if not deposits:
        await query.edit_message_text("هنوز هیچ واریزی ثبت نکرده‌اید.", reply_markup=kb.tracking_menu_kb())
        return

    lines = ["📄 آخرین واریزی‌های شما:\n"]
    for d in deposits:
        status = STATUS_LABELS.get(d["status"], d["status"])
        lines.append(f"#{d['id']} | 💰 {d['amount']:,} تومان | {status}")
    await query.edit_message_text("\n".join(lines), reply_markup=kb.tracking_menu_kb())


# ---------------- پشتیبانی آنلاین ----------------

async def start_support(query, context):
    context.user_data["state"] = "awaiting_support_message"
    support_text = db.get_setting("support_text")
    await query.edit_message_text(support_text, reply_markup=kb.cancel_kb("menu:back"))


async def handle_support_message(update, context, text):
    user = update.effective_user
    if not db.can_send_support(user.id):
        cooldown = db.get_setting("support_cooldown_minutes")
        await update.message.reply_text(
            f"⏱ برای جلوگیری از اسپم، هر کاربر فقط هر {cooldown} دقیقه یک‌بار می‌تواند پیام پشتیبانی بفرستد. "
            "کمی صبر کن و دوباره تلاش کن."
        )
        return

    clear_state(context)
    db.update_last_support(user.id)
    await update.message.reply_text(
        "✅ پیام شما برای پشتیبانی ارسال شد. به زودی پاسخ داده می‌شود.",
        reply_markup=kb.main_menu(),
    )
    admin_text = (
        f"☎️ پیام پشتیبانی جدید\n"
        f"👤 از طرف: {user.full_name} (@{user.username or '---'} | {user.id})\n\n"
        f"متن پیام:\n{text}"
    )
    await notify_admins(context, text=admin_text, reply_markup=kb.user_admin_kb(user.id, False))


# ---------------- نمایندگی ----------------

async def show_reseller_info(query, context):
    clear_state(context)
    user_id = query.from_user.id
    reseller = db.get_reseller(user_id)
    fee = int(db.get_setting("reseller_fee") or "0")

    if reseller:
        status = "🟢 فعال" if reseller["is_active"] else "🔴 غیرفعال (توسط ادمین خاموش شده)"
        text = (
            "🏪 شما همین الان نمایندگی فعال دارید.\n\n"
            f"🤖 بات: @{reseller['bot_username']}\n"
            f"🚦 وضعیت: {status}\n\n"
            "موجودی نمایندگی شما همان موجودی کیف پول اصلی‌تان در همین بات است؛ "
            "هر سفارشی که در بات شما ثبت شود از همین موجودی کسر می‌شود."
        )
        await query.edit_message_text(text, reply_markup=kb.reseller_info_kb(True))
        return

    text = (
        "🏪 با گرفتن نمایندگی، یک بات تلگرام مستقل با نام و توکن خودتان راه‌اندازی می‌شود که "
        "مشتریان شما می‌توانند مستقیماً از آن سفارش بدهند. هزینه سفارشات از موجودی کیف پول شما در همین بات کسر می‌شود، "
        "و خود سفارش‌ها برای تکمیل به ادمین ما ارسال می‌شود.\n\n"
        f"💰 هزینه فعال‌سازی نمایندگی: {fee:,} تومان (یک‌بار، از کیف پولتان کسر می‌شود)\n\n"
        "برای شروع باید از قبل یک بات در @BotFather ساخته باشید و توکنش را داشته باشید."
    )
    await query.edit_message_text(text, reply_markup=kb.reseller_info_kb(False))


async def start_reseller_signup(query, context):
    user_id = query.from_user.id
    if db.get_setting("reseller_enabled") != "1":
        await query.edit_message_text("سیستم نمایندگی در حال حاضر غیرفعال است.", reply_markup=kb.back_to_menu())
        return
    if db.get_reseller(user_id):
        await query.edit_message_text("شما همین الان نمایندگی دارید.", reply_markup=kb.back_to_menu())
        return

    fee = int(db.get_setting("reseller_fee") or "0")
    db_user = db.get_user(user_id)
    if db_user["balance"] < fee:
        await query.edit_message_text(
            f"موجودی کیف پول شما کافی نیست. هزینه نمایندگی {fee:,} تومان است؛ "
            "لطفاً ابتدا از «افزایش موجودی» کیف پولت رو شارژ کن.",
            reply_markup=kb.back_to_menu(),
        )
        return

    context.user_data["state"] = "awaiting_reseller_token"
    context.user_data["temp"] = {"fee": fee}
    await query.edit_message_text(
        "🤖 توکن باتی که از @BotFather گرفتی رو همینجا بفرست.\n"
        "⚠️ این توکن کلید کامل بات شماست؛ فقط به منابعی که کاملاً به آن‌ها اعتماد دارید بدهید.",
        reply_markup=kb.cancel_kb("menu:back"),
    )


async def handle_reseller_token(update, context, text):
    token = text.strip()
    if ":" not in token or len(token) < 20:
        await update.message.reply_text("این یک توکن معتبر بات تلگرام به نظر نمی‌رسد. دوباره بررسی کن و بفرست.")
        return

    from telegram import Bot
    try:
        test_bot = Bot(token=token)
        me = await test_bot.get_me()
    except Exception:
        await update.message.reply_text(
            "❌ این توکن کار نکرد (شاید اشتباه باشد یا قبلاً جای دیگری در حال استفاده باشد). دوباره بررسی کن."
        )
        return

    context.user_data["temp"]["bot_token"] = token
    context.user_data["temp"]["bot_username"] = me.username
    context.user_data["state"] = "awaiting_reseller_admin_id"
    await update.message.reply_text(
        f"✅ بات @{me.username} شناسایی شد.\n\n"
        "حالا آیدی عددی تلگرام خودت (به‌عنوان مدیر این بات) رو بفرست. "
        "می‌تونی برای گرفتنش به @userinfobot پیام بدی."
    )


async def handle_reseller_admin_id(update, context, text):
    if not text.strip().isdigit():
        await update.message.reply_text("لطفاً فقط آیدی عددی (بدون حروف) رو ارسال کن.")
        return

    user = update.effective_user
    temp = context.user_data.get("temp", {})
    fee = temp.get("fee", 0)
    db_user = db.get_user(user.id)
    if db_user["balance"] < fee:
        await update.message.reply_text("موجودی کافی نیست؛ ثبت‌نام لغو شد.", reply_markup=kb.main_menu())
        clear_state(context)
        return

    if fee > 0:
        db.update_balance(user.id, -fee)
    db.create_reseller(user.id, temp["bot_token"], temp["bot_username"], int(text.strip()))
    clear_state(context)

    await update.message.reply_text(
        f"🎉 نمایندگی شما با موفقیت فعال شد!\nبات شما: @{temp['bot_username']}\n\n"
        "از همین الان مشتریان می‌توانند به بات شما پیام بدن و سفارش بدن.",
        reply_markup=kb.main_menu(),
    )

    try:
        from reseller_manager import start_reseller_bot
        await start_reseller_bot(context.application, user.id)
    except Exception:
        pass

    await notify_admins(
        context,
        text=f"🏪 نمایندگی جدید فعال شد!\n👤 کاربر: {user.id} (@{user.username or '---'})\n🤖 بات: @{temp['bot_username']}",
    )


# ---------------- امتیازدهی به سفارش ----------------

async def handle_rating(query, context, order_id, rating):
    order = db.get_order(order_id)
    if not order or order["user_id"] != query.from_user.id:
        await query.edit_message_text("این سفارش پیدا نشد.")
        return
    if db.get_rating(order_id):
        await query.edit_message_text("شما قبلاً به این سفارش امتیاز داده‌اید. ممنون از نظرتون! 🙏")
        return

    db.create_rating(order_id, query.from_user.id, rating)
    await query.edit_message_text(f"ممنون از امتیازی که دادی! {'⭐' * rating}")

async def handle_text_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    from handlers_admin import handle_admin_text_state  # local import to avoid circular import

    state = context.user_data.get("state")
    text = update.message.text.strip()
    user = update.effective_user
    db_user = db.get_or_create_user(user.id, user.username or "", user.full_name or "")

    if db_user["is_blocked"]:
        await update.message.reply_text("⛔️ دسترسی شما به بات مسدود شده است.")
        return

    if db_user["kyc_required_pending"] and not db_user["kyc_verified"]:
        await update.message.reply_text("🪪 لطفاً ابتدا عکس کارت بانکی خود را برای احراز هویت ارسال کنید.")
        return

    # اگه ادمینه، همیشه اول هندلر ادمین رو امتحان کن (بدون نیاز به لیست state)
    if is_admin(user.id):
        from handlers_admin import handle_admin_text_state
        handled = await handle_admin_text_state(update, context, state or "", text)
        if handled:
            return

    if state == "awaiting_deposit_amount":
        await handle_deposit_amount(update, context, text)
    elif state == "awaiting_transfer_recipient":
        await handle_transfer_recipient(update, context, text)
    elif state == "awaiting_transfer_amount":
        await handle_transfer_amount(update, context, text)
    elif state == "awaiting_order_recipient":
        await handle_order_recipient_input(update, context, text)
    elif state == "awaiting_discount_code":
        await handle_discount_code_input(update, context, text)
    elif state == "awaiting_gram_amount":
        await handle_gram_amount(update, context, text)
    elif state == "awaiting_gram_wallet":
        await handle_gram_wallet(update, context, text)
    elif state == "awaiting_custom_stars_amount":
        await handle_custom_stars_amount(update, context, text)
    elif state == "awaiting_support_message":
        await handle_support_message(update, context, text)
    elif state == "awaiting_reseller_token":
        await handle_reseller_token(update, context, text)
    elif state == "awaiting_reseller_admin_id":
        await handle_reseller_admin_id(update, context, text)
    elif state == "awaiting_receipt_photo":
        await update.message.reply_text("لطفاً عکس رسید پرداخت رو ارسال کن، نه متن.")
    else:
        await update.message.reply_text(
            "از منوی زیر یکی از گزینه‌ها رو انتخاب کن 👇", reply_markup=kb.main_menu()
        )


async def handle_photo_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    db_user = db.get_or_create_user(user.id, user.username or "", user.full_name or "")

    if db_user["is_blocked"]:
        await update.message.reply_text("⛔️ دسترسی شما به بات مسدود شده است.")
        return

    if db_user["kyc_required_pending"] and not db_user["kyc_verified"]:
        await handle_kyc_photo(update, context)
        return

    state = context.user_data.get("state")
    if state == "awaiting_receipt_photo":
        await handle_receipt_photo(update, context)
    else:
        await update.message.reply_text(
            "اگر عکس رسید واریزی هست، لطفاً اول از منو «افزایش موجودی» رو بزن.",
            reply_markup=kb.main_menu(),
        )


async def handle_kyc_photo(update: Update, context: ContextTypes.DEFAULT_TYPE):
    photo = update.message.photo[-1]
    user = update.effective_user
    request_id = db.create_kyc_request(user.id, photo.file_id)

    await update.message.reply_text(
        "✅ عکس کارت شما برای بررسی ادمین ارسال شد. تا تایید، دسترسی شما به بات محدود می‌ماند؛ "
        "به محض تایید، پیام تایید برایت ارسال می‌شود."
    )

    caption = (
        f"🪪 درخواست احراز هویت جدید #{request_id}\n"
        f"👤 از طرف: {user.full_name} (@{user.username or '---'} | {user.id})"
    )
    await notify_admins(context, photo_file_id=photo.file_id, caption=caption, reply_markup=kb.kyc_admin_kb(request_id))
