import asyncio
import aiosqlite
import logging
import re
from datetime import datetime
from html import escape
from contextlib import suppress

from aiogram import Bot, Dispatcher, Router, F, types
from aiogram.filters import CommandStart, StateFilter, BaseFilter
from aiogram.filters.callback_data import CallbackData  # ⭐️ رفع خطا: این خط اضافه شد
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import (
    Message,
    CallbackQuery,
    ReplyKeyboardMarkup,
    KeyboardButton,
    InlineKeyboardMarkup,
    InlineKeyboardButton,
    Contact,
    Update,
    TelegramObject
)
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder
from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.enums import ParseMode
from aiogram.client.default import DefaultBotProperties
from aiogram.client.session.aiohttp import AiohttpSession  # ⭐️ این خط اضافه می‌شود
from aiogram.client.telegram import TelegramAPIServer      # ⭐️ مسیر ایمپورت اصلاح شد
# ⭐️ hquote به hblockquote تغییر کرد
from aiogram.utils.markdown import hbold, hcode, hitalic, hblockquote

# --- ⚠️ تنظیمات اصلی ---
# ❗️ توکن ربات خود را در اینجا قرار دهید
BOT_TOKEN = "6913980603:AAGnzwarrf0vM6TnzmbPrkkzBRszIjHMO8A"
# 🔑 آیدی عددی ادمین
ADMIN_ID = 468398141
# 📁 نام فایل دیتابیس
DB_NAME = "apple_store.db"

# --- 📚 کلاس‌های CallbackData ---


class OrderManage(CallbackData, prefix="ord_manage"):
    """
    برای دکمه‌های ادمین جهت مدیریت سفارش‌ها
    action: 'start_send', 'reject', 'confirm_recovery'
    """
    action: str
    order_id: int
    user_id: int


class ReplyToUser(CallbackData, prefix="reply_user"):
    """برای دکمه پاسخ به کاربر"""
    user_id: int


class ShowOrder(CallbackData, prefix="show_order"):
    """برای دکمه نمایش اطلاعات سفارش تکمیل شده به کاربر"""
    order_id: int


class Pagination(CallbackData, prefix="pager"):
    """برای دکمه‌های صفحه‌بندی 'سفارشات من'"""
    action: str  # 'prev' or 'next'
    page: int

# --- 🚦 کلاس‌های FSM (ماشین حالت) ---


class NewOrder(StatesGroup):
    """FSM برای ثبت سفارش جدید"""
    first_name = State()
    last_name = State()
    phone = State()
    confirm = State()
    wait_receipt = State()


class Recovery(StatesGroup):
    """FSM برای سفارش ریکاوری"""
    wait_contact = State()
    wait_receipt = State()


class Support(StatesGroup):
    """FSM برای ارسال پیام پشتیبانی"""
    wait_message = State()


class AdminAdd(StatesGroup):
    """FSM ادمین: افزودن اپل آیدی فروخته شده (برای ریکاوری)"""
    email = State()
    password = State()
    dob = State()
    sec_q1 = State()
    sec_q2 = State()
    sec_q3 = State()
    phone = State()


class AdminSearch(StatesGroup):
    """FSM ادمین: جستجو"""
    wait_term = State()


class Broadcast(StatesGroup):
    """FSM ادمین: پیام همگانی"""
    wait_message = State()
    confirm = State()


class Settings(StatesGroup):
    """FSM ادمین: تنظیمات مالی"""
    set_card = State()
    set_price = State()
    set_recovery_price = State()


class ChannelLock(StatesGroup):
    """FSM ادمین: تنظیم کانال قفل"""
    set_channel = State()


class AdminSend(StatesGroup):
    """FSM ادمین: ارسال اطلاعات سفارش جدید"""
    get_email = State()
    get_pass = State()
    get_sec_q1 = State()
    get_sec_q2 = State()
    get_sec_q3 = State()
    get_dob = State()
    confirm_send = State()


class AdminReply(StatesGroup):
    """FSM ادمین: پاسخ به کاربر"""
    wait_reply = State()

# --- 🗃️ توابع مدیریت پایگاه داده (Aiosqlite) ---


async def init_db():
    """ایجاد جداول پایگاه داده در صورت عدم وجود"""
    async with aiosqlite.connect(DB_NAME) as db:
        await db.execute(
            """
            CREATE TABLE IF NOT EXISTS apple_ids (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                email TEXT,
                password TEXT,
                dob TEXT,
                security_questions TEXT,
                customer_phone TEXT,
                status TEXT DEFAULT 'available',
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
            """
        )
        await db.execute(
            """
            CREATE TABLE IF NOT EXISTS settings (
                key TEXT PRIMARY KEY,
                value TEXT
            )
            """
        )
        await db.execute(
            """
            CREATE TABLE IF NOT EXISTS users (
                user_id INTEGER PRIMARY KEY,
                username TEXT,
                phone_number TEXT,
                joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
            """
        )
        await db.execute(
            """
            CREATE TABLE IF NOT EXISTS orders (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER,
                type TEXT DEFAULT 'new',
                first_name TEXT,
                last_name TEXT,
                phone TEXT,
                status TEXT DEFAULT 'pending',
                receipt_id TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
            """
        )

        # درج تنظیمات پیش‌فرض (اگر وجود نداشته باشند)
        default_settings = {
            "card_number": "0000-0000-0000-0000",
            "price": "150000",
            "recovery_price": "50000",
            "force_channel": ""
        }
        for key, value in default_settings.items():
            await db.execute(
                "INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)", (
                    key, value)
            )

        await db.commit()
    logging.info("Database initialized successfully.")


async def get_setting(key: str) -> str | None:
    """خواندن یک تنظیم خاص از دیتابیس"""
    async with aiosqlite.connect(DB_NAME) as db:
        async with db.execute("SELECT value FROM settings WHERE key = ?", (key,)) as cursor:
            row = await cursor.fetchone()
            return row[0] if row else None


async def get_all_settings() -> dict:
    """خواندن تمام تنظیمات از دیتابیس"""
    settings = {}
    async with aiosqlite.connect(DB_NAME) as db:
        async with db.execute("SELECT key, value FROM settings") as cursor:
            async for row in cursor:
                settings[row[0]] = row[1]
    return settings


async def update_setting(key: str, value: str):
    """آپدیت یا درج یک تنظیم در دیتابیس"""
    async with aiosqlite.connect(DB_NAME) as db:
        await db.execute(
            "INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)", (
                key, value)
        )
        await db.commit()


async def register_user(user_id: int, username: str | None, phone_number: str | None = None):
    """ثبت یا آپدیت اطلاعات کاربر در دیتابیس"""
    async with aiosqlite.connect(DB_NAME) as db:
        await db.execute(
            """
            INSERT OR REPLACE INTO users (user_id, username, phone_number, joined_at) 
            VALUES (?, ?, ?, ?)
            """,
            (user_id, username, phone_number, datetime.now())
        )
        await db.commit()

# --- 🛠️ توابع کمکی ---


def normalize_phone(phone: str) -> str:
    """نرمال‌سازی شماره تماس (حذف + و فاصله‌ها)"""
    phone = re.sub(r"[^\d]", "", phone)
    if phone.startswith('98'):
        phone = '0' + phone[2:]
    elif not phone.startswith('0'):
        phone = '0' + phone
    return phone


def escape_md(text: str) -> str:
    """برای MarkdownV2 (در صورت نیاز)"""
    escape_chars = r"[_*\[\]()~`>#+-=|{}.!]"
    return re.sub(f"({escape_chars})", r"\\\1", text)

# --- ⌨️ سازنده‌های کیبورد ---


def get_main_menu() -> ReplyKeyboardMarkup:
    """ایجاد کیبورد منوی اصلی کاربر"""
    builder = ReplyKeyboardBuilder()
    builder.row(KeyboardButton(text="🍎 خرید اپل آیدی"),
                KeyboardButton(text="♻️ ریکاوری"))
    builder.row(KeyboardButton(text="📦 سفارشات من"),
                KeyboardButton(text="📞 پشتیبانی"))
    return builder.as_markup(resize_keyboard=True)


def get_phone_keyboard() -> ReplyKeyboardMarkup:
    """ایجاد کیبورد درخواست شماره تماس"""
    builder = ReplyKeyboardBuilder()
    builder.row(KeyboardButton(
        text="📱 ارسال شماره تماس", request_contact=True))
    builder.row(KeyboardButton(text="🔙 بازگشت"))
    return builder.as_markup(resize_keyboard=True)


