# bot/handlers/user.py
import asyncio
import logging
import inspect
import json
from pathlib import Path
import jdatetime
import math
from datetime import datetime, timedelta
from database.queries import get_plans_by_category, is_category_full, is_plan_full
from bot.states.states import Purchase, DiscountStates
from database.queries import apply_discount_atomic


from bot.states.renew import Renew
from database.queries import get_active_order, add_order, attach_receipt, set_order_status, get_user
from database.models import PaymentStatus
from aiogram.fsm.context import FSMContext
from aiogram.filters.state import StateFilter


from aiogram import F, Router, types, Bot
from aiogram.filters import Command, CommandStart
from aiogram.fsm.context import FSMContext
from aiogram.types import (
    Message, CallbackQuery,
    InlineKeyboardMarkup, InlineKeyboardButton
)
from aiogram.exceptions import TelegramBadRequest
from aiogram.utils.keyboard import InlineKeyboardBuilder

from bot.menu.main_menu import MENU_COMMANDS, get_main_menu
from bot.keyboards.user import (
    build_plans_keyboard,
    build_plans_list_keyboard,
    build_payment_method_keyboard,
    build_receipt_keyboard,
    get_user_panel_keyboard,
)
from bot.keyboards.admin import order_action_keyboard
from bot.keyboards.shared import (
    get_support_button,
    get_free_test_button,
    get_user_panel_keyboard,
)
from bot.states.purchase import Purchase
from bot.utils.crypto import encrypt_bytes
from database.db import async_session
from database.models import PaymentStatus
from database.queries import (
    get_user,
    add_user,
    get_plan_by_id,
    get_category_by_id,
    get_order_by_id,
    add_order,
    attach_receipt,
    delete_order_by_id,
    set_order_status,
    get_user_pending_orders,
    set_order_price_discount,
    get_active_orders,
    add_gift_credit,
    get_user_gift_credit,
    get_links_by_plan_id,
)
from aiogram.types import LinkPreviewOptions
from services.payment.card_to_card import get_payment_info, get_payment_config
from services.link_pool.assigner import assign_unlimited_group
from config import ADMINS, SUPPORT_ADMIN_USERNAME
from cryptography.fernet import Fernet
from urllib.parse import quote

import math
from aiogram.filters import StateFilter
from aiogram.types import Message


from datetime import datetime
from aiogram import F, Router
from aiogram.filters import StateFilter
from aiogram.types import Message, CallbackQuery
from aiogram.fsm.context import FSMContext

from database.queries import get_discount_code, use_discount_code, set_order_price_discount, get_order_by_id, get_plan_by_id
from bot.keyboards.user import build_payment_method_keyboard





logger = logging.getLogger(__name__)
router = Router()

# ---------- هندلر عمومی برای تمام دکمه‌های منو ----------
@router.message(F.text.in_(MENU_COMMANDS.keys()))
async def handle_menu_buttons(msg: Message, state: FSMContext):
    logger.info("📌 handle_menu_buttons triggered: text=%s", msg.text)

    # ⛔ جلوگیری از بلعیدن دستورات
    if msg.text.startswith("/"):
        logger.warning("⏭ Skipping menu handler for command: %s", msg.text)
        return

    value = MENU_COMMANDS.get(msg.text)
    handler = None

    if callable(value):
        handler = value
    elif isinstance(value, str):
        handler = globals().get(value)
        if handler is None:
            fallback_name_map = {
                "buy": "show_categories",
                "renew": "renew_command",
                "help": "send_tutorial",
                "support": "support_command",
                "plans": "show_categories",
                "my_subscription": "show_user_subscription_cmd",
                "gift": "show_gift",
                "get_prize": "get_prize_handler",
                "start": "start_handler",
                "free_test": "free_test_command",
                "trust_and_feedback":"trust_and_feedback_handler",
                "refund_request": "refund_request_handler",
            }
            fallback = fallback_name_map.get(value)
            if fallback:
                handler = globals().get(fallback)

    if not handler:
        await msg.answer("⚠️ این گزینه پیکربندی نشده. لطفاً با پشتیبانی تماس بگیرید.")
        return

    try:
        sig = inspect.signature(handler)
        params = list(sig.parameters.keys())
        call_kwargs = {}
        if "bot" in params:
            call_kwargs["bot"] = getattr(msg, "bot", None)
        if "state" in params:
            call_kwargs["state"] = state
        result = handler(msg, **call_kwargs)
        if inspect.isawaitable(result):
            await result
    except Exception as e:
        import traceback
        error_text = "".join(traceback.format_exception(type(e), e, e.__traceback__))
        await msg.answer(f"⚠️ خطا:\n{e}")   # متن خطا رو برای خودت هم بفرسته



# ---------- /start ----------
@router.message(CommandStart())
async def start_handler(msg: types.Message, state: FSMContext):
    await state.clear()
    logger.info("🚀 /start called by user_id=%s", msg.from_user.id)
    user_id = msg.from_user.id

    # 🔓 رفع بلاک با استارت توسط کاربر ، اگر قبلاً بلاک شده بود
    try:
        await unblock_user(user_id)
    except Exception as e:
        logger.warning("unblock_user failed for %s: %s", user_id, e)


    # ثبت اولیه کاربر در جدول users
    if not await get_user(user_id):
        await add_user(user_id, msg.from_user.username)

    # بررسی تایید شماره با دیتابیس
    from bot.utils.user_check import is_user_verified
    if not await is_user_verified(user_id):
        keyboard = types.ReplyKeyboardMarkup(
            keyboard=[
                [types.KeyboardButton(
                    text="📞 ارسال شماره تماس",
                    request_contact=True
                )]
            ],
            resize_keyboard=True,
            one_time_keyboard=True
        )
        await msg.answer(
            "👋 سلام!\n📱 برای ادامه کار و احراز هویت، لطفاً شماره تلفن خود را با استفاده از دکمه‌ی زیر در پایین صفحه تایید و ارسال کنید. 👇\n📍بر روی دکمه ی «📞ارسال شماره تماس» کلیک کنید و سپس دکمه «ok» یا «share contact» را بزنید .\n\nشماره‌ی شما کاملاً محفوظ بوده و برای جلوگیری از ربات‌های مزاحم و اکانت‌های اسپم انجام می‌شود 💛",
            reply_markup=keyboard
        )
        return

    # اگر شماره تایید شده است، ادامه عادی
    await msg.answer(
        "به فروشگاه Mushak VPN🚀 👋 خوش آمدید !\nبرای شروع یکی از گزینه‌های زیر را انتخاب کنید 💝 :",
        reply_markup=get_main_menu()
    )


# bot/handlers/user.py (یا فایل مربوط به هندلر contact)
from aiogram import types
from aiogram import Router
from database.db import async_session
from database.models import UserPhone
from sqlalchemy import select


@router.message(lambda message: message.contact is not None)
async def contact_handler(msg: types.Message):
    """
    ذخیره شماره تماس کاربر در دیتابیس:
    - جدول user_phones
    """
    user_id = msg.from_user.id
    phone = msg.contact.phone_number
    username = msg.from_user.username

    async with async_session() as session:
        # بررسی اینکه قبلاً ثبت نشده باشد
        result = await session.execute(
            select(UserPhone).where(UserPhone.user_id == user_id)
        )
        existing = result.scalar_one_or_none()
        if existing is None:
            session.add(UserPhone(
                user_id=user_id,
                phone_number=phone,
                username=username
            ))
            await session.commit()

    await msg.answer(
        "✅ شماره تماس شما با موفقیت ثبت شد.\n"
        "برای ادامه /start را بزنید 💛",
        reply_markup=types.ReplyKeyboardRemove()
    )




# ---------- /plans ----------

# تعریف درست تابع:
async def show_categories(msg: types.Message, bot: Bot, state: FSMContext = None):

    if state:
        await state.clear()

    kb = await build_plans_keyboard()

    await bot.send_message(
        chat_id=msg.chat.id,
        text=(
            "📂 دسته‌بندی پلن‌ها:\n\n"
            "✅ برای مشاهده توضیحات پلن‌ها و آشنایی با آن‌ها، "
            '<a href="https://t.me/mushak_vpn/1060">اینجا کلیک کنید</a>.\n\n'
            "⁉️ کدام پلن برای من مناسب‌تر است؟\n"
            "اگر مصرف بالایی دارید، پلن «نامحدود» مقرون‌به‌صرفه‌ترین انتخاب است؛\n"
            "اما اگر کیفیت، پایداری و اتصال بدون قطعی در زمان ضعف اینترنت اولویت شماست، "
            "استفاده از پلن‌های «اقتصادی، VIP یا پرمیوم» را توصیه می‌کنیم.\n\n"
            "🤖 برای استفاده از Gemini 👈 پلن VIP و پرمیوم\n\n"
            "💬 راهنما و مشاوره رایگان قبل از خرید:\n"
            "🆔 @Mushak_vpn_admin"
        ),
        
        reply_markup=kb,
        parse_mode="HTML",
    link_preview_options=LinkPreviewOptions(is_disabled=True)
    )

# هندلر /plans
@router.message(Command("plans"))
async def plans_command_handler(msg: types.Message, bot: Bot, state: FSMContext):
    await show_categories(msg, bot=bot, state=state)


# ---------- بازگشت به دسته‌بندی‌ها ----------
@router.callback_query(F.data == "back_to_categories")
async def back_to_categories(cb: types.CallbackQuery):
    kb = await build_plans_keyboard()
    await cb.message.edit_text("دسته‌بندی پلن‌ها:", reply_markup=kb)
    await cb.answer()