async def get_admin_dashboard() -> InlineKeyboardMarkup:
    """ایجاد کیبورد شیشه‌ای پنل ادمین"""
    builder = InlineKeyboardBuilder()
    builder.row(InlineKeyboardButton(
        text="➕ افزودن اپل آیدی (ریکاوری)", callback_data="adm_add"))
    builder.row(InlineKeyboardButton(
        text="🔍 جستجو (سفارش/انبار)", callback_data="adm_search"))
    builder.row(
        InlineKeyboardButton(text="📢 پیام همگانی", callback_data="adm_cast"),
        InlineKeyboardButton(text="💳 تنظیمات مالی", callback_data="adm_sets")
    )

    # خواندن وضعیت قفل کانال
    channel_lock = await get_setting("force_channel")
    lock_status = f"فعال: {channel_lock}" if channel_lock else "غیرفعال"
    builder.row(InlineKeyboardButton(
        text=f"🔐 قفل کانال ({lock_status})", callback_data="adm_ch_lock"))

    builder.row(InlineKeyboardButton(
        text="📊 آمار پیشرفته", callback_data="adm_stats"))
    builder.row(InlineKeyboardButton(
        text="❌ بستن پنل", callback_data="adm_close"))
    return builder.as_markup()


async def get_force_join_kb(channel_username: str) -> InlineKeyboardMarkup:
    """ایجاد کیبورد شیشه‌ای عضویت اجباری"""
    builder = InlineKeyboardBuilder()
    try:
        # اگر @ داشت، لینک میسازیم
        if channel_username.startswith("@"):
            url = f"https://t.me/{channel_username.lstrip('@')}"
        # اگر آیدی عددی بود (معمولا پرایوت)، باید لینک اینوایت بگیریم
        # این بخش نیازمند دسترسی ادمین ربات به کانال است
        # else:
        #     chat = await bot.get_chat(channel_username)
        #     url = chat.invite_link
        # برای سادگی، فرض میکنیم ادمین @ChannelID وارد میکند
        else:
            url = f"https://t.me/{channel_username}"

    except Exception as e:
        logging.error(f"Could not get channel URL for {channel_username}: {e}")
        url = "https://t.me/"  # Fallback

    builder.row(InlineKeyboardButton(text=" عضویت در کانال ", url=url))
    builder.row(InlineKeyboardButton(
        text="✅ عضو شدم", callback_data="check_join"))
    return builder.as_markup()

# --- 🚦 میدل‌ور قفل کانال ---


class ChannelJoinMiddleware(BaseFilter):
    """
    میدل‌ور برای بررسی عضویت کاربر در کانال اجباری
    """

    def __init__(self, bot: Bot):
        self.bot = bot

    async def __call__(self, event: TelegramObject, data: dict) -> bool:
        # استخراج یوزر آیدی از آبجکت‌های مختلف
        if isinstance(event, Message):
            user_id = event.from_user.id
        elif isinstance(event, CallbackQuery):
            user_id = event.from_user.id
        else:
            return True  # برای آپدیت‌های دیگر، عبور کن

        # ادمین نیازی به چک شدن ندارد
        if user_id == ADMIN_ID:
            return True

        channel_id = await get_setting("force_channel")

        # اگر قفل کانال تنظیم نشده بود، عبور کن
        if not channel_id:
            return True

        try:
            # بررسی وضعیت عضویت
            member = await self.bot.get_chat_member(chat_id=channel_id, user_id=user_id)
            if member.status not in ["creator", "administrator", "member"]:
                # کاربر عضو نیست
                kb = await get_force_join_kb(channel_id)
                text = f"🌹 برای استفاده از ربات، لطفا ابتدا در کانال ما عضو شوید و سپس دکمه «عضو شدم» را بزنید:"

                if isinstance(event, Message):
                    await event.answer(text, reply_markup=kb)
                elif isinstance(event, CallbackQuery):
                    await event.message.answer(text, reply_markup=kb)
                    await event.answer()  # پاسخ به کلیک

                return False  # جلوگیری از اجرای هندلر اصلی

            # کاربر عضو است
            return True

        except TelegramBadRequest as e:
            # معمولا برای زمانی است که آیدی کانال اشتباه است
            logging.error(f"Error checking chat member for {channel_id}: {e}")
            if user_id == ADMIN_ID:
                if isinstance(event, Message):
                    await event.answer(f"⚠️ ادمین: خطایی در بررسی عضویت کانال ({channel_id}) رخ داد. آیا ربات در کانال ادمین است؟\n{e}")
                elif isinstance(event, CallbackQuery):
                    await event.message.answer(f"⚠️ ادمین: خطایی در بررسی عضویت کانال ({channel_id}) رخ داد. آیا ربات در کانال ادمین است؟\n{e}")
            # به کاربر عادی خطا را نشان نده، اجازه عبور بده
            return True
        except Exception as e:
            logging.error(f"Unexpected error in ChannelJoinMiddleware: {e}")
            return True  # در صورت خطای ناشناخته، اجازه عبور بده


# --- 🟢 روتر اصلی (کاربران) ---
user_router = Router()


@user_router.callback_query(F.data == "check_join")
async def handle_check_join(callback: CallbackQuery, bot: Bot):
    """هندلر دکمه 'عضو شدم'"""
    user_id = callback.from_user.id
    channel_id = await get_setting("force_channel")

    if not channel_id:
        await callback.message.delete()
        await callback.answer("قفل کانال غیرفعال است.", show_alert=True)
        return

    try:
        member = await bot.get_chat_member(chat_id=channel_id, user_id=user_id)
        if member.status in ["creator", "administrator", "member"]:
            # عضو شده
            await callback.message.delete()
            await callback.message.answer("✅ عضویت شما تایید شد. خوش آمدید!", reply_markup=get_main_menu())
            await callback.answer()
        else:
            # هنوز عضو نشده
            await callback.answer("❌ شما هنوز در کانال عضو نشده‌اید.", show_alert=True)

    except Exception as e:
        await callback.answer(f"خطایی رخ داد: {e}", show_alert=True)
        logging.error(f"Error re-checking join status: {e}")


@user_router.message(CommandStart())
async def handle_start(message: Message, state: FSMContext):
    """هندلر دستور /start"""
    await state.clear()
    user = message.from_user

    # ثبت کاربر در دیتابیس
    await register_user(user.id, user.username)

    if user.id == ADMIN_ID:
        # اگر ادمین بود، پنل ادمین را نمایش بده
        kb = await get_admin_dashboard()
        await message.answer("🔑 سلام ادمین! به پنل مدیریت خوش آمدید.", reply_markup=kb)
    else:
        # کاربر عادی
        await message.answer(
            f"سلام {escape(user.first_name)} عزیز! 👋\nبه فروشگاه خودکار اپل آیدی خوش آمدید.",
            reply_markup=get_main_menu()
        )


@user_router.message(F.text == "🔙 بازگشت")
async def handle_back(message: Message, state: FSMContext):
    """هندلر دکمه بازگشت (خروج از FSM)"""
    await state.clear()
    await message.answer("عملیات لغو شد. به منوی اصلی بازگشتید.", reply_markup=get_main_menu())

# --- 🍎 جریان خرید اپل آیدی (NewOrder FSM) ---


@user_router.message(F.text == "🍎 خرید اپل آیدی")
async def start_new_order(message: Message, state: FSMContext):
    await state.set_state(NewOrder.first_name)
    await message.answer("لطفاً نام خود را وارد کنید:", reply_markup=types.ReplyKeyboardRemove())


@user_router.message(NewOrder.first_name)
async def get_first_name(message: Message, state: FSMContext):
    if not message.text or len(message.text) > 50:
        await message.answer("لطفا یک نام معتبر وارد کنید.")
        return
    await state.update_data(first_name=message.text)
    await state.set_state(NewOrder.last_name)
    await message.answer("لطفاً نام خانوادگی خود را وارد کنید:")


@user_router.message(NewOrder.last_name)
async def get_last_name(message: Message, state: FSMContext):
    if not message.text or len(message.text) > 50:
        await message.answer("لطفا یک نام خانوادگی معتبر وارد کنید.")
        return
    await state.update_data(last_name=message.text)
    await state.set_state(NewOrder.phone)
    await message.answer("لطفاً شماره تماس خود را ارسال کنید یا روی دکمه زیر بزنید:", reply_markup=get_phone_keyboard())