# ---------- لغو خرید و بازگشت به دسته‌بندی‌ها ----------
from database.queries import (
    get_user_pending_orders,
    delete_order_by_id,
    set_order_status,
    add_gift_credit,            # اضافه‌شده برای بازگرداندن اعتبار هدیه
)
from bot.keyboards.user import build_plans_keyboard
from database.models import PaymentStatus

@router.callback_query(F.data == "cancel_purchase")
async def cancel_purchase(cb: types.CallbackQuery, state: FSMContext):
    # ۱) خواندن داده‌های state
    data = await state.get_data()
    order_id     = data.get("order_id")
    gift_applied = data.get("gift_applied", 0)  # اگر هدیه‌ای اعمال شده بود

    if order_id:
        # ۲) تغییر وضعیت سفارش به رد شده
        await set_order_status(order_id, PaymentStatus.rejected)
        # ۳) حذف سفارش اصلی
        await delete_order_by_id(order_id)

        # ۴) بازگرداندن اعتبار هدیه در صورت مصرف شده
        if gift_applied:
            await add_gift_credit(cb.from_user.id, gift_applied)

        # ۵) حذف سایر سفارشات معوق کاربر
        user_id = cb.from_user.id
        pending_orders = await get_user_pending_orders(user_id)
        for o in pending_orders:
            if o.payment_status == PaymentStatus.pending:
                await delete_order_by_id(o.id)

    # ۶) پاک کردن state و بازگشت به منوی پلن‌ها
    await state.clear()
    kb = await build_plans_keyboard()
    await cb.message.edit_text("❌ خرید لغو شد. مجدداً دسته‌بندی‌ها:", reply_markup=kb)
    await cb.answer("خرید لغو شد.")



# ---------- انتخاب دسته یا پلن ----------
# 1) وقتی دسته انتخاب شد
@router.callback_query(F.data.startswith("category_"))
async def choose_category(cb: types.CallbackQuery, state: FSMContext):
    category_id = int(cb.data.split("_")[1])
    print(f"👉 Category selected: {category_id}")

    # چک ظرفیت دسته
    is_full = await is_category_full(category_id)
    print(f"🔍 is_category_full({category_id}) = {is_full}")
    if is_full:
        print(f"⚠️ Category {category_id} is full")
        return await cb.answer("😢 این دسته پر شده. یکی دیگه رو انتخاب کن!", show_alert=True)

    # گرفتن پلن‌ها
    kb = await build_plans_list_keyboard(category_id)
    try:
        plans = await get_plans_by_category(category_id)
        print(f"✅ Plans found for category {category_id}: {len(plans)}")
    except Exception as e:
        print(f"❌ Error fetching plans for category {category_id}: {e}")

    print(f"✅ Keyboard buttons generated: {len(kb.inline_keyboard)}")

    await cb.message.edit_text("📦 پلن‌های موجود:", reply_markup=kb)
    await cb.answer()


# 2) وقتی روی یک پلن کلیک شد، اول ضوابط رو نمایش بده
@router.callback_query(F.data.startswith("plan_"))
async def prompt_terms(cb: types.CallbackQuery, state: FSMContext):
    try:
        plan_id = int(cb.data.split("_")[1])
        await state.update_data(plan_id=plan_id)

        print(f"👉 prompt_terms: user={cb.from_user.id}, plan_id={plan_id}")

        if await is_plan_full(plan_id):
            await cb.answer(
                "❌ ظرفیت این پلن تکمیل شده. لطفاً یکی دیگه انتخاب کن و یا با پشتیبانی تماس بگیر .",
                show_alert=True
            )
            return

        terms_text = (
            "📜 <b>قوانین و ضوابط خرید</b>\n\n"
            "✅ ممنون از اینکه موشک وی پی ان🚀 رو انتخاب کردید . در ادامه مواردی خدمتتون عرض میشه ، لطفا با دقت مطالعه کنید و برای ادامه خرید تایید کنید :\n"
            "• پشتیبانی کامل از سوی مجموعه ی موشک وی پی ان به صورت تمام و کمال تا اخرین روز اشتراک شما انجام میشود و مشکلات شما برطرف خواهد شد .\n"
            "• ❌ در صورتی که شرایطی رخ دهد که قطعی غیر قابل اجتناب صورت گیرد ، از جمله جنگ ، اینترنت ملی ، اعمال محدودیت اینترنت از سوی دیتا سنتر ها و ... ، موشک وی پی ان🚀 هیچ مسئولیتی در قبال قطعی ها نداشته و این مشکل از سوی ایجاد محدودیت بر روی اینترنت کشور می باشد . فلذا علاوه بر سعی و تلاش بر پشتیبانی کامل برای رفع مشکلات ، مسئولیتی متوجه موشک وی پی ان در این مواقع نیست . ❌\n"
            "• سرور های نامحدود در تاریخ های خاصی ارائه میشن، بنابراین براساس تاریخ خرید شما ممکنه از هزینه خریدتون کسر بشه .\n"
            "• بعد از پرداخت و ارسال رسید، امکان لغو وجود ندارد.\n"
            "• مسئولیت هرگونه واریزی اشتباه به عهده کاربر بوده و امکان بازگشت وجه وجود ندارد.\n"
            "👇 آیا با این شرایط موافقید؟"
        )
        kb = InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="✅ قبول می‌کنم", callback_data=f"terms_accept_{plan_id}"),
                InlineKeyboardButton(text="❌ قبول نمی‌کنم", callback_data=f"terms_decline_{plan_id}")
            ]
        ])

        try:
            await cb.message.edit_text(terms_text, reply_markup=kb, parse_mode="HTML")
        except Exception as e:
            print(f"⚠️ prompt_terms: edit_text failed ({e}), sending new message.")
            await cb.bot.send_message(cb.from_user.id, terms_text, reply_markup=kb, parse_mode="HTML")

        await cb.answer()
    except Exception as e:
        print(f"❌ Exception in prompt_terms: {e}")
        await cb.answer("⚠️ خطا در نمایش قوانین. لطفاً دوباره تلاش کنید.", show_alert=True)

# 3a) اگر قبول کرد
@router.callback_query(F.data.startswith("terms_accept_"))
async def terms_accepted(cb: types.CallbackQuery, state: FSMContext):
    try:
        plan_id = int(cb.data.split("_")[2])

        # 1) چک وجود پلن
        plan = await get_plan_by_id(plan_id)
        if not plan:
            await state.clear()
            await cb.message.edit_text("❌ پلن موردنظر پیدا نشد یا دیگر در دسترس نیست.")
            await cb.answer()
            return

        # 2) چک ظرفیت
        if await is_plan_full(plan_id):
            await state.clear()
            await cb.answer("⚠️ اوپس! ظرفیت بین انتخاب و تأیید پر شده.", show_alert=True)
            return

        # 3) بررسی state برای حالت تمدید
        data = await state.get_data()
        renew_order_id = data.get("renew_order_id")
        is_renew = renew_order_id is not None

        now = datetime.utcnow()
        grp = None

        # تعیین دستهٔ پلن (ایمن)
        is_volume_category = False
        is_unlimited_category = False
        try:
            from database.queries import get_category_by_id
            cat = await get_category_by_id(plan.category_id)
            if cat:
                is_volume_category = (getattr(cat, "type", None) == "حجمی")
                is_unlimited_category = (getattr(cat, "type", None) == "نامحدود")
        except Exception:
            # fallback به volume_limit اگر category در دسترس نبود
            is_volume_category = (plan.volume_limit is not None and plan.volume_limit > 0)
            is_unlimited_category = (plan.volume_limit is None or plan.volume_limit == 0)

        # 👇 فقط برای حجمی در حالت تمدید → now
        if is_renew and is_volume_category:
            cycle_start = now
        else:
            cycle_start = None  # نامحدود یا سفارش جدید → محاسبه در add_order

        # 4) ایجاد سفارش (اگر تمدید است، renew_order_id را منتقل کن)
        order_id = await add_order(
            cb.from_user.id,
            plan_id,
            start_date=cycle_start,
            expiration_date=None,
            renew_order_id=renew_order_id if is_renew else None
        )


        # گرفتن اطلاعات تاریخ‌ها برای نمایش به کاربر
        order = await get_order_by_id(order_id)
        import jdatetime
        jal_start = jdatetime.date.fromgregorian(date=order.start_date.date())
        start_str = jal_start.strftime("%Y/%m/%d")
        jal_exp = jdatetime.date.fromgregorian(date=order.expiration_date.date())
        expire_str = jal_exp.strftime("%Y/%m/%d")

        # 5) محاسبه قیمت و تخفیف
        base_discount = grp.discount_percent if grp else 0.0

        # —— محاسبهٔ extra_discount فقط برای دستهٔ نامحدود و بر اساس تاریخ واقعی خرید ——
        cycle_days = [1, 5, 10, 15, 20, 25]
        try:
            jal_date_real = jdatetime.date.fromgregorian(date=datetime.utcnow().date())
            jal_day_real = jal_date_real.day
            print(f"[discount-check] تاریخ شمسی خرید واقعی: {jal_date_real} → روز={jal_day_real}")
        except Exception as e:
            print(f"[discount-check] خطا در محاسبه تاریخ خرید واقعی: {e}")
            jal_day_real = None

        # تشخیص نامحدود بودن
        is_unlimited = False
        try:
            is_unlimited = is_unlimited_category
        except Exception:
            is_unlimited = (plan.volume_limit is None or plan.volume_limit == 0)

        extra_discount = 0.0
        if is_unlimited and not is_renew and jal_day_real:
            if jal_day_real not in cycle_days:
                extra_discount = 0.0
                print(f"[discount-check] ✅ تخفیف ۱۰٪ اعمال شد (روز {jal_day_real} جزو {cycle_days} نبود).")
            else:
                print(f"[discount-check] ⛔️ بدون تخفیف (روز {jal_day_real} جزو {cycle_days} بود).")

        # ————————————————————————————————————————————————

        total_discount = base_discount + extra_discount

        base_price = plan.price
        raw_final = base_price * (1 - total_discount / 100)
        # ⬅ گرد کردن به بالا
        final_price = int(math.ceil(raw_final / 1000)) * 1000

        await set_order_price_discount(order_id, final_price=final_price, discount=total_discount)

        # 📌 اگر تمدید بود → سرویس قبلی بعد از خرید موفق منقضی میشه
        await state.update_data(
            order_id=order_id,
            plan_id=plan_id,
            final_price=final_price,
            discount=total_discount,
            renew_order_id=renew_order_id if is_renew else None
        )

        # 6) ساخت فاکتور
        lines = [
            "🧾 <b>صورت‌حساب</b>",
            f"• پلن: {plan.name} ({plan.description or ''})",
            f"• قیمت پایه: {int(base_price)} تومان",
            f"• تاریخ شروع اعتبار: {start_str}",
            f"• تاریخ انقضا: {expire_str}",
        ]
        if base_discount:
            lines.append(f"• تخفیف گروهی: {int(base_discount)}٪")
        if extra_discount:
            lines.append(f"• تخفیف ویژه تاریخ خرید: {int(extra_discount)}٪")
        if total_discount:
            lines.append(f"• مجموع تخفیف: {int(total_discount)}٪")

        lines.append(f"• ✅مبلغ نهایی: {final_price:,} تومان✅")
        final_text = "\n".join(lines)

        await cb.message.edit_text(
            final_text,
            reply_markup=build_payment_method_keyboard(order_id),
            parse_mode="HTML"
        )
        await cb.answer("شرایط خرید پذیرفته شد. ادامه دهید.")

    except Exception as e:
        print(f"❌ Exception in terms_accepted: {e}")
        await cb.answer("⚠️ خطا در ثبت سفارش. لطفاً دوباره تلاش کنید.", show_alert=True)





# 3b) اگر قبول نکرد
@router.callback_query(F.data.startswith("terms_decline_"))
async def terms_declined(cb: types.CallbackQuery, state: FSMContext):
    try:
        await state.clear()
        kb = await build_plans_keyboard()
        await cb.message.edit_text("❌ شما شرایط را نپذیرفتید. دوباره انتخاب کنید:", reply_markup=kb)
        await cb.answer("خرید لغو شد.")
    except Exception as e:
        print(f"❌ Exception in terms_declined: {e}")
        await cb.answer("⚠️ خطا در لغو خرید.", show_alert=True)


# ---------- نمایش اطلاعات پرداخت و فعال‌سازی ارسال رسید ----------
@router.callback_query(F.data.startswith("show_payment_info_"))
async def show_payment_info(cb: types.CallbackQuery, state: FSMContext):
    order_id = int(cb.data.split("_")[-1])

    # بازخوانی سفارش
    order = await get_order_by_id(order_id)

    if not order or order.payment_status == PaymentStatus.rejected:
        try:
            await cb.message.delete()
        except Exception:
            pass
        await cb.bot.send_message(
            chat_id=cb.from_user.id,
            text="سفارش قبلی لغو شده است. لطفاً سفارش جدیدی ثبت کنید.",
            reply_markup=await build_plans_keyboard(),
            protect_content=True
        )
        await cb.answer()
        return

    # تولید متن پرداخت
    pay_text = await get_payment_info()
    new_text = f"{cb.message.text}\n\n{pay_text}"

    # حذف پیام قبلی (چون edit_text از protect_content پشتیبانی نمی‌کنه)
    try:
        await cb.message.delete()
    except Exception:
        pass

    # دریافت شماره کارت برای دکمه‌ی CopyTextButton
    config = await get_payment_config()
    card_number = config.card_number if config else "شماره کارت موجود نیست"

    # ساخت reply_markup با CopyTextButton و دکمه‌های موجود
    reply_markup = {
        "inline_keyboard": [
            [
                {"text": "💳 کپی شماره کارت", "copy_text": {"text": card_number}}
            ],
            [
                {"text": "📤 ارسال رسید", "callback_data": f"upload_receipt_{order_id}"},
                {"text": "❌ لغو خرید", "callback_data": "cancel_purchase"}
            ]
        ]
    }

    # ارسال پیام جدید با کیبورد
    await cb.bot.send_message(
        chat_id=cb.from_user.id,
        text=new_text,
        reply_markup=reply_markup,   # ← دیکشنری پایتونی، نه json.dumps
        parse_mode=ParseMode.HTML,
        disable_web_page_preview=True,
        protect_content=True
    )

    await cb.answer()

# ---------- «ارسال رسید» ----------
# ---------- درخواست ارسال رسید ----------
@router.callback_query(F.data.startswith("upload_receipt_"))
async def prompt_receipt(cb: CallbackQuery, state: FSMContext):
    try:
        order_id = int(cb.data.split("_")[2])
    except Exception as e:
        await cb.answer("⚠️ خطا در شناسه سفارش.", show_alert=True)
        return

    print(f"[prompt_receipt] callback from user={cb.from_user.id}, order_id={order_id}")

    order = await get_order_by_id(order_id)
    if not order:
        await cb.answer("سفارش قبلی حذف شده!\nلطفاً سفارش جدیدی ثبت کنید.", show_alert=True)
        return

    await state.set_state(Purchase.waiting_receipt)

    # 🟢 ذخیره کامل اطلاعات سفارش + آیدی پیام صورت‌حساب در State
    await state.update_data(
        order_id=order_id,
        plan_id=order.plan_id,
        renew_order_id=getattr(order, "renew_order_id", None),
        invoice_msg_id=cb.message.message_id  # 👈 ذخیره آیدی پیام صورت‌حساب
    )

    cancel_kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="❌ لغو ارسال رسید", callback_data="cancel_upload_receipt")]
    ])

    await cb.message.answer(
        "لطفاً عکس یا متن رسید پرداخت را ارسال کنید.\n(عکس یا متن را در همین چت ارسال کنید)",
        reply_markup=cancel_kb
    )
    await cb.answer()


@router.callback_query(F.data == "cancel_upload_receipt")
async def cancel_upload_receipt(cb: CallbackQuery, state: FSMContext):
    print(f"[cancel_upload_receipt] user={cb.from_user.id} cancel upload")
    await state.clear()
    kb = await build_plans_keyboard()
    try:
        await cb.message.edit_text(
            "ارسال رسید لغو شد. برای ارسال مجدد از قسمت صورت حساب 👆 روی 'ارسالی رسید پرداخت' کلیک کنید و یا خرید جدیدی انجام دهید 👇",
            reply_markup=kb
        )
    except Exception:
        await cb.bot.send_message(
            cb.from_user.id,
            "ارسال رسید لغو شد. برای ارسال مجدد از قسمت صورت حساب روی 'ارسالی رسید پرداخت' کلیک کنید.",
            reply_markup=kb
        )
    await cb.answer("ارسال رسید لغو شد.", show_alert=False)


# ---------- دریافت رسید ----------
from pathlib import Path
import json
from datetime import datetime
import jdatetime
from bot.utils.crypto import encrypt_bytes
import traceback

# 👇 اینجا ایمپورت درست میشه (همان‌طور که قبلاً در پروژه شما بوده)
from database.queries import (
    expire_order,
    get_order_by_id,
    get_plan_by_id,
    attach_receipt,
    update_order_with_renew,
    get_user_gift_credit,
)
# توجه: ADMINS و order_action_keyboard باید در همان ماژول یا سطح بالاتر موجود باشند (همان‌طور که در پروژه‌تان هست).