@user_router.message(NewOrder.phone, (F.contact | F.text))
async def get_phone(message: Message, state: FSMContext):
    phone = ""
    if message.contact:
        phone = message.contact.phone_number
    elif message.text:
        if message.text == "🔙 بازگشت":
            await state.clear()
            await message.answer("عملیات لغو شد.", reply_markup=get_main_menu())
            return
        phone = message.text

    normalized_phone = normalize_phone(phone)
    if not re.match(r"^09\d{9}$", normalized_phone):
        await message.answer("لطفا یک شماره تماس معتبر (مانند 09123456789) وارد کنید.", reply_markup=get_phone_keyboard())
        return

    await state.update_data(phone=normalized_phone)

    # نمایش پیش‌فاکتور
    data = await state.get_data()
    settings = await get_all_settings()
    price = int(settings.get("price", 150000))

    text = f"🧾 {hbold('پیش‌فاکتور سفارش شما')}\n\n"
    text += f"👤 {hbold('نام')}: {escape(data['first_name'])}\n"
    text += f"👥 {hbold('نام خانوادگی')}: {escape(data['last_name'])}\n"
    text += f"📱 {hbold('شماره تماس')}: {hcode(normalized_phone)}\n"
    text += f"🍎 {hbold('نوع سفارش')}: خرید اپل آیدی جدید\n\n"
    text += f"💰 {hbold('مبلغ قابل پرداخت')}: {price:,} تومان"

    builder = InlineKeyboardBuilder()
    builder.row(InlineKeyboardButton(
        text="✅ تایید و پرداخت", callback_data="confirm_order"))
    builder.row(InlineKeyboardButton(
        text="✏️ ویرایش اطلاعات", callback_data="edit_order"))

    await state.set_state(NewOrder.confirm)
    await message.answer(text, reply_markup=builder.as_markup())


@user_router.callback_query(NewOrder.confirm, F.data == "edit_order")
async def edit_order(callback: CallbackQuery, state: FSMContext):
    await state.set_state(NewOrder.first_name)
    await callback.message.edit_text("لطفاً نام خود را مجدداً وارد کنید:")
    await callback.answer()


@user_router.callback_query(NewOrder.confirm, F.data == "confirm_order")
async def confirm_order(callback: CallbackQuery, state: FSMContext):
    settings = await get_all_settings()
    price = int(settings.get("price", 150000))
    card_number = settings.get("card_number", "0000-0000-0000-0000")

    text = f"✅ سفارش شما تایید شد.\n\n"
    text += f"لطفاً مبلغ {hbold(f'{price:,} تومان')
                          } را به شماره کارت زیر واریز نمایید:\n\n"
    text += f"💳 {hcode(card_number)}\n\n"
    text += f"پس از واریز، {hbold('فقط عکس فیش واریزی')} را ارسال کنید. (ارسال متن یا فایل قابل قبول نیست)"

    await state.set_state(NewOrder.wait_receipt)
    await callback.message.edit_text(text)
    await callback.answer()


@user_router.message(NewOrder.wait_receipt, F.photo)
async def get_receipt_new(message: Message, state: FSMContext, bot: Bot):
    data = await state.get_data()
    receipt_id = message.photo[-1].file_id

    # ثبت سفارش در دیتابیس
    async with aiosqlite.connect(DB_NAME) as db:
        cursor = await db.execute(
            """
            INSERT INTO orders (user_id, type, first_name, last_name, phone, status, receipt_id)
            VALUES (?, 'new', ?, ?, ?, 'pending', ?)
            """,
            (
                message.from_user.id,
                data['first_name'],
                data['last_name'],
                data['phone'],
                receipt_id
            )
        )
        await db.commit()
        order_id = cursor.lastrowid

    await state.clear()

    # اطلاع‌رسانی به کاربر
    await message.answer(f"✅ فیش شما دریافت شد.\nسفارش شما (کد: {order_id}) ثبت شد و پس از تایید توسط ادمین، اطلاعات اپل آیدی برای شما ارسال خواهد شد.", reply_markup=get_main_menu())

    # ارسال فیش برای ادمین
    caption = f"🧾 {hbold('سفارش خرید جدید')} - #{order_id}\n\n"
    caption += f"👤 {hbold('کاربر')}: {escape(message.from_user.full_name)} (ID: {hcode(message.from_user.id)})\n"
    caption += f"🏷 {hbold('نام')}: {escape(data['first_name'])} {escape(data['last_name'])}\n"
    caption += f"📱 {hbold('شماره')}: {hcode(data['phone'])}"

    builder = InlineKeyboardBuilder()
    builder.row(
        InlineKeyboardButton(
            text="✅ تایید و ارسال اطلاعات",
            callback_data=OrderManage(
                action="start_send", order_id=order_id, user_id=message.from_user.id).pack()
        )
    )
    builder.row(
        InlineKeyboardButton(
            text="❌ رد سفارش",
            callback_data=OrderManage(
                action="reject", order_id=order_id, user_id=message.from_user.id).pack()
        )
    )
    builder.row(
        InlineKeyboardButton(
            text="↩️ پاسخ به کاربر",
            callback_data=ReplyToUser(user_id=message.from_user.id).pack()
        )
    )

    await bot.send_photo(
        ADMIN_ID,
        photo=receipt_id,
        caption=caption,
        reply_markup=builder.as_markup()
    )


@user_router.message(NewOrder.wait_receipt)
async def invalid_receipt(message: Message):
    await message.answer(f"❌ فرمت ارسالی نامعتبر است. لطفاً {hbold('فقط عکس')} فیش واریزی را ارسال کنید.")

# --- ♻️ جریان ریکاوری (Recovery FSM) ---


@user_router.message(F.text == "♻️ ریکاوری")
async def start_recovery(message: Message, state: FSMContext):
    await state.set_state(Recovery.wait_contact)
    await message.answer(
        "لطفاً شماره تماسی که قبلاً با آن اپل آیدی خریداری کرده‌اید را ارسال کنید:",
        reply_markup=get_phone_keyboard()
    )


@user_router.message(Recovery.wait_contact, (F.contact | F.text))
async def get_recovery_contact(message: Message, state: FSMContext):
    phone = ""
    if message.contact:
        phone = message.contact.phone_number
    elif message.text:
        if message.text == "🔙 بازگشت":
            await state.clear()
            await message.answer("عملیات لغو شد.", reply_markup=get_main_menu())
            return
        phone = message.text

    normalized_phone = normalize_phone(phone)
    if not re.match(r"^09\d{9}$", normalized_phone):
        await message.answer("لطفا یک شماره تماس معتبر (مانند 09123456789) وارد کنید.", reply_markup=get_phone_keyboard())
        return

    # جستجو در دیتابیس
    async with aiosqlite.connect(DB_NAME) as db:
        async with db.execute("SELECT id FROM apple_ids WHERE customer_phone = ? AND status = 'sold'", (normalized_phone,)) as cursor:
            account = await cursor.fetchone()

    if not account:
        await state.clear()
        await message.answer("❌ متاسفانه اطلاعاتی با این شماره تماس در آرشیو ما یافت نشد.", reply_markup=get_main_menu())
        return

    # اطلاعات یافت شد
    await state.update_data(phone=normalized_phone)

    settings = await get_all_settings()
    price = int(settings.get("recovery_price", 50000))
    card_number = settings.get("card_number", "0000-0000-0000-0000")

    text = f"✅ اطلاعات شما یافت شد.\n\n"
    text += f"هزینه ریکاوری و بازیابی اطلاعات: {hbold(f'{price:,} تومان')}\n\n"
    text += f"لطفاً مبلغ را به شماره کارت زیر واریز نمایید:\n"
    text += f"💳 {hcode(card_number)}\n\n"
    text += f"پس از واریز، {hbold('فقط عکس فیش واریزی')} را ارسال کنید."

    await state.set_state(Recovery.wait_receipt)
    await message.answer(text)


@user_router.message(Recovery.wait_receipt, F.photo)
async def get_receipt_recovery(message: Message, state: FSMContext, bot: Bot):
    data = await state.get_data()
    receipt_id = message.photo[-1].file_id

    # ثبت سفارش ریکاوری
    async with aiosqlite.connect(DB_NAME) as db:
        cursor = await db.execute(
            """
            INSERT INTO orders (user_id, type, phone, status, receipt_id, first_name, last_name)
            VALUES (?, 'recovery', ?, 'pending', ?, ?, ?)
            """,
            (
                message.from_user.id,
                data['phone'],
                receipt_id,
                message.from_user.first_name,  # استفاده از نام کاربر برای ریکاوری
                message.from_user.last_name or ""
            )
        )
        await db.commit()
        order_id = cursor.lastrowid

    await state.clear()

    # اطلاع‌رسانی به کاربر
    await message.answer(f"✅ فیش شما دریافت شد.\nسفارش ریکاوری شما (کد: {order_id}) ثبت شد و پس از تایید، اطلاعات برای شما ارسال خواهد شد.", reply_markup=get_main_menu())

    # ارسال فیش برای ادمین
    caption = f"🧾 {hbold('سفارش ریکاوری')} - #{order_id}\n\n"
    caption += f"👤 {hbold('کاربر')}: {escape(message.from_user.full_name)} (ID: {hcode(message.from_user.id)})\n"
    caption += f"📱 {hbold('شماره')}: {hcode(data['phone'])}"

    builder = InlineKeyboardBuilder()
    builder.row(
        InlineKeyboardButton(
            text="✅ تایید و ارسال ریکاوری",
            callback_data=OrderManage(
                action="confirm_recovery", order_id=order_id, user_id=message.from_user.id).pack()
        )
    )
    builder.row(
        InlineKeyboardButton(
            text="❌ رد سفارش",
            callback_data=OrderManage(
                action="reject", order_id=order_id, user_id=message.from_user.id).pack()
        )
    )
    builder.row(
        InlineKeyboardButton(
            text="↩️ پاسخ به کاربر",
            callback_data=ReplyToUser(user_id=message.from_user.id).pack()
        )
    )

    await bot.send_photo(
        ADMIN_ID,
        photo=receipt_id,
        caption=caption,
        reply_markup=builder.as_markup()
    )


@user_router.message(Recovery.wait_receipt)
async def invalid_receipt_recovery(message: Message):
    await message.answer(f"❌ فرمت ارسالی نامعتبر است. لطفاً {hbold('فقط عکس')} فیش واریزی را ارسال کنید.")

# --- 📦 جریان سفارشات من (My Orders) ---


async def format_orders_page(user_id: int, page: int = 1, limit: int = 5) -> (str, InlineKeyboardMarkup):
    """
    متن و کیبورد صفحه‌بندی شده سفارشات را ایجاد می‌کند.
    """
    offset = (page - 1) * limit

    async with aiosqlite.connect(DB_NAME) as db:
        # دریافت تعداد کل سفارشات
        async with db.execute("SELECT COUNT(*) FROM orders WHERE user_id = ?", (user_id,)) as cursor:
            total_count = (await cursor.fetchone())[0]

        # دریافت سفارشات صفحه فعلی
        query = """
            SELECT id, type, phone, status, created_at 
            FROM orders 
            WHERE user_id = ? 
            ORDER BY created_at DESC 
            LIMIT ? OFFSET ?
        """
        async with db.execute(query, (user_id, limit, offset)) as cursor:
            orders = await cursor.fetchall()

    if not orders and page == 1:
        return ("شما تاکنون هیچ سفارشی ثبت نکرده‌اید.", None)

    if not orders and page > 1:
        return ("صفحه دیگری وجود ندارد.", None)

    total_pages = (total_count + limit - 1) // limit

    text = f"📜 {hbold('لیست سفارشات شما')} (صفحه {page}/{total_pages})\n\n"
    builder = InlineKeyboardBuilder()

    status_map = {
        'pending': '⏳ در انتظار تایید',
        'completed': '✅ تکمیل شده',
        'rejected': '❌ رد شده'
    }
    type_map = {
        'new': '🍎 خرید جدید',
        'recovery': '♻️ ریکاوری'
    }

    for order in orders:
        order_id, o_type, phone, status, created_at = order
        text += "-----------------------------------\n"
        text += f"📦 {hbold(f'کد پیگیری: #{order_id}')}\n"
        text += f"🏷 {hbold('نوع')}: {type_map.get(o_type, o_type)}\n"
        text += f"📱 {hbold('شماره')}: {hcode(phone)}\n"
        text += f"📊 {hbold('وضعیت')}: {status_map.get(status, status)}\n"

        # اگر تکمیل شده بود، دکمه نمایش اطلاعات
        if status == 'completed':
            builder.row(
                InlineKeyboardButton(
                    text=f"🔐 نمایش اطلاعات سفارش #{order_id}",
                    callback_data=ShowOrder(order_id=order_id).pack()
                )
            )

    text += "\n-----------------------------------"

    # دکمه‌های صفحه‌بندی
    pagination_buttons = []
    if page > 1:
        pagination_buttons.append(
            InlineKeyboardButton(text="⬅️ صفحه قبل", callback_data=Pagination(
                action='prev', page=page - 1).pack())
        )
    if page < total_pages:
        pagination_buttons.append(
            InlineKeyboardButton(text="صفحه بعد ➡️", callback_data=Pagination(
                action='next', page=page + 1).pack())
        )

    if pagination_buttons:
        builder.row(*pagination_buttons)

    return text, builder.as_markup()


@user_router.message(F.text == "📦 سفارشات من")
async def my_orders_handler(message: Message):
    text, keyboard = await format_orders_page(message.from_user.id, page=1)
    await message.answer(text, reply_markup=keyboard)


@user_router.callback_query(Pagination.filter())
async def my_orders_pager(callback: CallbackQuery, callback_data: Pagination):
    page = callback_data.page
    if page < 1:
        await callback.answer("شما در صفحه اول هستید.", show_alert=True)
        return

    text, keyboard = await format_orders_page(callback.from_user.id, page=page)

    if text == "صفحه دیگری وجود ندارد.":
        await callback.answer(text, show_alert=True)
        return

    with suppress(TelegramBadRequest):  # جلوگیری از کرش اگر محتوا تکراری بود
        await callback.message.edit_text(text, reply_markup=keyboard)
    await callback.answer()


@user_router.callback_query(ShowOrder.filter())
async def show_order_details(callback: CallbackQuery, callback_data: ShowOrder):
    order_id = callback_data.order_id
    user_id = callback.from_user.id

    async with aiosqlite.connect(DB_NAME) as db:
        # ابتدا چک میکنیم سفارش مال خود کاربر باشد
        query = "SELECT phone FROM orders WHERE id = ? AND user_id = ? AND status = 'completed'"
        async with db.execute(query, (order_id, user_id)) as cursor:
            order_data = await cursor.fetchone()

        if not order_data:
            await callback.answer("❌ اطلاعات این سفارش یافت نشد یا هنوز تکمیل نشده است.", show_alert=True)
            return

        customer_phone = order_data[0]

        # حالا اطلاعات اپل آیدی را واکشی میکنیم
        query_apple = "SELECT email, password, dob, security_questions FROM apple_ids WHERE customer_phone = ? AND status = 'sold'"
        async with db.execute(query_apple, (customer_phone,)) as cursor:
            apple_id_data = await cursor.fetchone()

    if not apple_id_data:
        await callback.answer("❌ خطای سیستمی: اطلاعات اپل آیدی مرتبط یافت نشد. لطفاً به پشتیبانی پیام دهید.", show_alert=True)
        return

    email, password, dob, security_questions = apple_id_data

    text = f"🔐 {hbold(f'اطلاعات سفارش #{order_id}')}\n\n"
    text += f"📧 {hbold('ایمیل')}: {hcode(email)}\n"
    text += f"🔑 {hbold('رمز عبور')}: {hcode(password)}\n"
    text += f"🎂 {hbold('تاریخ تولد (DOB)')}: {hcode(dob)}\n\n"
    text += f"{hbold('سوالات امنیتی:')}\n"
    # ⭐️ hquote به hblockquote تغییر کرد
    text += f"{hblockquote(escape(security_questions))}\n\n"
    text += "❗️ لطفاً این اطلاعات را در جای امنی ذخیره کنید."

    # اطلاعات را در یک پیام جدید ارسال میکنیم (نه ادیت)
    await callback.message.answer(text)
    await callback.answer()

# --- 📞 جریان پشتیبانی (Support FSM) ---


@user_router.message(F.text == "📞 پشتیبانی")
async def start_support(message: Message, state: FSMContext):
    await state.set_state(Support.wait_message)
    await message.answer("لطفاً پیام خود را برای پشتیبانی ارسال کنید (متن، عکس، ...):", reply_markup=ReplyKeyboardBuilder().add(KeyboardButton(text="🔙 بازگشت")).as_markup(resize_keyboard=True))


@user_router.message(Support.wait_message)
async def get_support_message(message: Message, state: FSMContext, bot: Bot):
    if message.text == "🔙 بازگشت":
        await state.clear()
        await message.answer("عملیات لغو شد.", reply_markup=get_main_menu())
        return

    await state.clear()

    user_info = f"👤 {hbold('پیام جدید از')}: {escape(message.from_user.full_name)}\n"
    user_info += f"🆔 {hbold('User ID')}: {hcode(message.from_user.id)}"

    kb = InlineKeyboardBuilder().row(
        InlineKeyboardButton(
            text="↩️ پاسخ به کاربر",
            callback_data=ReplyToUser(user_id=message.from_user.id).pack()
        )
    ).as_markup()

    try:
        # فوروارد پیام کاربر به ادمین
        await bot.send_message(ADMIN_ID, user_info)
        await message.forward(ADMIN_ID)
        # ارسال دکمه پاسخ در یک پیام جداگانه
        await bot.send_message(ADMIN_ID, "جهت پاسخ به این کاربر، روی دکمه زیر بزنید:", reply_markup=kb)

        await message.answer("✅ پیام شما برای پشتیبانی ارسال شد. منتظر پاسخ بمانید.", reply_markup=get_main_menu())

    except Exception as e:
        await message.answer(f"❌ خطایی در ارسال پیام رخ داد: {e}", reply_markup=get_main_menu())
        logging.error(f"Error forwarding support message: {e}")