# ---------- دریافت رسید ----------
@router.message(Purchase.waiting_receipt)
async def receive_receipt(msg: Message, state: FSMContext):
    try:
        print(
            f"[receive_receipt] triggered for user={msg.from_user.id} "
            f"content_types={[k for k in msg.__dict__.keys() if getattr(msg, k, None)]}"
        )

        cur_state = await state.get_state()
        state_data = await state.get_data()

        if "order_id" not in state_data or "plan_id" not in state_data:
            print("[receive_receipt] state missing order_id or plan_id -> ignoring")
            await msg.answer(
                "⚠️ خطا: سفارش پیدا نشد یا مدت زمان ارسال رسید تمام شده. لطفاً دوباره سفارش دهید."
            )
            await state.clear()
            return

        if not (msg.photo or (msg.text and msg.text.strip())):
            print("[receive_receipt] invalid content (not photo/text)")
            await msg.answer("⛔️ لطفاً فقط عکس یا متن رسید را ارسال کنید.")
            return

        order_id = state_data["order_id"]
        plan_id = state_data["plan_id"]
        gift_applied = int(state_data.get("gift_applied", 0))

        order = await get_order_by_id(order_id)
        if not order:
            await msg.answer("⚠️ سفارش پیدا نشد.")
            await state.clear()
            return

        renew_order_id = state_data.get("renew_order_id") or getattr(order, "renew_order_id", None)

        plan = await get_plan_by_id(plan_id)
        username = msg.from_user.username or "-"

        base_price = int(plan.price) if plan else 0
        final_price = int(order.final_price or 0)
        discount = float(order.discount_percent or 0)
        display_price = final_price

        folder = Path("receipts")
        folder.mkdir(exist_ok=True)

        timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")

        if msg.photo:
            receipt_type = "photo"
            file_id = msg.photo[-1].file_id
            file_path_img = folder / f"{msg.from_user.id}_{order_id}_{timestamp}.jpg"
            try:
                await msg.bot.download(msg.photo[-1], destination=file_path_img)
            except Exception as e:
                print(f"[receive_receipt] failed to download photo: {e}")
        else:
            receipt_type = "text"
            file_id = msg.text.strip()
            file_path_img = None

        receipt_data = {
            "user_id": msg.from_user.id,
            "order_id": order_id,
            "plan_id": plan_id,
            "receipt_type": receipt_type,
            "receipt_value": file_id,
            "username": username,
            "timestamp": msg.date.isoformat(),
            "base_price": base_price,
            "final_price": final_price,
            "discount": discount,
            "gift_applied": gift_applied,
            "saved_file": str(file_path_img) if file_path_img else None,
        }

        try:
            file_path_json = folder / f"{msg.from_user.id}_{order_id}_{timestamp}.json"
            with file_path_json.open("w", encoding="utf-8") as f:
                json.dump(receipt_data, f, ensure_ascii=False, indent=2)

            plain_bytes = json.dumps(receipt_data, ensure_ascii=False).encode("utf-8")
            encrypted_bytes = encrypt_bytes(plain_bytes)
            file_path_bin = folder / f"{msg.from_user.id}_{order_id}_{timestamp}.bin"
            with file_path_bin.open("wb") as f:
                f.write(encrypted_bytes)
        except Exception as save_err:
            print(f"[receive_receipt] file saving warning: {save_err}")

        await set_order_status(order_id, PaymentStatus.pending)
        await attach_receipt(order_id, receipt_type, file_id)

        if renew_order_id:
            try:
                await update_order_with_renew(order_id, renew_order_id)
            except Exception as e:
                print(f"[receive_receipt] failed to update renew_order_id: {e}")

        # 🟢 حذف دکمه‌های شیشه‌ای پیام صورت‌حساب صورت‌گرفته
        invoice_msg_id = state_data.get("invoice_msg_id")
        if invoice_msg_id:
            try:
                await msg.bot.edit_message_reply_markup(
                    chat_id=msg.chat.id,
                    message_id=invoice_msg_id,
                    reply_markup=None
                )
                print(f"[receive_receipt] successfully removed reply_markup from invoice msg {invoice_msg_id}")
            except Exception as markup_err:
                print(f"[receive_receipt] failed to remove markup from invoice msg: {markup_err}")

        remaining_credit = await get_user_gift_credit(msg.from_user.id)

        start_str, expire_str = "", ""
        if order.start_date and order.expiration_date:
            try:
                d_start = order.start_date.date() if isinstance(order.start_date, datetime) else order.start_date
                d_expire = order.expiration_date.date() if isinstance(order.expiration_date, datetime) else order.expiration_date
                jal_start = jdatetime.date.fromgregorian(date=d_start)
                jal_expire = jdatetime.date.fromgregorian(date=d_expire)
                start_str = jal_start.strftime("%Y/%m/%d")
                expire_str = jal_expire.strftime("%Y/%m/%d")
            except Exception as dt_err:
                print(f"[receive_receipt] date format error: {dt_err}")

        # 🔹 پیام برای ادمین
        from html import escape
        user_full_name = escape(msg.from_user.full_name)
        user_username = f"@{msg.from_user.username}" if msg.from_user.username else "ندارد"

        caption_lines = [
            "🔔 <b>رسید تایید نشده ارسال شد</b>",
            f"سفارش: #{order.order_code}",
            f"👤 نام کاربر: {user_full_name}",
            f"🔗 یوزرنیم: {user_username}",
            f"🆔 آیدی عددی: <code>{msg.from_user.id}</code>",
            f"پلن: {plan.name if plan else '-'}",
            f"💵 مبلغ پایه: {base_price:,} تومان",
        ]

        if renew_order_id:
            caption_lines.insert(1, "♻️ <b>این سفارش مربوط به تمدید است</b>")

        if start_str and expire_str:
            caption_lines += [
                f"📅 شروع اعتبار: {start_str}",
                f"⏳ پایان اعتبار: {expire_str}"
            ]

        if discount:
            pre_gift = final_price + gift_applied
            caption_lines += [
                f"🏷️ تخفیف: {int(discount)}٪",
                f"💵 مبلغ پس از تخفیف: {pre_gift:,} تومان",
            ]

        if gift_applied > 0:
            caption_lines += [
                f"🎁 اعتبار هدیه مصرف‌شده: {gift_applied:,} تومان",
                f"💰 اعتبار باقی‌مانده: {remaining_credit:,} تومان",
                f"💳 مبلغ پرداختی واقعی: {final_price:,} تومان",
            ]
        else:
            caption_lines.append(f"💳 مبلغ پرداختی واقعی: {final_price:,} تومان")

        caption_lines.append("\nرسید کاربر:")
        caption = "\n".join(caption_lines)

        for admin_id in ADMINS:
            try:
                if receipt_type == "photo":
                    await msg.bot.send_photo(
                        admin_id,
                        file_id,
                        caption=caption,
                        reply_markup=order_action_keyboard(order_id),
                        parse_mode="HTML",
                    )
                else:
                    await msg.bot.send_message(
                        admin_id,
                        f"{caption}\n\n{file_id}",
                        reply_markup=order_action_keyboard(order_id),
                        parse_mode="HTML",
                    )
            except Exception as e:
                print(f"[receive_receipt] failed to send to admin {admin_id}: {e}")

        # 🔹 پیام برای کاربر
        user_lines = [
            "✅ رسید شما با موفقیت ثبت شد.",
            f"💰 مبلغ پرداختی: {display_price:,} تومان",
        ]
        if discount:
            user_lines.append(f"🟢 شامل تخفیف {int(discount)}٪")
        if gift_applied > 0:
            user_lines.append(f"🎁 اعتبار استفاده‌شده: {gift_applied:,} تومان")

        user_lines.append("")
        user_lines.append("⚠️ لطفاً رسید خود را دوباره ارسال نکنید.")
        user_lines.append("❌ ارسال مجدد یا تکراری رسید، روند تأیید آن را با تأخیر یا مشکل مواجه می‌کند.")
        user_lines.append("")
        user_lines.append("لطفاً منتظر تأیید باشید. 💕")

        await msg.answer("\n".join(user_lines))

        await state.clear()
        print("[receive_receipt] done, state cleared after receipt submission")

    except Exception:
        print("[receive_receipt] Exception:\n", traceback.format_exc())
        await msg.answer("⚠️ خطا در دریافت رسید. لطفاً دوباره تلاش کنید یا با پشتیبانی تماس بگیرید.")
        await state.clear()






# لیست ماه‌های فارسی برای فرمت "۱۵ تیر ۱۴۰۳"
JALALI_MONTHS = [
    "فروردین", "اردیبهشت", "خرداد",
    "تیر", "مرداد", "شهریور",
    "مهر", "آبان", "آذر",
    "دی", "بهمن", "اسفند"
]

def format_shamsi_date(dt: datetime) -> str:
    """تاریخ میلادی را به فرمت '۱۵ تیر ۱۴۰۳' تبدیل می‌کند"""
    shamsi = jdatetime.datetime.fromgregorian(datetime=dt)
    day = shamsi.day
    month_name = JALALI_MONTHS[shamsi.month - 1]
    year = shamsi.year
    return f"{day} {month_name} {year}"





# همین فایل یا فایل جداگانه: هندلر callback برای انتخاب اشتراک



@router.callback_query(F.data.startswith("user:sub:"))
async def user_subscription_detail_cb(cb: CallbackQuery, state: FSMContext):
    order_id = int(cb.data.split(":")[-1])
    order = await get_order_by_id(order_id)

    if not order:
        # اگر اشتراک پیدا نشد، پیغام هشدار بده
        await cb.answer("❌ اشتراک مورد نظر پیدا نشد.", show_alert=True)
        return

    # گرفتن اطلاعات پلن
    plan = await get_plan_by_id(order.plan_id)

    # محاسبه بازه زمانی
    start = order.start_date or order.created_at
    end   = order.expiration_date
    days_left = max((end.date() - datetime.utcnow().date()).days, 0)

    # قالب‌بندی تاریخ شمسی
    start_fa = format_shamsi_date(start)
    end_fa   = format_shamsi_date(end)

    # متن جزئیات اشتراک
    text = (
        f"📄 <b>جزئیات اشتراک #{order.id}</b>\n\n"
        f"🔖 پلن: <i>{plan.name}</i>\n"
        f"📅 شروع: <i>{start_fa}</i>\n"
        f"📅 پایان: <i>{end_fa}</i>\n"
        f"⏳ روزهای باقی‌مانده: <i>{days_left}</i>\n"
        f"🔗 لینک شما: {order.assigned_link}"
    )

    # ساخت کیبورد شامل دکمه تمدید و بازگشت
    markup = InlineKeyboardMarkup(inline_keyboard=[
        [
            InlineKeyboardButton(
                text="🔄 تمدید اشتراک",
                callback_data=f"renew:{order.id}"
            )
        ],
        [
            InlineKeyboardButton(
                text="🏠 بازگشت به منو",
                callback_data="user:menu"
            )
        ]
    ])

    # ویرایش پیام قبلی و نمایش جزئیات با کیبورد
    await cb.message.edit_text(text, parse_mode="HTML", reply_markup=markup)
    # پاسخ خالی برای حذف «بارگذاری»
    await cb.answer()