# --- 🔴 روتر ادمین ---
admin_router = Router()
# فیلتر اختصاصی برای ادمین
admin_router.message.filter(F.from_user.id == ADMIN_ID)
admin_router.callback_query.filter(F.from_user.id == ADMIN_ID)


@admin_router.message(CommandStart())
async def admin_start_reroute(message: Message, state: FSMContext):
    """/start ادمین را به هندلر اصلی هدایت میکند"""
    await handle_start(message, state)


@admin_router.callback_query(F.data == "adm_close")
async def admin_close_panel(callback: CallbackQuery):
    await callback.message.delete()
    await callback.answer("پنل بسته شد.")


@admin_router.callback_query(F.data == "admin_dashboard")
async def admin_show_dashboard(callback: CallbackQuery):
    kb = await get_admin_dashboard()
    await callback.message.edit_text("🔑 پنل مدیریت:", reply_markup=kb)
    await callback.answer()

# --- ادمین: افزودن اپل آیدی (ریکاوری) ---


@admin_router.callback_query(F.data == "adm_add")
async def admin_add_start(callback: CallbackQuery, state: FSMContext):
    await state.set_state(AdminAdd.email)
    await callback.message.edit_text("1/7: ایمیل اپل آیدی فروخته شده را وارد کنید:")
    await callback.answer()


@admin_router.message(AdminAdd.email)
async def admin_add_email(message: Message, state: FSMContext):
    await state.update_data(email=message.text)
    await state.set_state(AdminAdd.password)
    await message.answer("2/7: رمز عبور را وارد کنید:")


@admin_router.message(AdminAdd.password)
async def admin_add_pass(message: Message, state: FSMContext):
    await state.update_data(password=message.text)
    await state.set_state(AdminAdd.dob)
    await message.answer("3/7: تاریخ تولد (DOB) را وارد کنید (مثال: 1990-01-01):")


@admin_router.message(AdminAdd.dob)
async def admin_add_dob(message: Message, state: FSMContext):
    await state.update_data(dob=message.text)
    await state.set_state(AdminAdd.sec_q1)
    await message.answer("4/7: سوال امنیتی ۱ (همراه با جواب) را وارد کنید:")


@admin_router.message(AdminAdd.sec_q1)
async def admin_add_q1(message: Message, state: FSMContext):
    await state.update_data(q1=message.text)
    await state.set_state(AdminAdd.sec_q2)
    await message.answer("5/7: سوال امنیتی ۲ (همراه با جواب) را وارد کنید:")


@admin_router.message(AdminAdd.sec_q2)
async def admin_add_q2(message: Message, state: FSMContext):
    await state.update_data(q2=message.text)
    await state.set_state(AdminAdd.sec_q3)
    await message.answer("6/7: سوال امنیتی ۳ (همراه با جواب) را وارد کنید:")


@admin_router.message(AdminAdd.sec_q3)
async def admin_add_q3(message: Message, state: FSMContext):
    await state.update_data(q3=message.text)
    await state.set_state(AdminAdd.phone)
    await message.answer(f"7/7: {hbold('شماره موبایل مشتری')} که با آن خرید کرده را وارد کنید (مهم برای ریکاوری):")


@admin_router.message(AdminAdd.phone)
async def admin_add_phone(message: Message, state: FSMContext):
    normalized_phone = normalize_phone(message.text)
    if not re.match(r"^09\d{9}$", normalized_phone):
        await message.answer("شماره موبایل نامعتبر است. مجدد وارد کنید (مثال: 09123456789):")
        return

    data = await state.get_data()

    security_questions = (
        f"Q1: {data['q1']}\n"
        f"Q2: {data['q2']}\n"
        f"Q3: {data['q3']}"
    )

    async with aiosqlite.connect(DB_NAME) as db:
        # اکانت را با شماره تلفن آپدیت میکنیم یا اگر نبود درج میکنیم
        await db.execute(
            """
            INSERT INTO apple_ids (email, password, dob, security_questions, customer_phone, status)
            VALUES (?, ?, ?, ?, ?, 'sold')
            ON CONFLICT(customer_phone) DO UPDATE SET
                email = excluded.email,
                password = excluded.password,
                dob = excluded.dob,
                security_questions = excluded.security_questions,
                status = 'sold'
            """,
            (
                data['email'],
                data['password'],
                data['dob'],
                security_questions,
                normalized_phone
            )
        )
        await db.commit()

    await state.clear()
    kb = await get_admin_dashboard()
    await message.answer(f"✅ اکانت برای ریکاوری (مربوط به شماره {normalized_phone}) با موفقیت ذخیره شد.", reply_markup=kb)

# --- ادمین: جستجو ---


@admin_router.callback_query(F.data == "adm_search")
async def admin_search_start(callback: CallbackQuery, state: FSMContext):
    await state.set_state(AdminSearch.wait_term)
    await callback.message.edit_text("عبارت جستجو (شماره، ایمیل، کد سفارش، نام) را وارد کنید:")
    await callback.answer()


@admin_router.message(AdminSearch.wait_term)
async def admin_search_term(message: Message, state: FSMContext):
    term = message.text
    like_term = f"%{term}%"
    normalized_phone = normalize_phone(term)
    like_phone = f"%{normalized_phone}%"

    results = []

    async with aiosqlite.connect(DB_NAME) as db:
        # جستجو در سفارشات
        query_orders = """
            SELECT id, user_id, type, phone, status 
            FROM orders 
            WHERE phone LIKE ? OR first_name LIKE ? OR last_name LIKE ? OR id = ?
            ORDER BY created_at DESC LIMIT 5
        """
        async with db.execute(query_orders, (like_phone, like_term, like_term, term if term.isdigit() else -1)) as cursor:
            orders = await cursor.fetchall()
            if orders:
                results.append(hbold("--- 📦 نتایج سفارشات (Orders) ---"))
                for o in orders:
                    results.append(
                        f"ID: {hcode(o[0])} | نوع: {o[2]} | شماره: {hcode(o[3])} | وضعیت: {o[4]} | UserID: {hcode(o[1])}"
                    )

        # جستجو در انبار
        query_apple_ids = """
            SELECT id, email, customer_phone, status 
            FROM apple_ids 
            WHERE email LIKE ? OR customer_phone LIKE ?
            ORDER BY created_at DESC LIMIT 5
        """
        async with db.execute(query_apple_ids, (like_term, like_phone)) as cursor:
            accounts = await cursor.fetchall()
            if accounts:
                results.append(hbold("\n--- 🍎 نتایج انبار (Apple IDs) ---"))
                for a in accounts:
                    results.append(
                        f"ID: {hcode(a[0])} | ایمیل: {hcode(a[1])} | شماره مشتری: {hcode(a[2])} | وضعیت: {a[3]}"
                    )

    await state.clear()
    kb = await get_admin_dashboard()

    if not results:
        await message.answer(f"هیچ نتیجه‌ای برای '{escape(term)}' یافت نشد.", reply_markup=kb)
        return

    await message.answer("\n".join(results), reply_markup=kb)


# --- ادمین: پیام همگانی ---
@admin_router.callback_query(F.data == "adm_cast")
async def admin_cast_start(callback: CallbackQuery, state: FSMContext):
    await state.set_state(Broadcast.wait_message)
    await callback.message.edit_text(f"پیامی که میخواهید برای {hbold('همه کاربران')} ارسال شود را وارد کنید (متن، عکس، ...):")
    await callback.answer()


@admin_router.message(Broadcast.wait_message)
async def admin_cast_get(message: Message, state: FSMContext):
    # ذخیره پیام برای ارسال
    await state.update_data(message_id=message.message_id, chat_id=message.chat.id)
    await state.set_state(Broadcast.confirm)

    builder = InlineKeyboardBuilder()
    builder.row(InlineKeyboardButton(
        text="✅ بله، ارسال شود", callback_data="cast_confirm"))
    builder.row(InlineKeyboardButton(
        text="❌ لغو", callback_data="cast_cancel"))

    await message.answer("آیا از ارسال این پیام برای همه کاربران مطمئن هستید؟", reply_markup=builder.as_markup())


@admin_router.callback_query(Broadcast.confirm, F.data == "cast_cancel")
async def admin_cast_cancel(callback: CallbackQuery, state: FSMContext):
    await state.clear()
    await callback.message.edit_text("ارسال پیام همگانی لغو شد.")
    await callback.answer()


@admin_router.callback_query(Broadcast.confirm, F.data == "cast_confirm")
async def admin_cast_confirm(callback: CallbackQuery, state: FSMContext, bot: Bot):
    data = await state.get_data()
    message_id = data['message_id']
    chat_id = data['chat_id']

    await state.clear()
    await callback.message.edit_text("⏳ در حال ارسال پیام همگانی...")

    async with aiosqlite.connect(DB_NAME) as db:
        async with db.execute("SELECT user_id FROM users") as cursor:
            users = await cursor.fetchall()

    if not users:
        await callback.message.edit_text("هیچ کاربری در دیتابیس یافت نشد.")
        return

    success_count = 0
    fail_count = 0

    for (user_id,) in users:
        try:
            await bot.copy_message(
                chat_id=user_id,
                from_chat_id=chat_id,
                message_id=message_id
            )
            success_count += 1
            await asyncio.sleep(0.1)  # جلوگیری از اسپم و ریت لیمیت
        except (TelegramForbiddenError, TelegramBadRequest):
            fail_count += 1
        except Exception as e:
            fail_count += 1
            logging.error(f"Error broadcasting to {user_id}: {e}")

    report = f"📣 {hbold('گزارش پیام همگانی')}\n\n"
    report += f"✅ ارسال موفق: {success_count} نفر\n"
    report += f"❌ ارسال ناموفق (بلاک کرده یا ربات حذف شده): {fail_count} نفر"

    kb = await get_admin_dashboard()
    await callback.message.answer(report, reply_markup=kb)
    await callback.answer()

# --- ادمین: تنظیمات مالی ---


@admin_router.callback_query(F.data == "adm_sets")
async def admin_sets_start(callback: CallbackQuery, state: FSMContext):
    settings = await get_all_settings()
    text = f"⚙️ {hbold('تنظیمات مالی')}\n\n"
    text += f"💳 شماره کارت فعلی:\n{hcode(settings.get('card_number', 'N/A'))}\n"
    text += f"💰 قیمت خرید فعلی: {hcode(settings.get('price', 'N/A'))} تومان\n"
    text += f"♻️ قیمت ریکاوری فعلی: {hcode(settings.get('recovery_price', 'N/A'))}\n\n"
    text += "1/3: شماره کارت جدید را وارد کنید (یا 'skip' برای رد شدن):"

    await state.set_state(Settings.set_card)
    await callback.message.edit_text(text)
    await callback.answer()


@admin_router.message(Settings.set_card)
async def admin_sets_card(message: Message, state: FSMContext):
    if message.text.lower() != 'skip':
        await update_setting('card_number', message.text)
    await state.set_state(Settings.set_price)
    await message.answer(f"2/3: قیمت جدید {hbold('خرید اپل آیدی')} را به تومان وارد کنید (مثال: 150000) (یا 'skip'):")


@admin_router.message(Settings.set_price)
async def admin_sets_price(message: Message, state: FSMContext):
    if message.text.lower() != 'skip':
        if not message.text.isdigit():
            await message.answer("لطفا فقط عدد وارد کنید.")
            return
        await update_setting('price', message.text)
    await state.set_state(Settings.set_recovery_price)
    await message.answer(f"3/3: قیمت جدید {hbold('ریکاوری')} را به تومان وارد کنید (مثال: 50000) (یا 'skip'):")


@admin_router.message(Settings.set_recovery_price)
async def admin_sets_recovery(message: Message, state: FSMContext):
    if message.text.lower() != 'skip':
        if not message.text.isdigit():
            await message.answer("لطفا فقط عدد وارد کنید.")
            return
        await update_setting('recovery_price', message.text)

    await state.clear()
    kb = await get_admin_dashboard()
    await message.answer("✅ تنظیمات مالی با موفقیت ذخیره شد.", reply_markup=kb)

# --- ادمین: تنظیم قفل کانال ---


@admin_router.callback_query(F.data == "adm_ch_lock")
async def admin_ch_lock_start(callback: CallbackQuery, state: FSMContext):
    current = await get_setting('force_channel')
    text = f"🔐 {hbold('تنظیم قفل کانال')}\n"
    text += f"وضعیت فعلی: {hcode(current) if current else 'غیرفعال'}\n\n"
    text += "لطفاً آیدی کانال (مانند @ChannelID) را وارد کنید.\n"
    text += f"برای غیرفعال کردن، کلمه {hcode('off')} را ارسال کنید.\n\n"
    text += f"⚠️ {hbold('توجه')}: ربات {hbold('باید')} در کانال مورد نظر ادمین باشد."

    await state.set_state(ChannelLock.set_channel)
    await callback.message.edit_text(text)
    await callback.answer()


@admin_router.message(ChannelLock.set_channel)
async def admin_ch_lock_set(message: Message, state: FSMContext, bot: Bot):
    new_channel = message.text

    if new_channel.lower() == 'off':
        await update_setting('force_channel', '')
        await state.clear()
        kb = await get_admin_dashboard()
        await message.answer("✅ قفل کانال با موفقیت غیرفعال شد.", reply_markup=kb)
        return

    if not new_channel.startswith('@'):
        await message.answer("❌ آیدی کانال نامعتبر است. باید با @ شروع شود (مثال: @ChannelID).")
        return

    # تست عضویت ادمین (برای اطمینان از دسترسی ربات)
    try:
        await bot.get_chat_member(new_channel, bot.id)
    except Exception as e:
        await message.answer(f"❌ ربات نتوانست به کانال {new_channel} دسترسی پیدا کند.\n"
                             f"مطمئن شوید ربات در کانال عضو و ادمین است.\n"
                             f"خطا: {e}")
        return

    await update_setting('force_channel', new_channel)
    await state.clear()
    kb = await get_admin_dashboard()
    await message.answer(f"✅ قفل کانال روی {hcode(new_channel)} تنظیم شد.", reply_markup=kb)

# --- ادمین: آمار ---


@admin_router.callback_query(F.data == "adm_stats")
async def admin_stats(callback: CallbackQuery):
    async with aiosqlite.connect(DB_NAME) as db:
        users_count = (await (await db.execute("SELECT COUNT(*) FROM users")).fetchone())[0]
        total_accounts = (await (await db.execute("SELECT COUNT(*) FROM apple_ids")).fetchone())[0]
        sold_accounts = (await (await db.execute("SELECT COUNT(*) FROM apple_ids WHERE status = 'sold'")).fetchone())[0]
        pending_orders = (await (await db.execute("SELECT COUNT(*) FROM orders WHERE status = 'pending'")).fetchone())[0]
        completed_orders = (await (await db.execute("SELECT COUNT(*) FROM orders WHERE status = 'completed'")).fetchone())[0]

    # محاسبه درآمد (ساده شده)
    # این بخش میتواند با join کردن قیمت زمان سفارش دقیق‌تر شود
    settings = await get_all_settings()
    price = int(settings.get('price', 0))
    recovery_price = int(settings.get('recovery_price', 0))

    async with aiosqlite.connect(DB_NAME) as db:
        income_new = (await (await db.execute("SELECT COUNT(*) FROM orders WHERE status = 'completed' AND type = 'new'")).fetchone())[0]
        income_recovery = (await (await db.execute("SELECT COUNT(*) FROM orders WHERE status = 'completed' AND type = 'recovery'")).fetchone())[0]

    total_income = (income_new * price) + (income_recovery * recovery_price)

    text = f"📊 {hbold('آمار ربات')}\n\n"
    text += f"👤 {hbold('تعداد کل کاربران')}: {users_count} نفر\n\n"
    text += f"--- {hbold('انبار')} ---\n"
    text += f"🍎 {hbold('کل اکانت‌های ثبت شده')}: {total_accounts}\n"
    text += f"🤝 {hbold('اکانت‌های تخصیص داده شده')}: {sold_accounts}\n\n"
    text += f"--- {hbold('سفارشات')} ---\n"
    text += f"⏳ {hbold('سفارشات در انتظار')}: {pending_orders}\n"
    text += f"✅ {hbold('سفارشات تکمیل شده')}: {completed_orders}\n\n"
    text += f"--- {hbold('مالی')} ---\n"
    text += f"💰 {hbold('درآمد تقریبی (بر اساس تنظیمات فعلی)')}: {total_income:,} تومان"

    await callback.message.edit_text(text, reply_markup=await get_admin_dashboard())
    await callback.answer()

# --- ادمین: هندلرهای مدیریت سفارش ---