# ایمپورت از مسیرِ صحیح:

# کوئری‌ها
from database.queries import get_plans_by_ids

# کیبوردها
@router.message(Command("my_subscription"))
async def show_user_subscription_cmd(msg: types.Message, bot: Bot, state: FSMContext):
    user_id = msg.from_user.id

    async with async_session() as session:
        orders = await get_active_orders(user_id, session)
        # فقط سفارش‌های اصلی (is_renew=False) نمایش داده می‌شوند
        orders = [o for o in orders if not getattr(o, "is_renew", False)]
        logging.info(f"[SUBS] user={user_id}, active_orders={[o.id for o in orders]}")

    if not orders:
        return await bot.send_message(
            chat_id=msg.chat.id,
            text="❌ شما اشتراک فعالی ندارید.",
            reply_markup=get_support_button()
        )

    if len(orders) == 1:
        order = orders[0]
        plan = await get_plan_by_id(order.plan_id)

        start = order.start_date or order.created_at
        end   = order.expiration_date
        days_left = max((end.date() - datetime.utcnow().date()).days, 0)

        start_fa = format_shamsi_date(start)
        end_fa = format_shamsi_date(end)

        text = (
            f"📄 <b>اشتراک من</b>\n\n"
            f"🔖 پلن: <i>{plan.name}</i>\n"
            f"📅 شروع: <i>{start_fa}</i>\n"
            f"📅 پایان: <i>{end_fa}</i>\n"
            f"⏳ روزهای باقی‌مانده: <i>{days_left}</i>\n"
            f"🔗 لینک شما: {order.assigned_link}"
        )
        return await bot.send_message(
            chat_id=msg.chat.id,
            text=text,
            parse_mode="HTML",
            reply_markup=get_support_button()
        )

    # اگر چند اشتراک اصلی فعال بود
    # گرفتن همه plan_idهای موجود
    plan_ids = {o.plan_id for o in orders}

    # یکجا گرفتن همه پلان‌ها
    plans = await get_plans_by_ids(plan_ids, session=session)  # حتما session را پاس بده
    plan_map = {p.id: p.name for p in plans}

    # ساخت کیبورد
    keyboard_rows: list[list[InlineKeyboardButton]] = []
    for o in orders:
        plan_name = plan_map.get(o.plan_id, f"پلن {o.plan_id}")
        keyboard_rows.append([
            InlineKeyboardButton(
                text=f"({plan_name} | {o.order_code}#)",
                callback_data=f"user:sub:{o.id}"
            )
        ])
    keyboard_rows.append([
        InlineKeyboardButton(
            text="🏠 بازگشت به منو",
            callback_data="user:menu"
        )
    ])
    kb = InlineKeyboardMarkup(inline_keyboard=keyboard_rows)

    return await bot.send_message(
        chat_id=msg.chat.id,
        text="📃 شما چند اشتراک فعال دارید. لطفاً یکی را انتخاب کنید:",
        reply_markup=kb
    )








@router.callback_query(F.data == "user:menu")
async def user_menu_cb(cb: CallbackQuery):
    """
    وقتی کاربر روی دکمه‌ی «🏠 منو» کلیک می‌کند،
    دوباره منوی اصلی را نمایش می‌دهد.
    اگر محتوا و کیبورد مثل قبل باشد، fallback به ارسال پیام جدید می‌کند.
    """
    text = (
        "🏠 <b>منوی اصلی</b>\n\n"
        "🔖 اشتراک من: مشاهده وضعیت اشتراک‌های شما\n"
        "🛒 خرید پلن: ثبت سفارش جدید\n"
        "❓ راهنما: راهنمای استفاده از ربات"
    )
    kb = get_user_panel_keyboard()

    try:
        # سعی می‌کنیم پیام را ویرایش کنیم
        await cb.message.edit_text(text, parse_mode="HTML", reply_markup=kb)
    except TelegramBadRequest as e:
        # اگر خطای «message is not modified» آمد، پیام جدید بفرست
        if "message is not modified" in e.message:
            await cb.bot.send_message(
                chat_id=cb.from_user.id,
                text=text,
                parse_mode="HTML",
                reply_markup=kb
            )
        else:
            # اگر خطای دیگری بود دوباره پرتاب کن
            raise
    finally:
        # حتماً callback loading را ببند
        await cb.answer()


# 1. راهنما ← هدایت به لینک آموزش + دکمه پشتیبانی
@router.callback_query(F.data == "user:help")
async def user_help_cb(cb: CallbackQuery):
    await cb.answer()  # بستن لودینگ

    tutorial_url = "https://t.me/mushak_vpn_guide"  # ← لینک آموزش خودت

    builder = InlineKeyboardBuilder()
    # دکمه‌ی لینک آموزش
    builder.button(
        text="📘 آموزش اتصال",
        url=tutorial_url
    )
    # دکمه‌ی پشتیبانی (مثل get_support_button)
    builder.button(
        text="💬 تماس با پشتیبانی",
        url="https://t.me/Mushak_vpn_admin"  # ← لینک پشتیبان خودت
    )

    builder.adjust(1, 1)  # دو دکمه در دو ردیف جدا

    markup = builder.as_markup()

    await cb.message.answer(
        "برای دریافت راهنمایی، می‌توانید از گزینه‌های زیر استفاده کنید:",
        reply_markup=markup
    )



# 2. خرید پلن ← اجرای دستی /plans
@router.callback_query(F.data == "user:buy_plan")
async def user_buy_plan_cb(cb: CallbackQuery, state: FSMContext):
    await cb.answer()

    fake_msg = Message.model_validate({
        "message_id": cb.message.message_id,
        "date": cb.message.date,
        "chat": cb.message.chat.model_dump(),
        "message_thread_id": None,
        "from": cb.from_user.model_dump(),
        "text": "/plans"
    })

    await show_categories(fake_msg, bot=cb.bot, state=state)



# 3. اشتراک من ← اجرای دستی /my_subscription
@router.callback_query(F.data == "user:my_subscription")
async def user_my_subscription_cb(cb: CallbackQuery, bot: Bot, state: FSMContext):
    await cb.answer()

    from aiogram.types import Message
    fake_msg = Message.model_validate(
        {
            "message_id": cb.message.message_id,
            "date": cb.message.date,
            "chat": cb.message.chat.model_dump(),
            "message_thread_id": None,
            "from": cb.from_user.model_dump(),
            "text": "/my_subscription"
        }
    )

    await show_user_subscription_cmd(fake_msg, bot=bot, state=state)





# 🔹 نمایش اعتبار هدیه کاربر
@router.message(Command("gift"))
async def show_gift(msg: types.Message):
    credit = await get_user_gift_credit(msg.from_user.id)

    await msg.answer(
        f"🎁 اعتبار هدیه‌ی شما: {credit:,} تومان\n\n"
        "با هر خرید، به میزان 5٪ از مبلغ خرید، اعتبار هدیه دریافت خواهید کرد.\n\n"
        f"🆔 آیدی عددی شما: <code>{msg.from_user.id}</code>",
        parse_mode="HTML"
    )


# 🔹 مرحله صفر: انتخاب بین تخفیف / هدیه / هیچکدام
@router.callback_query(F.data.startswith("get_gift_"))
async def ask_discount_or_gift(cb: CallbackQuery, state: FSMContext):
    order_id = int(cb.data.split("_")[-1])

    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="🏷 استفاده از کد تخفیف", callback_data=f"use_discount_{order_id}")],
        [InlineKeyboardButton(text="🎁 استفاده از اعتبار هدیه", callback_data=f"use_gift_real_{order_id}")],
        [InlineKeyboardButton(text="❌ هیچکدام", callback_data=f"use_none_{order_id}")]
    ])

    await cb.message.edit_text(
        "لطفاً انتخاب کنید:\n\nمی‌خواهید از کد تخفیف استفاده کنید یا از اعتبار هدیه؟",
        reply_markup=kb
    )
    await cb.answer()


# 🔹 مسیر استفاده از کد تخفیف
@router.callback_query(F.data.startswith("use_discount_"))
async def ask_discount_code(cb: CallbackQuery, state: FSMContext):
    order_id = int(cb.data.split("_")[-1])
    await state.update_data(order_id=order_id)

    kb = InlineKeyboardMarkup(
        inline_keyboard=[
            [InlineKeyboardButton(text="❌ لغو", callback_data=f"cancel_discount_{order_id}")]
        ]
    )

    await cb.message.edit_text(
        "🏷 لطفاً کد تخفیف خود را وارد کنید (یا روی «لغو» بزنید):",
        reply_markup=kb
    )

    await state.set_state(DiscountStates.waiting_discount_code)
    await cb.answer()


# 🔹 لغو وارد کردن کد تخفیف
@router.callback_query(F.data.startswith("cancel_discount_"))
async def cancel_discount(cb: CallbackQuery, state: FSMContext):
    order_id = int(cb.data.split("_")[-1])

    order = await get_order_by_id(order_id)
    plan = await get_plan_by_id(order.plan_id)
    base_price = order.final_price or plan.price

    lines = [
        "🧾 <b>صورت‌حساب نهایی (بدون تخفیف)</b>",
        f"• پلن: {plan.name}",
        f"• مبلغ نهایی: {base_price:,} تومان",
    ]
    kb = build_payment_method_keyboard(order_id)

    await cb.message.edit_text("\n".join(lines), reply_markup=kb, parse_mode="HTML")
    await cb.answer("❌ عملیات لغو شد.")
    await state.clear()