@admin_router.callback_query(OrderManage.filter(F.action == 'reject'))
async def admin_reject_order(callback: CallbackQuery, callback_data: OrderManage, bot: Bot):
    order_id = callback_data.order_id
    user_id = callback_data.user_id

    async with aiosqlite.connect(DB_NAME) as db:
        await db.execute("UPDATE orders SET status = 'rejected' WHERE id = ?", (order_id,))
        await db.commit()

    # اطلاع به کاربر
    try:
        await bot.send_message(user_id, f"❌ سفارش شما با کد پیگیری #{order_id} متاسفانه تایید نشد.\n"
                               f"جهت پیگیری، لطفاً به پشتیبانی پیام دهید.")
    except Exception as e:
        logging.warning(f"Failed to send rejection message to {user_id}: {e}")

    # ادیت پیام ادمین
    new_caption = callback.message.caption + f"\n\n--- ❌ {hbold('رد شده')} ---"
    await callback.message.edit_caption(caption=new_caption, reply_markup=None)
    await callback.answer("سفارش رد شد.")


@admin_router.callback_query(OrderManage.filter(F.action == 'confirm_recovery'))
async def admin_confirm_recovery(callback: CallbackQuery, callback_data: OrderManage, bot: Bot):
    order_id = callback_data.order_id
    user_id = callback_data.user_id

    async with aiosqlite.connect(DB_NAME) as db:
        # واکشی شماره تلفن از سفارش
        async with db.execute("SELECT phone FROM orders WHERE id = ?", (order_id,)) as cursor:
            order_data = await cursor.fetchone()
            if not order_data:
                await callback.answer("❌ خطای سیستمی: سفارش یافت نشد.", show_alert=True)
                return

        customer_phone = order_data[0]

        # واکشی اطلاعات اپل آیدی
        query = "SELECT email, password, dob, security_questions FROM apple_ids WHERE customer_phone = ? AND status = 'sold'"
        async with db.execute(query, (customer_phone,)) as cursor:
            apple_id_data = await cursor.fetchone()

        if not apple_id_data:
            await callback.answer(f"❌ خطای سیستمی: اطلاعاتی برای شماره {customer_phone} یافت نشد.", show_alert=True)
            return

        # آپدیت وضعیت سفارش
        await db.execute("UPDATE orders SET status = 'completed' WHERE id = ?", (order_id,))
        await db.commit()

    email, password, dob, security_questions = apple_id_data

    # ارسال اطلاعات به کاربر
    text = f"✅ {hbold(f'سفارش ریکاوری #{order_id} تایید شد.')}\n\n"
    text += f"🔐 {hbold('اطلاعات بازیابی شده:')}\n\n"
    text += f"📧 {hbold('ایمیل')}: {hcode(email)}\n"
    text += f"🔑 {hbold('رمز عبور')}: {hcode(password)}\n"
    text += f"🎂 {hbold('تاریخ تولد (DOB)')}: {hcode(dob)}\n\n"
    text += f"{hbold('سوالات امنیتی:')}\n"
    # ⭐️ hquote به hblockquote تغییر کرد
    text += f"{hblockquote(escape(security_questions))}\n\n"
    text += "❗️ لطفاً این اطلاعات را در جای امنی ذخیره کنید."

    try:
        await bot.send_message(user_id, text)
    except Exception as e:
        await callback.answer(f"❌ ارسال به کاربر ناموفق بود: {e}", show_alert=True)
        # سفارش را برمیگردانیم (چون به دست کاربر نرسیده)
        async with aiosqlite.connect(DB_NAME) as db:
            await db.execute("UPDATE orders SET status = 'pending' WHERE id = ?", (order_id,))
            await db.commit()
        return

    # ادیت پیام ادمین
    new_caption = callback.message.caption + \
        f"\n\n--- ✅ {hbold('اطلاعات ریکاوری ارسال شد')} ---"
    await callback.message.edit_caption(caption=new_caption, reply_markup=None)
    await callback.answer("اطلاعات ریکاوری با موفقیت برای کاربر ارسال شد.")


# --- ادمین: FSM ارسال سفارش جدید ---
@admin_router.callback_query(OrderManage.filter(F.action == 'start_send'))
async def admin_start_send(callback: CallbackQuery, callback_data: OrderManage, state: FSMContext):
    await state.set_state(AdminSend.get_email)
    # ذخیره اطلاعات سفارش در FSM
    await state.update_data(
        order_id=callback_data.order_id,
        user_id=callback_data.user_id,
        admin_message_id=callback.message.message_id
    )
    # حذف دکمه‌ها از پیام فیش
    await callback.message.edit_reply_markup(reply_markup=None)
    await callback.message.answer(f"📦 {hbold(f'ارسال سفارش #{callback_data.order_id}')}\n\n"
                                  "1/6: ایمیل اپل آیدی را وارد کنید:")
    await callback.answer()


@admin_router.message(AdminSend.get_email)
async def admin_send_email(message: Message, state: FSMContext):
    await state.update_data(email=message.text)
    await state.set_state(AdminSend.get_pass)
    await message.answer("2/6: رمز عبور را وارد کنید:")


@admin_router.message(AdminSend.get_pass)
async def admin_send_pass(message: Message, state: FSMContext):
    await state.update_data(password=message.text)
    await state.set_state(AdminSend.get_sec_q1)
    await message.answer("3/6: سوال امنیتی ۱ (با جواب) را وارد کنید:")


@admin_router.message(AdminSend.get_sec_q1)
async def admin_send_q1(message: Message, state: FSMContext):
    await state.update_data(q1=message.text)
    await state.set_state(AdminSend.get_sec_q2)
    await message.answer("4/6: سوال امنیتی ۲ (با جواب) را وارد کنید:")


@admin_router.message(AdminSend.get_sec_q2)
async def admin_send_q2(message: Message, state: FSMContext):
    await state.update_data(q2=message.text)
    await state.set_state(AdminSend.get_sec_q3)
    await message.answer("5/6: سوال امنیتی ۳ (با جواب) را وارد کنید:")


@admin_router.message(AdminSend.get_sec_q3)
async def admin_send_q3(message: Message, state: FSMContext):
    await state.update_data(q3=message.text)
    await state.set_state(AdminSend.get_dob)
    await message.answer("6/6: تاریخ تولد (DOB) را وارد کنید (مثال: 1990-01-01):")


@admin_router.message(AdminSend.get_dob)
async def admin_send_dob(message: Message, state: FSMContext):
    await state.update_data(dob=message.text)
    data = await state.get_data()

    # نمایش پیش‌نمایش
    text = f"🚨 {hbold('پیش‌نمایش ارسال')}\n\n"
    text += f"📧 {hbold('ایمیل')}: {hcode(data['email'])}\n"
    text += f"🔑 {hbold('رمز عبور')}: {hcode(data['password'])}\n"
    text += f"🎂 {hbold('تاریخ تولد')}: {hcode(data['dob'])}\n"
    text += f"❓ {hbold('سوال ۱')}: {escape(data['q1'])}\n"
    text += f"❓ {hbold('سوال ۲')}: {escape(data['q2'])}\n"
    text += f"❓ {hbold('سوال ۳')}: {escape(data['q3'])}\n\n"
    text += f"این اطلاعات برای کاربر {hcode(data['user_id'])} (سفارش #{data['order_id']}) ارسال خواهد شد. {hbold('تایید می‌کنید؟')}"

    builder = InlineKeyboardBuilder()
    builder.row(InlineKeyboardButton(
        text="✅ بله، ارسال شود", callback_data="send_confirm"))
    builder.row(InlineKeyboardButton(
        text="❌ لغو و شروع مجدد", callback_data="send_cancel"))

    await state.set_state(AdminSend.confirm_send)
    await message.answer(text, reply_markup=builder.as_markup())


@admin_router.callback_query(AdminSend.confirm_send, F.data == "send_cancel")
async def admin_send_cancel(callback: CallbackQuery, state: FSMContext):
    await state.set_state(AdminSend.get_email)
    await callback.message.edit_text("عملیات لغو شد. لطفاً از ابتدا وارد کنید:\n1/6: ایمیل اپل آیدی را وارد کنید:")
    await callback.answer()


@admin_router.callback_query(AdminSend.confirm_send, F.data == "send_confirm")
async def admin_send_confirm(callback: CallbackQuery, state: FSMContext, bot: Bot):
    data = await state.get_data()
    order_id = data['order_id']
    user_id = data['user_id']
    admin_message_id = data['admin_message_id']

    await callback.message.edit_text("⏳ در حال ارسال اطلاعات به کاربر و ذخیره‌سازی...")

    security_questions = (
        f"Q1: {data['q1']}\n"
        f"Q2: {data['q2']}\n"
        f"Q3: {data['q3']}"
    )

    customer_phone = ""

    async with aiosqlite.connect(DB_NAME) as db:
        # واکشی شماره تلفن از سفارش
        async with db.execute("SELECT phone FROM orders WHERE id = ?", (order_id,)) as cursor:
            order_data = await cursor.fetchone()
            if not order_data:
                await callback.message.edit_text("❌ خطای سیستمی: سفارش یافت نشد.")
                await state.clear()
                return
        customer_phone = order_data[0]

        # ثبت اپل آیدی جدید در انبار به عنوان 'فروخته شده'
        await db.execute(
            """
            INSERT INTO apple_ids (email, password, dob, security_questions, customer_phone, status)
            VALUES (?, ?, ?, ?, ?, 'sold')
            """,
            (
                data['email'],
                data['password'],
                data['dob'],
                security_questions,
                customer_phone
            )
        )

        # آپدیت وضعیت سفارش
        await db.execute("UPDATE orders SET status = 'completed' WHERE id = ?", (order_id,))
        await db.commit()

    # ارسال اطلاعات به کاربر
    text_to_user = f"✅ {hbold(f'سفارش خرید #{order_id} تایید و تکمیل شد.')}\n\n"
    text_to_user += f"🔐 {hbold('اطلاعات اپل آیدی شما:')}\n\n"
    text_to_user += f"📧 {hbold('ایمیل')}: {hcode(data['email'])}\n"
    text_to_user += f"🔑 {hbold('رمز عبور')}: {hcode(data['password'])}\n"
    text_to_user += f"🎂 {hbold('تاریخ تولد (DOB)')}: {hcode(data['dob'])}\n\n"
    text_to_user += f"{hbold('سوالات امنیتی:')}\n"
    # ⭐️ hquote به hblockquote تغییر کرد
    text_to_user += f"{hblockquote(escape(security_questions))}\n\n"
    text_to_user += f"❗️ لطفاً این اطلاعات را در جای امنی ذخیره کنید و {hbold('رمز عبور و سوالات امنیتی را در اسرع وقت تغییر دهید.')}"

    try:
        await bot.send_message(user_id, text_to_user)
    except Exception as e:
        await callback.message.answer(f"❌ ارسال به کاربر ناموفق بود: {e}\n"
                                      f"اما اطلاعات در دیتابیس (برای ریکاوری) ذخیره شد.")
        # سفارش را برمیگردانیم (چون به دست کاربر نرسیده)
        async with aiosqlite.connect(DB_NAME) as db:
            await db.execute("UPDATE orders SET status = 'pending' WHERE id = ?", (order_id,))
            await db.commit()
        await state.clear()
        return

    # ادیت پیام فیش اصلی ادمین
    try:
        # ابتدا کپشن فعلی را بگیریم (اگر وجود دارد)
        current_caption = ""
        if callback.message.caption:
            current_caption = callback.message.caption
        elif 'admin_message_id' in data:
            # اگر پیام اصلی نبود، سعی کن از آبجکت پیام ذخیره شده بگیری
            # این بخش ممکن است نیاز به دریافت آبجکت پیام داشته باشد
            # برای سادگی، فعلا فقط روی پیام فعلی کار میکنیم
            # اگر پیام فعلی کپشن نداشت (یعنی پیام "در حال ارسال" بود)
            # باید پیام اصلی را ادیت کنیم

            # پیدا کردن پیام اصلی (فیش)
            original_message = await bot.edit_message_caption(
                chat_id=ADMIN_ID,
                message_id=admin_message_id,
                # موقتا ست میکنیم
                caption=f"--- ✅ {hbold('اطلاعات با موفقیت ارسال شد')} ---"
            )

            if original_message.caption and original_message.caption != f"--- ✅ {hbold('اطلاعات با موفقیت ارسال شد')} ---":
                # اگر کپشن قبلی وجود داشت، آن را اضافه میکنیم
                await bot.edit_message_caption(
                    chat_id=ADMIN_ID,
                    message_id=admin_message_id,
                    caption=original_message.caption.replace(
                        f"--- ✅ {hbold('اطلاعات با موفقیت ارسال شد')} ---", "") + f"\n\n--- ✅ {hbold('اطلاعات با موفقیت ارسال شد')} ---"
                )

            await state.clear()
            kb = await get_admin_dashboard()
            await callback.message.answer("✅ اطلاعات با موفقیت برای کاربر ارسال و در دیتابیس ذخیره شد.", reply_markup=kb)
            await callback.answer()
            return  # چون پیام اصلی را ادیت کردیم، خارج میشویم

        # اگر کد به اینجا رسید یعنی روی پیام فیش هستیم
        if current_caption:
            await bot.edit_message_caption(
                chat_id=ADMIN_ID,
                message_id=callback.message.message_id,
                caption=current_caption +
                f"\n\n--- ✅ {hbold('اطلاعات با موفقیت ارسال شد')} ---"
            )

    except Exception as e:
        logging.warning(f"Could not edit admin message: {e}")

    await state.clear()
    kb = await get_admin_dashboard()
    await callback.message.answer("✅ اطلاعات با موفقیت برای کاربر ارسال و در دیتابیس ذخیره شد.", reply_markup=kb)
    await callback.answer()


# --- ادمین: FSM پاسخ به کاربر ---
@admin_router.callback_query(ReplyToUser.filter())
async def admin_reply_start(callback: CallbackQuery, callback_data: ReplyToUser, state: FSMContext):
    await state.set_state(AdminReply.wait_reply)
    await state.update_data(user_id=callback_data.user_id)
    await callback.message.answer(f"↩️ در حال پاسخ به کاربر {hcode(callback_data.user_id)}...\n"
                                  "پیام خود را بنویسید:")
    await callback.answer()


@admin_router.message(AdminReply.wait_reply)
async def admin_reply_send(message: Message, state: FSMContext, bot: Bot):
    data = await state.get_data()
    user_id = data['user_id']

    try:
        # ارسال پیام ادمین به کاربر
        text_to_user = f"👨‍💻 {hbold('پاسخ پشتیبانی')}:\n\n" + message.text
        await bot.send_message(user_id, text_to_user)

        # اطلاع به ادمین
        await message.answer("✅ پاسخ شما با موفقیت ارسال شد.")

    except Exception as e:
        await message.answer(f"❌ خطایی در ارسال پیام به کاربر {user_id} رخ داد: {e}")

    finally:
        await state.clear()

# --- 🚀 تابع اصلی اجرای ربات ---


async def main():
    # تنظیم لاگ‌ها
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
    )

    # 1. ساخت دیتابیس
    await init_db()

    # ⭐️ --- تنظیم سرور محلی (Local Bot API) --- ⭐️
    # اگر از سرور محلی (برای دور زدن فیلترینگ) استفاده می‌کنید،
    # این بخش را از کامنت خارج کنید و آدرس سرور خود را تنظیم کنید.
    #
    # ❗️ آدرس سرور محلی خود را اینجا بگذارید
    #LOCAL_SERVER_URL = "http://127.0.0.1:12334"
    #custom_server = TelegramAPIServer.from_base(LOCAL_SERVER_URL)
    #custom_session = AiohttpSession(api=custom_server)
    # -------------------------------------------------

    # 2. ساخت آبجکت‌های Bot و Dispatcher
    # استفاده از ParseMode.HTML به عنوان پیش‌فرض
    bot = Bot(
        token=BOT_TOKEN,
        default=DefaultBotProperties(parse_mode=ParseMode.HTML)
        # ⭐️ اگر از سرور محلی استفاده می‌کنید، خط زیر را هم از کامنت خارج کنید
        # session=custom_session
    )
    # استفاده از MemoryStorage برای FSM (برای سادگی در تک فایل)
    storage = MemoryStorage()
    dp = Dispatcher(storage=storage)

    # 3. ثبت میدل‌ور قفل کانال
    # میدل‌ور را به روتر اصلی کاربر متصل میکنیم
    user_router.message.filter(ChannelJoinMiddleware(bot))
    user_router.callback_query.filter(ChannelJoinMiddleware(bot))

    # 4. ثبت روترها
    # ابتدا روتر ادمین (که فیلتر ID دارد)
    dp.include_router(admin_router)
    # سپس روتر کاربر (که میدل‌ور قفل کانال دارد)
    dp.include_router(user_router)

    # ثبت هندلر بازگشت عمومی در سطح Dispatcher
    @dp.message(StateFilter("*"), F.text == "🔙 بازگشت")
    async def global_back_handler(message: Message, state: FSMContext):
        current_state = await state.get_state()
        if current_state is None:
            await message.answer("شما در منوی اصلی هستید.", reply_markup=get_main_menu())
            return

        logging.info(
            f"Cancelling state {current_state} for {message.from_user.id}")
        await state.clear()
        await message.answer("عملیات لغو شد. به منوی اصلی بازگشتید.", reply_markup=get_main_menu())

    # 5. اجرای ربات
    logging.info("Starting bot polling...")
    await bot.delete_webhook(drop_pending_updates=True)
    await dp.start_polling(bot)


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        logging.info("Bot stopped by user")