# 🔹 اعمال کد تخفیف
@router.message(StateFilter(DiscountStates.waiting_discount_code))
async def apply_discount_code(msg: Message, state: FSMContext):
    raw_code = msg.text

    # پاکسازی + استانداردسازی
    code = raw_code.strip().upper()
    code = code.replace("ي", "ی").replace("ك", "ک")  # عربی → فارسی
    code = code.translate(str.maketrans("۰۱۲۳۴۵۶۷۸۹", "0123456789"))

    # دریافت سفارش
    data = await state.get_data()
    order_id = data.get("order_id")
    if not order_id:
        return await msg.answer("⚠️ شناسه سفارش در حالت ذخیره نشده است. دوباره امتحان کنید.")

    order = await get_order_by_id(order_id)
    if not order:
        return await msg.answer("⚠️ سفارش معتبر پیدا نشد.")

    plan = await get_plan_by_id(order.plan_id)
    if not plan:
        return await msg.answer("⚠️ پلن مرتبط با سفارش پیدا نشد.")

    base_price = order.final_price if order.final_price is not None else plan.price

    discount = await get_discount_code(code)
    if not discount:
        return await msg.answer("❌ کد تخفیف معتبر نیست.")

    # 🛑 بررسی انقضا
    if discount.expires_at is not None and discount.expires_at < datetime.utcnow():
        return await msg.answer("⏳ زمان استفاده از این کد تخفیف منقضی شده است.")

    # 🛑 بررسی پر شدن سقف مصرف کلی
    if discount.usage_limit is not None and discount.used_count >= discount.usage_limit:
        return await msg.answer("⛔️ سقف استفاده از این کد پر شده و دیگر معتبر نیست.")

    # 🛑 بررسی پر شدن سقف مصرف هر کاربر
    if getattr(discount, "per_user_limit", None) is not None:
        from database.queries import count_user_discount_usage
        user_usage = await count_user_discount_usage(msg.from_user.id, discount.id)
        if user_usage >= discount.per_user_limit:
            return await msg.answer("⛔️ شما به سقف استفاده از این کد رسیده‌اید.")


    # محاسبه قیمت نهایی
    final_price = base_price
    if discount.percent:
        final_price -= (base_price * discount.percent) // 100
    final_price = max(final_price, 0)
    final_price = math.ceil(final_price / 1000) * 1000

    # اجرای اتمیک
    success, reason = await apply_discount_atomic(
        order_id=order_id,
        code=code,
        final_price=final_price,
        discount_percent=discount.percent or 0,
        user_id=msg.from_user.id
    )

    if not success:
        if reason == "already_applied":
            return await msg.answer("⚠️ روی این سفارش قبلاً تخفیف اعمال شده است.")
        return await msg.answer("❌ خطا در اعمال کد تخفیف.")

    # پیام موفقیت
    lines = [
        "🧾 <b>صورت‌حساب با کد تخفیف</b>",
        f"• پلن: {plan.name}",
        f"• تخفیف: {discount.percent}٪",
        f"• مبلغ نهایی: {final_price:,} تومان"
    ]
    kb = build_payment_method_keyboard(order_id)
    await msg.answer("\n".join(lines), reply_markup=kb, parse_mode="HTML")
    await state.clear()



# 🔹 مسیر اعتبار هدیه (انتقال به ask_use_gift)
@router.callback_query(F.data.startswith("use_gift_real_"))
async def redirect_to_gift(cb: CallbackQuery, state: FSMContext):
    order_id = int(cb.data.split("_")[-1])
    await ask_use_gift(cb, state, order_id=order_id)


# 🔹 مسیر هیچکدام
@router.callback_query(F.data.startswith("use_none_"))
async def skip_discount_and_gift(cb: CallbackQuery, state: FSMContext):
    order_id = int(cb.data.split("_")[-1])
    order = await get_order_by_id(order_id)
    plan = await get_plan_by_id(order.plan_id)
    base_price = order.final_price or plan.price

    lines = [
        "🧾 <b>صورت‌حساب نهایی</b>",
        f"• پلن: {plan.name}",
        f"• مبلغ نهایی: {base_price:,} تومان",
    ]
    kb = build_payment_method_keyboard(order_id)
    await cb.message.edit_text("\n".join(lines), reply_markup=kb, parse_mode="HTML")
    await cb.answer("بدون تخفیف یا هدیه ادامه می‌دهید.")


# 🔹 مرحله اول: استفاده از اعتبار هدیه
@router.callback_query(F.data.startswith("get_gift_realstep_"))
async def ask_use_gift(cb: CallbackQuery, state: FSMContext, order_id: int = None):
    if order_id is None:
        order_id = int(cb.data.split("_")[-1])

    credit = await get_user_gift_credit(cb.from_user.id)
    if credit <= 0:
        return await cb.answer(
            "🎁 اعتبار شما صفر است. با هر خرید ۵٪ اعتبار هدیه دریافت می‌کنید.",
            show_alert=True
        )

    prompt_text = (
        f"🎁 اعتبار هدیه‌ی شما: {credit:,} تومان\n\n"
        "آیا می‌خواهید از این اعتبار برای کاهش مبلغ فاکتور استفاده کنید؟\n"
        "با هر خرید 5٪ از خریدتان به عنوان اعتبار هدیه داده می‌شود."
    )
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="✅ بله", callback_data=f"use_gift_yes_{order_id}"),
         InlineKeyboardButton(text="❌ خیر", callback_data=f"use_gift_no_{order_id}")]
    ])

    await cb.message.edit_text(prompt_text, reply_markup=kb)
    await cb.answer()


@router.callback_query(F.data.startswith("use_gift_no_"))
async def no_use_gift(cb: CallbackQuery, state: FSMContext):
    await cb.answer("بدون استفاده از اعتبار هدیه ادامه می‌دهید.")
    order_id = int(cb.data.split("_")[-1])

    order = await get_order_by_id(order_id)
    if not order:
        return await cb.message.answer("سفارش پیدا نشد!")

    plan = await get_plan_by_id(order.plan_id)
    base_price = int(order.final_price or 0)
    await set_order_price_discount(order_id, final_price=base_price, discount=order.discount_percent or 0)

    lines = [
        "🧾 <b>صورت‌حساب نهایی</b>",
        f"• پلن: {plan.name}",
        f"• مبلغ نهایی: {base_price:,} تومان",
    ]
    if order.discount_percent:
        lines.insert(1, f"• تخفیف اختصاصی: {int(order.discount_percent)}٪")

    kb = build_payment_method_keyboard(order_id)
    await cb.message.edit_text("\n".join(lines), reply_markup=kb, parse_mode="HTML")

    await state.update_data(gift_applied=0)
    await state.set_state(Purchase.waiting_receipt)


# 🔹 مرحله دوم: تایید استفاده از هدیه (متن راهنما به روز شد)
@router.callback_query(F.data.startswith("use_gift_yes_"))
async def yes_use_gift_first(cb: CallbackQuery):
    order_id = int(cb.data.split("_")[-1])
    credit = await get_user_gift_credit(cb.from_user.id) or 0

    warn_text = (
        f"⚠️ توجه!\n\n"
        f"شما {credit:,} تومان اعتبار هدیه دارید.\n"
        "با ادامه این فرآیند، حداکثر تا ۳۰٪ از مبلغ فاکتور از اعتبار هدیه شما کسر شده و مابقی اعتبار در حساب شما باقی خواهد ماند.\n\n"
        "آیا مطمئن هستید؟"
    )
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="✅ بله، استفاده کن", callback_data=f"use_gift_confirm_{order_id}"),
         InlineKeyboardButton(text="❌ لغو", callback_data=f"use_gift_cancel_{order_id}")]
    ])
    await cb.message.edit_text(warn_text, reply_markup=kb)
    await cb.answer()


@router.callback_query(F.data.startswith("use_gift_cancel_"))
async def cancel_use_gift(cb: CallbackQuery):
    order_id = int(cb.data.split("_")[-1])
    order = await get_order_by_id(order_id)
    plan = await get_plan_by_id(order.plan_id)
    base_price = order.final_price or plan.price

    lines = [
        "🧾 <b>صورت‌حساب نهایی</b>",
        f"• پلن: {plan.name}",
        f"• مبلغ نهایی: {base_price:,} تومان",
    ]
    if order.discount_percent:
        lines.insert(1, f"• تخفیف اختصاصی: {int(order.discount_percent)}٪")

    kb = build_payment_method_keyboard(order_id)
    await cb.message.edit_text("\n".join(lines), reply_markup=kb, parse_mode="HTML")
    await cb.answer("❌ استفاده از اعتبار هدیه لغو شد.")


# 🔹 مرحله سوم: اعمال نهایی اعتبار هدیه (محدودیت ۳0٪ اضافه شد)
@router.callback_query(F.data.startswith("use_gift_confirm_"))
async def yes_use_gift_final(cb: CallbackQuery, state: FSMContext):
    order_id = int(cb.data.split("_")[-1])
    user_id = cb.from_user.id
    data = await state.get_data()

    order = await get_order_by_id(order_id)
    plan  = await get_plan_by_id(order.plan_id)
    base_price = data.get("final_price") or order.final_price or plan.price
    discount_pct = data.get("discount", 0.0)

    gift = await get_user_gift_credit(user_id) or 0

    # 🟢 محاسبه حداکثر ۳۰ درصد مبلغ قابل پرداخت (گردشده به هزار تومان)
    max_gift_allowed = math.floor((base_price * 0.30) / 1000) * 1000

    # 🟢 محاسبه اعتبار نهایی کسر شونده (کمترین مقدار بین موجودی هدیه و سقف ۳۰٪)
    applied = min(gift, max_gift_allowed)

    new_price = base_price - applied
    new_price = math.floor(new_price / 1000) * 1000

    # کسر از موجودی هدیه و ثبت قیمت جدید
    await add_gift_credit(user_id, -applied)
    await set_order_price_discount(order_id, final_price=new_price, discount=discount_pct)
    await state.update_data(gift_applied=applied)

    lines = [
        "🧾 <b>صورت‌حساب با استفاده از هدیه</b>",
        f"• پلن: {plan.name}",
    ]
    if discount_pct:
        lines.append(f"• تخفیف اختصاصی: {int(discount_pct)}٪")
    lines += [
        f"• اعتبار استفاده‌شده: {applied:,} تومان (سقف ۳۰٪)",
        f"• مبلغ نهایی: {new_price:,} تومان",
    ]
    if order.renew_order_id:
        lines.insert(1, "♻️ این سفارش به عنوان <b>تمدید</b> ثبت شده است")

    kb = build_payment_method_keyboard(order_id)
    await cb.message.edit_text("\n".join(lines), reply_markup=kb, parse_mode="HTML")
    await cb.answer("🎁 اعتبار هدیه اعمال شد.")




from aiogram import Router, types
from bot import bot
from bot.middlewares.membership import is_user_member

@router.callback_query(lambda c: c.data == "check_membership")
async def check_membership_callback(callback_query: types.CallbackQuery):
    user_id = callback_query.from_user.id

    if await is_user_member(user_id, bot):
        await callback_query.message.edit_text(
            "✅ عضویت شما تأیید شد.\n حالا می‌توانید از ربات استفاده کنید /start."
        )
    else:
        await callback_query.message.edit_text(
            "🚫 هنوز عضو نیستید! لطفاً اول عضو کانال شوید و دوباره امتحان کنید./start"
        )



# آموزش اتصال 
@router.message(Command(commands=["tutorial", "آموزش_اتصال"]))
async def send_tutorial(message: types.Message):
    """
    هندلر دستور آموزش اتصال:
    با ارسال دکمه‌ای که کاربر را به لینک مورد نظر هدایت می‌کند.
    """
    tutorial_url = "https://t.me/mushak_vpn_guide"  # ← لینک خود را اینجا بگذارید

    builder = InlineKeyboardBuilder()
    builder.button(
        text="📘 آموزش اتصال",
        url=tutorial_url
    )
    builder.adjust(1)
    markup = builder.as_markup()

    await message.answer(
        "برای مشاهده‌ی راهنمای اتصال، روی دکمه‌ی زیر کلیک کنید:",
        reply_markup=markup
    )



# ارتباط با پشتیبانی 
@router.message(Command("support"))
async def support_command(message: Message):
    await message.answer(
        "برای ارتباط با پشتیبانی روی دکمه زیر کلیک کنید:",
        reply_markup=get_support_button()
    )

@router.message(F.text == "🛠 پشتیبانی")
async def handle_support_button(message: Message):
    await message.answer(
        "برای ارتباط با پشتیبانی روی دکمه زیر کلیک کنید:",
        reply_markup=get_support_button()
    )


# دریافت تست رایگان
from aiogram import Router
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.filters import Command
from aiogram.enums import ParseMode
from urllib.parse import quote
from config import SUPPORT_ADMIN_USERNAME


# قالب آماده با فرمت مونوگراف
FREE_TEST_TEMPLATE = """```🎁 سلام!
🆓 لطفاً یک تست رایگان برای من فعال کنید.
🙏 ممنونم!
```"""

@router.message(Command("free_test"))
async def free_test_command(message: Message):
    # URL-encode کردن متن برای پارامتر text
    text_param = quote(FREE_TEST_TEMPLATE)
    url = f"https://t.me/{SUPPORT_ADMIN_USERNAME}?text={text_param}"

    kb = InlineKeyboardMarkup(inline_keyboard=[
        [
            InlineKeyboardButton(
                text="🎁 دریافت تست رایگان",
                url=url
            )
        ]
    ])

    await message.answer(
        f"{FREE_TEST_TEMPLATE}\n"
        "📨 **برای دریافت تست رایگان:**\n"
        "1️⃣ روی دکمه‌ی زیر کلیک کنید.\n"
        "2️⃣ در چت پشتیبانی پیام اماده **Send** را بزنید.",
        parse_mode=ParseMode.MARKDOWN,
        reply_markup=kb
    )




# bot/handlers/user.py

@router.callback_query(F.data.startswith("filled_category_"))
async def alert_filled_category(cb: CallbackQuery):
    await cb.answer("⚠️ این دسته‌بندی تکمیل ظرفیت شده است.\nلطفا از سایر دسته بندی و پلن ها تهیه کنید و یا اینکه با پشتیبانی در تماس باشید .", show_alert=True)

@router.callback_query(F.data.startswith("filled_plan_"))
async def alert_filled_plan(cb: CallbackQuery):
    await cb.answer("⚠️ این پلن تکمیل ظرفیت شده است.\nلطفا از سایر دسته بندی و پلن ها تهیه کنید و یا اینکه با پشتیبانی در تماس باشید ", show_alert=True)



from aiogram import types
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
from database.db import async_session
from database.queries import get_active_orders, get_order_by_id, add_order
from bot.keyboards.user import build_receipt_keyboard

from datetime import datetime, timedelta
from aiogram import types
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery

# 📌 مرحله 1: وقتی کاربر دکمه‌ی "♻️ تمدید سرویس" رو بزنه
@router.message(lambda msg: msg.text == "♻️ تمدید سرویس")
async def renew_command(msg: types.Message):
    import jdatetime

    user_id = msg.from_user.id

    async with async_session() as session:
        active_orders = await get_active_orders(user_id, session)

    if not active_orders:
        await msg.answer("❌ شما هیچ سرویس فعالی برای تمدید ندارید.")
        return

    # ساخت کیبورد برای انتخاب سرویس (تاریخ به شمسی)
    kb = InlineKeyboardMarkup(
        inline_keyboard=[
            [
                InlineKeyboardButton(
                    text=f"🆔 سرویس {o.order_code} | پایان: {jdatetime.date.fromgregorian(date=o.expiration_date.date()).strftime('%Y/%m/%d')}",
                    callback_data=f"renew:{o.id}"
                )
            ]
            for o in active_orders
        ]
    )

    await msg.answer(
        "♻️ لطفاً سرویس موردنظر خود را برای تمدید انتخاب کنید:",
        reply_markup=kb
    )


# 📌 مرحله 2: وقتی کاربر یکی از سرویس‌ها رو انتخاب کرد
# جایگزین کامل process_renew_callback
@router.callback_query(lambda c: c.data and c.data.startswith("renew:"))
async def process_renew_callback(query: CallbackQuery, state: FSMContext):
    try:
        await query.answer()
        user_id = query.from_user.id

        # استخراج order_id از callback_data
        try:
            order_id = int(query.data.split(":")[1])
        except Exception:
            await query.message.answer("⚠️ شناسه سفارش نامعتبر است.")
            return

        # گرفتن سفارش
        order = await get_order_by_id(order_id)
        if not order:
            await query.message.answer("❌ سفارش پیدا نشد.")
            return

        # گرفتن پلن مرتبط
        plan = await get_plan_by_id(order.plan_id)
        if not plan:
            await query.message.answer("⚠️ خطا: پلن مرتبط پیدا نشد. لطفاً با پشتیبانی تماس بگیرید.")
            return

        # تلاش برای گرفتن دسته‌بندی (در صورت وجود)
        category = None
        try:
            category = await get_category_by_id(plan.category_id)
        except Exception:
            category = None

        # تشخیص نامحدود بودن پلن با اولویت category.type سپس volume_limit
        if category and getattr(category, "type", None) is not None:
            is_unlimited = (category.type == "نامحدود")
        else:
            is_unlimited = (plan.volume_limit is None or plan.volume_limit == 0)

        # محاسبه روزهای باقی‌مانده
        today = datetime.utcnow().date()
        try:
            exp_date = order.expiration_date.date() if order.expiration_date else today
        except Exception:
            exp_date = today
        remaining_days = (exp_date - today).days

        # اگر پلن نامحدود است و بیشتر از ۵ روز مانده → عدم اجازهٔ تمدید مستقیم
        if is_unlimited and remaining_days > 5:
            kb = InlineKeyboardMarkup(inline_keyboard=[
                [InlineKeyboardButton(text="🛍️ خرید سرویس جدید", callback_data="user:buy_plan")]
            ])
            await query.message.answer(
                f"⏳ هنوز {remaining_days} روز تا پایان سرویس باقی مانده است.\n"
                "امکان تمدید سرویس نامحدود فقط وقتی فعال می‌شود که کمتر از ۵ روز اعتبار داشته باشید.\n\n"
                "👇 در صورت تمایل می‌توانید یک سرویس جدید خریداری کنید:",
                reply_markup=kb
            )
            return

        # ✅ گرفتن پلن‌های موجود در همان دسته‌بندی (در صورت وجود تابع)
        plans_in_category = []
        try:
            # تابع موجود پروژه شما نامش get_plans_by_category است
            plans_in_category = await get_plans_by_category(plan.category_id)
        except Exception:
            plans_in_category = []

        # اگر دسته‌بندی خالی بود یا فیلترها باعث شد چیزی برنگردد،
        # حداقل پلن فعلی کاربر را به لیست اضافه کن
        if not plans_in_category:
            plans_in_category = [plan]
        else:
            # مطمئن شویم پلن فعلی یک‌بار در لیست وجود دارد و آن را در صدر می‌گذاریم
            unique = {p.id: p for p in plans_in_category}
            unique[plan.id] = plan  # اطمینان از وجود پلن فعلی
            ordered = [unique.pop(plan.id)]
            ordered.extend(unique.values())
            plans_in_category = ordered

        # ساخت کیبورد (هر ردیف یک دکمه) 👉 اصلاح شده
        kb_rows = [
            [InlineKeyboardButton(text=f"{p.name} | {int(p.price):,} تومان", callback_data=f"plan_{p.id}")]
            for p in plans_in_category
        ]
        kb_rows.append([InlineKeyboardButton(text="🔙 انصراف", callback_data="cancel_upload_receipt")])
        kb = InlineKeyboardMarkup(inline_keyboard=kb_rows)

        # ذخیرهٔ سفارش مورد تمدید داخل state و هدایت به انتخاب پلن‌های همان دسته
        await state.update_data(renew_order_id=order.id)

        category_title = category.title if category and getattr(category, "title", None) else "نامشخص"
        await query.message.answer(
            f"🛍️ لطفاً یکی از پلن‌های موجود در دسته‌بندی «{category_title}» را انتخاب کنید:",
            reply_markup=kb
        )

    except Exception as e:
        import traceback
        error_text = "".join(traceback.format_exception(type(e), e, e.__traceback__))
        print("❌ Exception in process_renew_callback:\n", error_text)
        await query.message.answer("⚠️ خطا در پردازش درخواست تمدید. لطفاً دوباره تلاش کنید یا با پشتیبانی تماس بگیرید.")


# آدرس رضایت و اعتماد

@router.message(lambda msg: msg.text == "✅ اعتماد و رضایت شما")
async def trust_and_feedback_handler(msg: Message):
    await msg.answer(
        "🌟 برای مشاهده گوشه ای از رضایت و اعتماد کاربران و مشتریان ما روی گزینه ی زیر کلیک کنید 💕 :\n\n"
        "👈 [کلیک کنید](https://t.me/Mushak_vpn_feedback)",  # لینک دلخواه شما
        disable_web_page_preview=True,
        parse_mode="Markdown"
    )

# دکمه کنسلی و بازگشت وجه
from bot.keyboards.shared import get_support_button

@router.message(F.text == "درخواست کنسلی و بازگشت وجه")
async def refund_request_handler(msg: Message):
    text = (
        "😔💔 از اینکه تجربه‌ی شما رضایت‌بخش نبوده، صمیمانه متأسفیم.\n\n"
        "🛡️ شرایط کنسلی و بازگشت وجه به شرح زیر است:\n"
        "• سرورهای Nitro🪽🏎️ : تا *۱۰ روز* پس از خرید\n"
        "• سرورهای VIP👑 : تا *۳ روز* پس از خرید\n"
        "دارای ضمانت بازگشت کامل وجه می‌باشند.\n"
        "👈 بعد از این مدت همچنان مانند قبل تا آخرین روز اشتراکتون کنار شماییم و پشتیبانی با حوصله مشکلاتتون رو کامل پیگیری و برطرف می‌کنه 💙\n\n"
        "📌 در صورتی که از سرویس خریداری‌شده رضایت کافی ندارید، "
        "لطفاً ابتدا به ادمین پشتیبانی پیام دهید و مشکل خود را مطرح کنید.\n"
        "بسیاری از مشکلات به دلیل نحوه‌ی استفاده یا تنظیمات نادرست و ناآگاهی کاربران از نحوه ی استفاده بوده "
        "و معمولاً با راهنمایی پشتیبانی به‌طور کامل برطرف می‌شوند.💛\n\n"
        "🛠️ در صورت نیاز، امکان ارتقای سرور با پرداخت هزینه ی مابه تفاوت و بهبود کیفیت اتصال نیز با هماهنگی شما فراهم است.🚀\n\n"
        "✅ اگر مشکل به‌هیچ‌وجه برطرف نشد و یا تصمیم قطعی به کنسل کردن سرویس خود داشتید و درخواست شما در بازه‌ی مجاز کنسلی ثبت شود، "
        "مبلغ پرداختی به‌صورت کامل بازگردانده شده و سرویس شما لغو خواهد شد.💖🙏\n\n"
        "با کلیک روی دکمه‌ی زیر، به ادمین پشتیبانی متصل می‌شوید.👇\n"
        "لطفاً علت نارضایتی و مشکلی که هنگام استفاده از سرویس با آن مواجه شده‌اید را به‌طور کامل و دقیق توضیح دهید تا بتوانیم در سریع‌ترین زمان ممکن و به بهترین شکل شما را راهنمایی کنیم و مشکل را برطرف نماییم.💚"
    )

    await msg.answer(
        text,
        reply_markup=get_support_button("📞 ارتباط با پشتیبانی")
    )
    
    
# دریافت جایزه
from database.queries import (
    get_user_game_last_played,
    set_user_game_last_played
)


# 🔹 ۱) منوی اولیه دریافت جایزه
@router.message(F.text == "🎁 دریافت جایزه")
async def get_prize_handler(msg: Message):
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [
            InlineKeyboardButton(text="🎲 تاس شانسی", callback_data="prize:dice"),
            InlineKeyboardButton(text="🎰 کازینو", callback_data="prize:casino")
        ]
    ])
    await msg.answer(
        "🎁 <b>بخش جوایز روزانه</b>\n\n"
        "یکی از بازی‌های زیر را انتخاب کنید و شانس خود را امتحان کنید:\n\n"
        "🎲 <b>تاس:</b> اگر عدد ۶ بیاورید <b>۱۰,۰۰۰ تومان</b> جایزه می‌گیرید.\n"
        "🎰 <b>کازینو:</b> اگر ۳ تا لیمو (🍋🍋🍋) بیاورید <b>۵۰,۰۰۰ تومان</b> جایزه می‌گیرید!\n\n"
        "⚠️ <i>هر بازی هر ۲۴ ساعت یک‌بار قابل استفاده است.</i>",
        reply_markup=kb,
        parse_mode="HTML"
    )



# 🔹 ۲) پردازش بازی‌های تاس و کازینو (با مدیریت کامل خطا)
@router.callback_query(F.data.startswith("prize:"))
async def play_prize_game(cb: CallbackQuery):
    try:
        game_type = cb.data.split(":")[1]  # "dice" یا "casino"
        user_id = cb.from_user.id
        now = datetime.utcnow()

        # استعلام محدودیت ۲۴ ساعته
        last_roll = await get_user_game_last_played(user_id, game_type)

        if last_roll:
            time_passed = now - last_roll
            if time_passed < timedelta(hours=24):
                remaining = timedelta(hours=24) - time_passed
                hours = remaining.seconds // 3600
                minutes = (remaining.seconds % 3600) // 60
                
                game_name = "تاس" if game_type == "dice" else "کازینو"
                await cb.answer(
                    f"⏳ شما در ۲۴ ساعت گذشته بازی {game_name} را انجام داده‌اید!\n"
                    f"زمان باقی‌مانده: {hours} ساعت و {minutes} دقیقه",
                    show_alert=True
                )
                return

        # ثبت زمان بازی جاری
        await set_user_game_last_played(user_id, game_type, now)
        await cb.answer()

        # بازی تاس
        if game_type == "dice":
            dice_msg = await cb.message.answer_dice(emoji="🎲")
            await asyncio.sleep(3.5)
            val = dice_msg.dice.value

            if val == 6:
                await add_gift_credit(user_id, 10000)
                await cb.message.answer(
                    "🎉 <b>هورااااا! تاس شما ۶ آمد! 🏆</b>\n\n"
                    "🎁 مبلغ <b>۱۰,۰۰۰ تومان</b> به اعتبار هدیه‌ی شما افزوده شد 💖\n"
                    "می‌توانید از بخش «🎁 اعتبار هدیه‌ی من» موجودی خود را مشاهده کنید.",
                    parse_mode="HTML"
                )
            else:
                await cb.message.answer(
                    f"🎲 عدد تاس شما: <b>{val}</b>\n\n"
                    "متأسفانه این بار شانس با شما نبود 🙁 (فقط عدد ۶ برنده می‌شود)\n"
                    "۲۴ ساعت دیگر دوباره امتحان کنید! 🌟",
                    parse_mode="HTML"
                )

        # بازی کازینو
        elif game_type == "casino":
            dice_msg = await cb.message.answer_dice(emoji="🎰")
            await asyncio.sleep(3.5)
            val = dice_msg.dice.value

            if val == 43:  # ترکیب ۳ لیمو در تلگرام
                await add_gift_credit(user_id, 50000)
                await cb.message.answer(
                    "🎉🎉🎉 <b>برنده جک‌پات لیمو شدید! 🍋🍋🍋</b>\n\n"
                    "🎁 مبلغ <b>۵۰,۰۰۰ تومان</b> به اعتبار هدیه‌ی شما افزوده شد! 🏆💝\n"
                    "می‌توانید از بخش «🎁 اعتبار هدیه‌ی من» موجودی خود را مشاهده کنید.",
                    parse_mode="HTML"
                )
            else:
                await cb.message.answer(
                    "🎰 این بار ۳ تا لیمو (🍋🍋🍋) نیامد 🙁\n\n"
                    "۲۴ ساعت دیگر دوباره شانس خودت رو در کازینو امتحان کن! 🌟",
                    parse_mode="HTML"
                )

    except Exception as e:
        import traceback
        print(f"❌ Error in play_prize_game: {e}")
        traceback.print_exc()
        await cb.message.answer("⚠️ در پردازش بازی خطایی رخ داد. لطفاً دوباره تلاش کنید.")