import asyncio
import os
import json
#import sqlite3
import sys
import random
import zipfile, shutil
from datetime import datetime
from typing import List, Dict, Optional, Tuple, Any

from balecore import Bot
from balecore.updates import Message, CallbackQuery
from balecore.keyboards import InlineKeyboardButton, InlineKeyboardMarkup
from aiobale import Client, Dispatcher

# ==================== CONSTANTS ====================
TOKEN = "Token"
OWNER_IDS = [Admins]

PANEL_DATA_FILE = "data/panel.json"
ADMINS_FILE = "data/admins.json"
SESSIONS_DIR = "sessions"
ACC_DIR = "acc"

# ==================== PANEL MANAGER ====================
class PanelManager:
    """مدیریت تنظیمات پنل"""
    
    def __init__(self, config_file: str = PANEL_DATA_FILE):
        self.config_file = config_file
        self.default_config = {"delay": 3}
        
        # ایجاد پوشه data اگر وجود نداشت
        os.makedirs(os.path.dirname(config_file), exist_ok=True)
        
        # ایجاد فایل panel.json اگر وجود نداشت
        if not os.path.exists(config_file):
            with open(config_file, "w", encoding="utf-8") as f:
                json.dump(self.default_config, f, indent=4)
    

    def get_delay_name(self, delay: float) -> str:
        """تبدیل مقدار تاخیر به اسم مربوطه"""
        if delay <= 1.0:
            return "🔥 سوپر سریع"
        elif delay <= 1.8:
            return "⚡ خیلی سریع"
        elif delay <= 3.0:
            return "📎 سریع"
        elif delay <= 10:
            return "⏱ معمولی"
        elif delay <= 20:
            return "🐢 کند"
        else:
            return "🛡 امن"

    async def load_data(self) -> Dict[str, Any]:
        """بارگذاری تنظیمات"""
        with open(self.config_file, "r", encoding="utf-8") as f:
            return json.load(f)
    
    async def _save_data(self, data: Dict[str, Any]) -> None:
        """ذخیره تنظیمات"""
        with open(self.config_file, "w", encoding="utf-8") as f:
            json.dump(data, f, indent=4)
    
    async def update(self, key: str, value: Any) -> None:
        """به‌روزرسانی یک تنظیم"""
        data = await self.load_data()
        data[key] = value
        await self._save_data(data)
    
    async def get_delay(self) -> float:
        """دریافت تاخیر"""
        data = await self.load_data()
        return float(data.get("delay", 3))

# ==================== ADMIN MANAGER ====================
class AdminManager:
    """مدیریت ادمین‌ها"""
    
    def __init__(self, admins_file: str = ADMINS_FILE):
        self.admins_file = admins_file
        os.makedirs(os.path.dirname(admins_file), exist_ok=True)
        
        if not os.path.exists(admins_file):
            with open(admins_file, "w", encoding="utf-8") as f:
                json.dump([], f, indent=4)
    
    async def load_admins(self) -> List[int]:
        """بارگذاری لیست ادمین‌ها"""
        with open(self.admins_file, "r", encoding="utf-8") as f:
            return json.load(f)
    
    async def save_admins(self, admins: List[int]) -> None:
        """ذخیره لیست ادمین‌ها"""
        with open(self.admins_file, "w", encoding="utf-8") as f:
            json.dump(admins, f, indent=4)
    
    async def is_owner(self, user_id: int) -> bool:
        """بررسی مالک بودن"""
        return user_id in OWNER_IDS
    
    async def is_admin(self, user_id: int) -> bool:
        """بررسی ادمین بودن"""
        admins = await self.load_admins()
        return user_id in admins or user_id in OWNER_IDS
    
    async def add_admin(self, user_id: int) -> bool:
        """افزودن ادمین"""
        if user_id in OWNER_IDS:
            return False
        admins = await self.load_admins()
        if user_id not in admins:
            admins.append(user_id)
            await self.save_admins(admins)
            return True
        return False
    
    async def remove_admin(self, user_id: int) -> bool:
        """حذف ادمین"""
        admins = await self.load_admins()
        if user_id in admins:
            admins.remove(user_id)
            await self.save_admins(admins)
            return True
        return False
    
    async def get_admins_list(self) -> List[int]:
        """دریافت لیست ادمین‌ها"""
        return await self.load_admins()

# ==================== SESSION MANAGER ====================
class SessionManager:
    """مدیریت سشن‌ها در پوشه acc"""
    
    def __init__(self):
        self.sessions_dir = "acc"  # فقط پوشه acc
        os.makedirs(self.sessions_dir, exist_ok=True)
    
    def get_all_sessions(self) -> List[str]:
        """دریافت لیست تمام سشن‌ها"""
        if not os.path.exists(self.sessions_dir):
            return []
        return [f for f in os.listdir(self.sessions_dir) if f.endswith('.bale')]
    

    async def get_available_sessions(self, count: int) -> List[str]:
        """دریافت تعداد مشخصی سشن"""
        all_sessions = self.get_all_sessions()
        return all_sessions[:count]
    
    def get_sessions_count(self) -> int:
        """تعداد کل سشن‌ها"""
        return len(self.get_all_sessions())
    
    def delete_session(self, session_file: str) -> bool:
        """حذف یک سشن"""
        try:
            session_path = os.path.join(self.sessions_dir, session_file)
            os.remove(session_path)
            return True
        except Exception:
            return False
    
    async def validate_session(self, session_file: str) -> Tuple[bool, Optional[int]]:
        """بررسی اعتبار یک سشن"""
        try:
            dp = Dispatcher()
            client = Client(dp, session_file=os.path.join(self.sessions_dir, session_file))
            await asyncio.wait_for(client.start(), timeout=12)
            me = await client.get_me()
            user_id = me.id
            await client.stop()
            return True, user_id
        except Exception:
            return False, None
    
    async def execute_join(self, session_file: str, link: str) -> bool:
        """اجرای عملیات جوین با یک سشن"""
        try:
            dp = Dispatcher()
            client = Client(dp, session_file=os.path.join(self.sessions_dir, session_file))
            await client.join_chat(link)
            await client.stop()
            return True
        except Exception:
            return False
    
    async def execute_leave(self, session_file: str, link: str) -> bool:
        """اجرای عملیات لفت با یک سشن"""
        try:
            dp = Dispatcher()
            client = Client(dp, session_file=os.path.join(self.sessions_dir, session_file))
            await client.leave_group(link)
            await client.stop()
            return True
        except Exception:
            return False


# ==================== UI COMPONENTS ====================
class UIBuilder:
    """ساخت رابط کاربری"""
    
    @staticmethod
    def main_menu(delay_name: str, sessions_count: int, is_owner: bool = False) -> Tuple[str, InlineKeyboardMarkup]:
        """منوی اصلی"""
        keyboard = InlineKeyboardMarkup()

        # دکمه جوین برای همه (ادمین و مالک)
        keyboard.add_row(InlineKeyboardButton("✅ جوین کردن", callback_data="admember_join_menu"))

        # دکمه‌های زیر فقط برای مالک
        if is_owner:
            keyboard.add_row(InlineKeyboardButton(f"⏱ تاخیر : {delay_name}", callback_data="admember_delay"))
            keyboard.add_row(InlineKeyboardButton("🚪 لفت دادن", callback_data="admember_leave_menu"))
            keyboard.add_row(InlineKeyboardButton("🔄 بررسی سشن‌ها", callback_data="admember_check_sessions"))
            keyboard.add_row(InlineKeyboardButton("👥 مدیریت ادمین‌ها", callback_data="admember_manage_admins"))
            keyboard.add_row(InlineKeyboardButton("🔄 ترتیب", callback_data="admember_reorder"))
            keyboard.add_row(InlineKeyboardButton("📦 بکاپ", callback_data="admember_backup"))  # اضافه کن

        text = f"🤖 *پنل مدیریت ممبر*\n\n📊 آمار:\n• کل سشن‌ها: {sessions_count}\n"

        return text, keyboard
    
    @staticmethod
    def delay_menu() -> Tuple[str, InlineKeyboardMarkup]:
        """منوی تنظیم تاخیر با 6 سرعت مختلف"""
        keyboard = InlineKeyboardMarkup()
        keyboard.add_row(
            InlineKeyboardButton("🔥 سوپر سریع", callback_data="admember_set_delay_0.9"),
            InlineKeyboardButton("⚡ خیلی سریع", callback_data="admember_set_delay_1.5")
        )
        keyboard.add_row(
            InlineKeyboardButton("📎 سریع", callback_data="admember_set_delay_2.5"),
            InlineKeyboardButton("⏱ معمولی", callback_data="admember_set_delay_7")
        )
        keyboard.add_row(
            InlineKeyboardButton("🐢 کند", callback_data="admember_set_delay_15"),
            InlineKeyboardButton("🛡 امن", callback_data="admember_set_delay_30")
        )
        keyboard.add_row(InlineKeyboardButton("🔙 بازگشت", callback_data="admember_back"))
        
        text = (
            "*⏱ تنظیم سرعت عملیات:*\n\n"
            "🔥 **سوپر سریع** → 1.5-5 ثانیه\n"
            "⚡ **خیلی سریع** → 5-10 ثانیه\n"
            "📎 **سریع** → 10-20 ثانیه\n"
            "⏱ **معمولی** → 20-30 ثانیه\n"
            "🐢 **کند** → 30-50 ثانیه\n"
            "🛡 **امن** → 50-100 ثانیه\n\n"
            "⚠️ تاخیر بین هر عملیات به صورت **رندوم** در بازه مشخص شده است.\n"
            "✅ هر دسته شامل 50 سشن همزمان"
        )
        
        return text, keyboard
    
    @staticmethod
    def back_button() -> InlineKeyboardMarkup:
        """دکمه بازگشت"""
        keyboard = InlineKeyboardMarkup()
        keyboard.add_row(InlineKeyboardButton("🔙 بازگشت", callback_data="admember_back"))
        return keyboard
    
    @staticmethod
    def manage_admins_menu(admins: List[int]) -> Tuple[str, InlineKeyboardMarkup]:
        """منوی مدیریت ادمین‌ها"""
        keyboard = InlineKeyboardMarkup()
        keyboard.add_row(InlineKeyboardButton("➕ افزودن ادمین", callback_data="admember_add_admin"))
        keyboard.add_row(InlineKeyboardButton("➖ حذف ادمین", callback_data="admember_remove_admin"))
        keyboard.add_row(InlineKeyboardButton("📋 لیست ادمین‌ها", callback_data="admember_list_admins"))
        keyboard.add_row(InlineKeyboardButton("🔙 بازگشت", callback_data="admember_back"))
        
        text = f"👥 *مدیریت ادمین‌ها*\n\nتعداد ادمین‌ها: {len(admins)}\n\nمالک‌های اصلی دسترسی کامل دارند."
        
        return text, keyboard

# ==================== MAIN MANAGER ====================
class AdMemberManager:
    """مدیریت اصلی اد ممبر"""
    
    def __init__(self, bot: Bot):
        self.bot = bot
        self.panel = PanelManager()
        self.sessions = SessionManager()
        self.ui = UIBuilder()
        self.admin_manager = AdminManager()
        self.pending_admin = {}
        self.pending_join = {}
        self.pending_leave = {}
        self.acc_dir = "acc"
        os.makedirs(self.acc_dir, exist_ok=True)
    
        # ========== مدیریت همزمانی ==========
        self.active_operations = 0  # تعداد عملیات سنگین در حال اجرا (جوین/لفت)
        self.max_operations = 4     # حداکثر عملیات همزمان
        self.is_checking = False    # بررسی در حال اجراست؟
        self.operation_lock = asyncio.Lock()  # قفل برای تغییرات اتمیک
    
    async def can_start_operation(self, op_type: str) -> Tuple[bool, str]:
        """
        بررسی مجاز بودن شروع عملیات
        returns: (مجاز است?, پیام خطا)
        """
        async with self.operation_lock:
            # عملیات بررسی انحصاری است
            if self.is_checking:
                return False, "🔴 *عملیات مهم در حال انجام است!*\n\nربات در حال بررسی سشن‌ها می‌باشد.\nلطفاً چند دقیقه دیگر امتحان کنید."
            
            # جوین/لفت محدودیت 4 تایی دارند
            if op_type in ["join", "leave"]:
                if self.active_operations >= self.max_operations:
                    return False, f"⏳ *ربات مشغول است!*\n\nدر حال حاضر {self.max_operations} عملیات همزمان در حال اجراست.\nلطفاً چند دقیقه دیگر امتحان کنید."
                return True, ""
            
            # ترتیب و بکاپ و بررسی در جای دیگر بررسی می‌شوند
            return True, ""

    async def start_operation(self, op_type: str):
        """شروع عملیات (افزایش شمارنده)"""
        async with self.operation_lock:
            if op_type in ["join", "leave"]:
                self.active_operations += 1

    async def finish_operation(self, op_type: str):
        """پایان عملیات (کاهش شمارنده)"""
        async with self.operation_lock:
            if op_type in ["join", "leave"]:
                self.active_operations -= 1

    async def start_checking(self):
        """شروع عملیات بررسی (انحصاری)"""
        async with self.operation_lock:
            self.is_checking = True

    async def finish_checking(self):
        """پایان عملیات بررسی"""
        async with self.operation_lock:
            self.is_checking = False

    # ========== CALLBACK HANDLERS ==========
    async def handle_callback(self, callback_query: CallbackQuery) -> None:
        """مدیریت کلیه callbackها"""
        data = callback_query.data
        chat_id = callback_query.message.chat.id
        message_id = callback_query.message.message_id
        
        handlers = {
            "admember_reorder": self._handle_reorder,
            "admember_start": self._handle_start,
            "admember_delay": self._handle_delay_menu,
            "admember_join_menu": self._handle_join_menu,
            "admember_leave_menu": self._handle_leave_menu,
            "admember_check_sessions": self._handle_check_sessions,
            "admember_back": self._handle_back,
            "admember_manage_admins": self._handle_manage_admins,
            "admember_add_admin": self._handle_add_admin,
            "admember_remove_admin": self._handle_remove_admin,
            "admember_list_admins": self._handle_list_admins,
            "admember_backup": self._handle_backup,
        }
        
        if data.startswith("admember_set_delay_"):
            await self._handle_set_delay(callback_query, chat_id, message_id)
        elif data in handlers:
            await self.bot.answer_callback_query(callback_query.id)
            if data == "admember_reorder":
                await self._handle_reorder(chat_id, message_id, callback_query.id)
            elif data == "admember_backup":
                await self._handle_backup(chat_id, message_id, callback_query.id)
            else:
                await handlers[data](chat_id, message_id)
    
    async def _handle_manage_admins(self, chat_id: int, message_id: int) -> None:
        """مدیریت ادمین‌ها"""
        if not await self.admin_manager.is_owner(chat_id):
            await self.bot.answer_callback_query(message_id, "❌ فقط مالک دسترسی دارد!")
            return
        
        admins = await self.admin_manager.get_admins_list()
        text, keyboard = self.ui.manage_admins_menu(admins)
        await self.bot.edit_message_text(
            chat_id=chat_id,
            message_id=message_id,
            text=text,
            reply_markup=keyboard
        )
    
    async def _handle_add_admin(self, chat_id: int, message_id: int) -> None:
        """درخواست افزودن ادمین"""
        if not await self.admin_manager.is_owner(chat_id):
            await self.bot.answer_callback_query(message_id, "❌ فقط مالک دسترسی دارد!")
            return
        
        self.pending_admin[chat_id] = "add"
        keyboard = InlineKeyboardMarkup()
        keyboard.add_row(InlineKeyboardButton("🔙 انصراف", callback_data="admember_manage_admins"))
        
        await self.bot.edit_message_text(
            chat_id=chat_id,
            message_id=message_id,
            text="➕ *افزودن ادمین*\n\nلطفاً آیدی عددی ادمین را ارسال کنید:",
            reply_markup=keyboard
        )
    
    async def _handle_remove_admin(self, chat_id: int, message_id: int) -> None:
        """درخواست حذف ادمین"""
        if not await self.admin_manager.is_owner(chat_id):
            await self.bot.answer_callback_query(message_id, "❌ فقط مالک دسترسی دارد!")
            return
        
        self.pending_admin[chat_id] = "remove"
        keyboard = InlineKeyboardMarkup()
        keyboard.add_row(InlineKeyboardButton("🔙 انصراف", callback_data="admember_manage_admins"))
        
        await self.bot.edit_message_text(
            chat_id=chat_id,
            message_id=message_id,
            text="➖ *حذف ادمین*\n\nلطفاً آیدی عددی ادمین را ارسال کنید:",
            reply_markup=keyboard
        )
    
    async def _handle_list_admins(self, chat_id: int, message_id: int) -> None:
        """نمایش لیست ادمین‌ها"""
        if not await self.admin_manager.is_owner(chat_id):
            await self.bot.answer_callback_query(message_id, "❌ فقط مالک دسترسی دارد!")
            return
        
        admins = await self.admin_manager.get_admins_list()
        owners = OWNER_IDS
        
        text = "👥 *لیست کاربران*\n\n"
        text += "👑 *مالک‌های اصلی:*\n"
        for owner in owners:
            text += f"• `{owner}`\n"
        
        text += f"\n👤 *ادمین‌ها:*\n"
        if admins:
            for admin in admins:
                text += f"• `{admin}`\n"
        else:
            text += "• هیچ ادمینی وجود ندارد\n"
        
        keyboard = InlineKeyboardMarkup()
        keyboard.add_row(InlineKeyboardButton("🔙 بازگشت", callback_data="admember_manage_admins"))
        
        await self.bot.edit_message_text(
            chat_id=chat_id,
            message_id=message_id,
            text=text,
            reply_markup=keyboard
        )

    async def _handle_reorder(self, chat_id: int, message_id: int, callback_query_id: str = None) -> None:
        """مرتب کردن سشن‌های پوشه acc و حذف فایل‌های غیر bale"""
        
        # بررسی اینکه عملیات بررسی در حال اجرا نباشد
        if self.is_checking:
            if callback_query_id:
                await self.bot.answer_callback_query(callback_query_id, "🔴 عملیات مهم در حال انجام است!", show_alert=True)
            else:
                await self.bot.send_message(chat_id, "🔴 عملیات مهم در حال انجام است!\nلطفاً چند دقیقه دیگر امتحان کنید.")
            return
        
        if not await self.admin_manager.is_owner(chat_id):
            if callback_query_id:
                await self.bot.answer_callback_query(callback_query_id, "❌ فقط مالک دسترسی دارد!")
            return
        
        if callback_query_id:
            await self.bot.answer_callback_query(callback_query_id, "🔄 در حال مرتب‌سازی...")
        
        # پاک کردن فایل‌های غیر bale
        deleted_count = 0
        for f in os.listdir(self.acc_dir):
            if not f.endswith('.bale'):
                try:
                    os.remove(os.path.join(self.acc_dir, f))
                    deleted_count += 1
                except:
                    pass
        
        # گرفتن فقط فایل‌های bale
        files = [f for f in os.listdir(self.acc_dir) if f.endswith('.bale')]
        
        if not files:
            await self.bot.send_message(chat_id, "📂 هیچ سشنی وجود ندارد!")
            await self._show_main_menu(chat_id, message_id)
            return
        
        # مرتب‌سازی بر اساس شماره
        def extract_number(name):
            try:
                return int(name.split('.')[0])
            except:
                return 999999
        
        files.sort(key=extract_number)
        
        # تغییر نام به 1.bale, 2.bale, ...
        renamed_count = 0
        for i, old_name in enumerate(files, 1):
            old_path = os.path.join(self.acc_dir, old_name)
            new_path = os.path.join(self.acc_dir, f"{i}.bale")
            if old_path != new_path:
                os.rename(old_path, new_path)
                renamed_count += 1
        
        msg_text = f"✅ {len(files)} سشن مرتب شدند!"
        if deleted_count > 0:
            msg_text += f"\n🗑 {deleted_count} فایل غیرمجاز حذف شد"
        if renamed_count > 0:
            msg_text += f"\n🔄 {renamed_count} فایل تغییر نام یافت"
        
        await self.bot.send_message(chat_id, msg_text)
        await self._show_main_menu(chat_id, message_id)
    
    async def _handle_backup(self, chat_id: int, message_id: int, callback_query_id: str = None) -> None:
        """ساخت بکاپ از پوشه acc و ارسال برای ادمین"""
        
        # بررسی اینکه عملیات بررسی در حال اجرا نباشد
        if self.is_checking:
            if callback_query_id:
                await self.bot.answer_callback_query(callback_query_id, "🔴 عملیات مهم در حال انجام است!", show_alert=True)
            else:
                await self.bot.send_message(chat_id, "🔴 عملیات مهم در حال انجام است!\nلطفاً چند دقیقه دیگر امتحان کنید.")
            return
        
        if not await self.admin_manager.is_owner(chat_id):
            if callback_query_id:
                await self.bot.answer_callback_query(callback_query_id, "❌ فقط مالک دسترسی دارد!")
            return
        
        if callback_query_id:
            await self.bot.answer_callback_query(callback_query_id, "📦 در حال ساخت بکاپ...")
        
        # ارسال پیام وضعیت
        status_msg = await self.bot.send_message(
            chat_id=chat_id,
            text="🔄 *در حال تهیه بکاپ...*\n\n⏳ لطفاً صبر کنید..."
        )
        
        # دریافت لیست فایل‌های .bale از پوشه acc
        bale_files = [f for f in os.listdir(self.acc_dir) if f.endswith('.bale')]
        
        if not bale_files:
            await self.bot.edit_message_text(
                chat_id=chat_id,
                message_id=status_msg.message_id,
                text="📂 *هیچ فایل سشنی برای بکاپ وجود ندارد!*"
            )
            await self._show_main_menu(chat_id, message_id)
            return
        
        # ساخت فایل زیپ
        now = datetime.now().strftime("%Y%m%d_%H%M%S")
        zip_name = f"backup_acc_{now}.zip"
        
        # ذخیره مسیر فعلی
        original_dir = os.getcwd()
        
        try:
            # به‌روزرسانی پیام
            await self.bot.edit_message_text(
                chat_id=chat_id,
                message_id=status_msg.message_id,
                text=f"🔄 *در حال فشرده‌سازی {len(bale_files)} فایل...*\n\n⏳ این عملیات چند لحظه طول می‌کشد..."
            )
            
            # رفتن به پوشه acc
            os.chdir(self.acc_dir)
            
            # ساخت فایل زیپ
            with zipfile.ZipFile(os.path.join(original_dir, zip_name), "w", zipfile.ZIP_DEFLATED) as zf:
                for f in bale_files:
                    zf.write(f)
            
            # برگشت به مسیر اصلی
            os.chdir(original_dir)
            
            # به‌روزرسانی پیام
            await self.bot.edit_message_text(
                chat_id=chat_id,
                message_id=status_msg.message_id,
                text="📤 *در حال ارسال فایل بکاپ...*"
            )
            
            # ارسال فایل برای ادمین
            await self.bot.send_document(
                chat_id=chat_id,
                document=zip_name,
                caption=f"📦 *بکاپ سشن‌ها*\n\n📅 تاریخ: {datetime.now().strftime('%Y/%m/%d %H:%M:%S')}\n📁 تعداد فایل‌ها: {len(bale_files)}"
            )
            
            # حذف فایل زیپ موقت
            os.remove(zip_name)
            
            # حذف پیام وضعیت
            await self.bot.delete_message(chat_id=chat_id, message_id=status_msg.message_id)
            
            await self.bot.send_message(chat_id, f"✅ بکاپ با موفقیت ساخته و ارسال شد!\n📁 تعداد فایل‌ها: {len(bale_files)}")
            
        except Exception as e:
            os.chdir(original_dir)
            await self.bot.edit_message_text(
                chat_id=chat_id,
                message_id=status_msg.message_id,
                text=f"❌ *خطا در ساخت بکاپ:*\n`{e}`"
            )
        
        await self._show_main_menu(chat_id, message_id)

    async def process_admin_action(self, chat_id: int, user_id_str: str) -> None:
        """پردازش افزودن/حذف ادمین"""
        action = self.pending_admin.get(chat_id)
        if not action:
            return
        
        try:
            target_id = int(user_id_str)
            
            if action == "add":
                if target_id in OWNER_IDS:
                    await self.bot.send_message(chat_id, "❌ این کاربر مالک اصلی است!")
                elif await self.admin_manager.add_admin(target_id):
                    await self.bot.send_message(chat_id, f"✅ ادمین `{target_id}` اضافه شد!")
                else:
                    await self.bot.send_message(chat_id, "❌ این کاربر قبلاً ادمین است!")
            
            elif action == "remove":
                if target_id in OWNER_IDS:
                    await self.bot.send_message(chat_id, "❌ نمی‌توانید مالک را حذف کنید!")
                elif await self.admin_manager.remove_admin(target_id):
                    await self.bot.send_message(chat_id, f"✅ ادمین `{target_id}` حذف شد!")
                else:
                    await self.bot.send_message(chat_id, "❌ این کاربر ادمین نیست!")
        
        except ValueError:
            await self.bot.send_message(chat_id, "❌ آیدی نامعتبر!")
        
        self.pending_admin.pop(chat_id, None)
        await self._show_main_menu(chat_id)
    
    async def process_join_conversation(self, chat_id: int, text: str) -> None:
        """پردازش گفتگوی جوین"""
        state = self.pending_join.get(chat_id)
        if not state:
            return
        
        if state["step"] == "waiting_for_link":
            # ذخیره لینک و رفتن به مرحله بعد
            self.pending_join[chat_id]["link"] = text
            self.pending_join[chat_id]["step"] = "waiting_for_count"
            
            keyboard = InlineKeyboardMarkup()
            keyboard.add_row(InlineKeyboardButton("🔙 انصراف", callback_data="admember_back"))
            
            await self.bot.send_message(
                chat_id=chat_id,
                text="🔢 *لطفاً تعداد سشن‌ها را وارد کنید:*\n\nمثال: `10`\n(سشن‌های 1 تا 10 استفاده می‌شوند)",
                reply_markup=keyboard
            )
        
        elif state["step"] == "waiting_for_count":
            try:
                count = int(text.strip())
                if count <= 0:
                    raise ValueError
            except:
                await self.bot.send_message(chat_id, "❌ لطفاً یک عدد معتبر وارد کنید!")
                return
            
            link = state["link"]
            
            # بررسی مجاز بودن قبل از شروع عملیات
            allowed, msg = await self.can_start_operation("join")
            if not allowed:
                del self.pending_join[chat_id]
                await self.bot.send_message(chat_id, msg)
                await self._show_main_menu(chat_id)
                return
            
            del self.pending_join[chat_id]
            
            # گرفتن سشن‌های 1.bale تا count.bale
            sessions = []
            for i in range(1, count + 1):
                session_file = f"{i}.bale"
                if os.path.exists(os.path.join(self.acc_dir, session_file)):
                    sessions.append(session_file)
            
            if not sessions:
                await self.bot.send_message(chat_id, f"❌ سشن‌های 1 تا {count} یافت نشد!\nلطفاً ابتدا سشن‌ها را مرتب کنید.")
                await self._show_main_menu(chat_id)
                return
            
            delay_time = await self.panel.get_delay()
            
            # شروع عملیات (افزایش شمارنده)
            await self.start_operation("join")
            
            # اجرا در Task جداگانه
            asyncio.create_task(self._run_join_operation(chat_id, sessions, link, delay_time))
            
            await self.bot.send_message(chat_id, f"✅ عملیات جوین {count} ممبر در پس‌زمینه شروع شد!\n⏳ لطفاً منتظر بمانید...")
            await self._show_main_menu(chat_id)

    async def process_leave_conversation(self, chat_id: int, text: str) -> None:
        """پردازش گفتگوی لفت"""
        state = self.pending_leave.get(chat_id)
        if not state:
            return
        
        if state["step"] == "waiting_for_chat_id":
            try:
                chat_id_target = int(text.strip())
            except ValueError:
                await self.bot.send_message(chat_id, "❌ لطفاً یک چت آیدی عددی معتبر وارد کنید!")
                return
            
            # ذخیره چت آیدی و رفتن به مرحله بعد
            self.pending_leave[chat_id]["chat_id_target"] = chat_id_target
            self.pending_leave[chat_id]["step"] = "waiting_for_count"
            
            keyboard = InlineKeyboardMarkup()
            keyboard.add_row(InlineKeyboardButton("🔙 انصراف", callback_data="admember_back"))
            
            await self.bot.send_message(
                chat_id=chat_id,
                text="🔢 *لطفاً تعداد سشن‌ها را وارد کنید:*\n\nمثال: `10`\n(سشن‌های 1 تا 10 استفاده می‌شوند)",
                reply_markup=keyboard
            )
        
        elif state["step"] == "waiting_for_count":
            try:
                count = int(text.strip())
                if count <= 0:
                    raise ValueError
            except:
                await self.bot.send_message(chat_id, "❌ لطفاً یک عدد معتبر وارد کنید!")
                return
            
            chat_id_target = state["chat_id_target"]
            
            # بررسی مجاز بودن قبل از شروع عملیات
            allowed, msg = await self.can_start_operation("leave")
            if not allowed:
                del self.pending_leave[chat_id]
                await self.bot.send_message(chat_id, msg)
                await self._show_main_menu(chat_id)
                return
            
            del self.pending_leave[chat_id]
            
            # گرفتن سشن‌های 1.bale تا count.bale
            sessions = []
            for i in range(1, count + 1):
                session_file = f"{i}.bale"
                if os.path.exists(os.path.join(self.acc_dir, session_file)):
                    sessions.append(session_file)
            
            if not sessions:
                await self.bot.send_message(chat_id, f"❌ سشن‌های 1 تا {count} یافت نشد!\nلطفاً ابتدا سشن‌ها را مرتب کنید.")
                await self._show_main_menu(chat_id)
                return
            
            delay_time = await self.panel.get_delay()
            
            # شروع عملیات (افزایش شمارنده)
            await self.start_operation("leave")
            
            # اجرا در Task جداگانه
            asyncio.create_task(self._run_leave_operation(chat_id, sessions, chat_id_target, delay_time))
            
            await self.bot.send_message(chat_id, f"✅ عملیات لفت {count} ممبر در پس‌زمینه شروع شد!\n⏳ لطفاً منتظر بمانید...")
            await self._show_main_menu(chat_id)

    async def _handle_back(self, chat_id: int, message_id: int) -> None:
        """مدیریت بازگشت به منوی اصلی"""
        # پاک کردن وضعیت‌های pending
        self.pending_join.pop(chat_id, None)
        self.pending_leave.pop(chat_id, None)
        await self._show_main_menu(chat_id, message_id)

    async def _handle_start(self, chat_id: int, message_id: int) -> None:
        """مدیریت شروع"""
        # پاک کردن وضعیت‌های pending
        self.pending_join.pop(chat_id, None)
        self.pending_leave.pop(chat_id, None)
        await self._show_main_menu(chat_id, message_id)
        
    async def _handle_delay_menu(self, chat_id: int, message_id: int) -> None:
        """مدیریت منوی تاخیر"""
        text, keyboard = self.ui.delay_menu()
        await self.bot.edit_message_text(
            chat_id=chat_id,
            message_id=message_id,
            text=text,
            reply_markup=keyboard
        )
    
    async def _handle_set_delay(self, callback_query: CallbackQuery, chat_id: int, message_id: int) -> None:
        """مدیریت تنظیم تاخیر"""
        delay_value = float(callback_query.data.split("_")[3])
        await self.bot.answer_callback_query(callback_query.id, f"✅ تاخیر به {delay_value} ثانیه تنظیم شد")
        await self.panel.update("delay", delay_value)
        await self._show_main_menu(chat_id, message_id)
    
    async def _handle_join_menu(self, chat_id: int, message_id: int = None) -> None:
        """مدیریت منوی جوین - شروع گفتگو"""
        self.pending_join[chat_id] = {"step": "waiting_for_link"}
        
        keyboard = InlineKeyboardMarkup()
        keyboard.add_row(InlineKeyboardButton("🔙 انصراف", callback_data="admember_back"))
        
        await self.bot.send_message(
            chat_id=chat_id,
            text="🔗 *لطفاً لینک گروه/کانال را ارسال کنید:*\n\nمثال: `https://ble.ir/username`",
            reply_markup=keyboard
        )

    async def _handle_leave_menu(self, chat_id: int, message_id: int = None) -> None:
        """مدیریت منوی لفت - شروع گفتگو"""
        self.pending_leave[chat_id] = {"step": "waiting_for_chat_id"}
        
        keyboard = InlineKeyboardMarkup()
        keyboard.add_row(InlineKeyboardButton("🔙 انصراف", callback_data="admember_back"))
        
        await self.bot.send_message(
            chat_id=chat_id,
            text="🆔 *لطفاً چت آیدی عددی گروه/کانال را ارسال کنید:*\n\nمثال: `123456789`",
            reply_markup=keyboard
        )
    
    async def _handle_check_sessions(self, chat_id: int, message_id: int = None) -> None:
        """شروع بررسی سشن‌ها در Task جداگانه"""
        
        async with self.operation_lock:
            if self.is_checking:
                if message_id:
                    await self.bot.answer_callback_query(message_id, "🔴 عملیات بررسی قبلاً شروع شده!", show_alert=True)
                return
            if self.active_operations > 0:
                if message_id:
                    await self.bot.answer_callback_query(message_id, "⏳ در حال حاضر عملیات دیگری در حال اجراست!", show_alert=True)
                return
        
        if message_id:
            await self.bot.answer_callback_query(message_id, "🔄 شروع بررسی سشن‌ها...")
        
        asyncio.create_task(self._run_check_sessions(chat_id, message_id))


    async def _run_check_sessions(self, chat_id: int, message_id: int = None) -> None:
        """اجرای واقعی بررسی سشن‌ها در Task جداگانه"""
        await self.start_checking()
        
        try:
            if not os.path.exists(self.acc_dir):
                await self.bot.send_message(chat_id=chat_id, text="📂 پوشه 'acc' وجود ندارد!")
                return
            
            delay = await self.panel.get_delay()
            
            if delay <= 1.0:
                batch_sleep = 2
            elif delay <= 1.8:
                batch_sleep = 4
            elif delay <= 2.5:
                batch_sleep = 8
            elif delay <= 6:
                batch_sleep = 12
            elif delay <= 9:
                batch_sleep = 16
            else:
                batch_sleep = 20
            
            batch_size = 50
            
            msg = await self.bot.send_message(
                chat_id=chat_id,
                text=f"🔄 *بررسی سشن‌ها شروع شد...*\n\n⚡ تاخیر بین دسته‌ها: {batch_sleep} ثانیه\n📦 حجم هر دسته: {batch_size}"
            )
            
            files = [f for f in sorted(os.listdir(self.acc_dir)) if f.endswith('.bale')]
            total_files = len(files)
            
            if total_files == 0:
                await self.bot.edit_message_text(chat_id, msg.message_id, "📂 *پوشه 'acc' خالی است!*")
                return
            
            valid_users = []
            broken_files = []
            duplicate_users = []
            user_ids = set()
            processed = 0
            
            for batch_start in range(0, total_files, batch_size):
                batch = files[batch_start:batch_start + batch_size]
                batch_paths = [os.path.join(self.acc_dir, f) for f in batch]
                
                results = await asyncio.gather(*[self.sessions.validate_session(f) for f in batch])
                
                for i, (is_valid, uid) in enumerate(results):
                    file = batch[i]
                    path = batch_paths[i]
                    
                    if not is_valid:
                        broken_files.append(file)
                        try:
                            os.remove(path)
                        except:
                            pass
                    elif uid in user_ids:
                        duplicate_users.append(file)
                        try:
                            os.remove(path)
                        except:
                            pass
                    else:
                        user_ids.add(uid)
                        valid_users.append(file)
                
                processed += len(batch)
                await asyncio.sleep(batch_sleep)
                
                percent = int((processed / total_files) * 100)
                await self.bot.edit_message_text(
                    chat_id=chat_id,
                    message_id=msg.message_id,
                    text=(
                        f"🔄 *بررسی سشن‌ها...* {percent}%\n\n"
                        f"📊 *پیشرفت:* {processed}/{total_files}\n"
                        f"✅ *سالم:* {len(valid_users)}\n"
                        f"❌ *خراب:* {len(broken_files)}\n"
                        f"🔄 *تکراری:* {len(duplicate_users)}"
                    )
                )
            
            text_result = (
                f"✅ *پاکسازی سشن‌ها تکمیل شد!*\n\n"
                f"📊 *نتایج نهایی:*\n"
                f"━━━━━━━━━━━━━━━━━━━━\n"
                f"📁 *کل سشن‌ها:* `{total_files}`\n"
                f"✅ *سالم:* `{len(valid_users)}`\n"
                f"❌ *خراب حذف شده:* `{len(broken_files)}`\n"
                f"🔄 *تکراری حذف شده:* `{len(duplicate_users)}`\n"
                f"━━━━━━━━━━━━━━━━━━━━"
            )
            
            await self.bot.edit_message_text(chat_id, msg.message_id, text_result)
            
        except Exception as e:
            await self.bot.send_message(chat_id, f"❌ خطا در بررسی سشن‌ها: {e}")
        finally:
            await self.finish_checking()
    
    # ========== MAIN MENU ==========
    async def _show_main_menu(self, chat_id: int, message_id: int = None) -> None:
        """نمایش منوی اصلی"""
        delay = await self.panel.get_delay()
        delay_name = self.panel.get_delay_name(delay)
        sessions_count = self.sessions.get_sessions_count()
        is_owner = await self.admin_manager.is_owner(chat_id)
        
        print(f"DEBUG: delay={delay}, delay_name={delay_name}")  # اضافه کن
        
        text, keyboard = self.ui.main_menu(delay_name, sessions_count, is_owner)
        
        if message_id:
            await self.bot.edit_message_text(
                chat_id=chat_id,
                message_id=message_id,
                text=text,
                reply_markup=keyboard
            )
        else:
            await self.bot.send_message(chat_id=chat_id, text=text, reply_markup=keyboard)
                
    # ========== COMMAND PROCESSORS ==========
    async def process_join_command(self, chat_id: int, command_text: str) -> None:
        """پردازش دستور جوین - اجرا در Task جداگانه"""
        
        # بررسی مجاز بودن
        allowed, msg = await self.can_start_operation("join")
        if not allowed:
            await self.bot.send_message(chat_id, msg)
            return
        
        parts = command_text.split("\n")
        
        if len(parts) < 3:
            await self.bot.send_message(chat_id=chat_id, text="📝 فرمت صحیح:\nعضو شو\nتعداد\nلینک")
            return
        
        try:
            count = int(parts[1].strip())
            link = parts[2].strip()
        except:
            await self.bot.send_message(chat_id=chat_id, text="❌ تعداد باید عدد باشد!")
            return
        
        if count <= 0:
            await self.bot.send_message(chat_id=chat_id, text="❌ تعداد باید بزرگتر از صفر باشد!")
            return
        
        # گرفتن سشن‌های 1.bale تا count.bale
        sessions = []
        for i in range(1, count + 1):
            session_file = f"{i}.bale"
            if os.path.exists(os.path.join(self.acc_dir, session_file)):
                sessions.append(session_file)
        
        if not sessions:
            await self.bot.send_message(chat_id=chat_id, text=f"❌ سشن‌های 1 تا {count} یافت نشد!\nلطفاً ابتدا سشن‌ها را مرتب کنید.")
            return
        
        delay_time = await self.panel.get_delay()
        
        # شروع عملیات (افزایش شمارنده)
        await self.start_operation("join")
        
        # اجرا در Task جداگانه
        asyncio.create_task(self._run_join_operation(chat_id, sessions, link, delay_time))
        
        await self.bot.send_message(chat_id, f"✅ عملیات جوین {count} ممبر در پس‌زمینه شروع شد!\n⏳ لطفاً منتظر بمانید...")


    async def _run_join_operation(self, chat_id: int, sessions: List[str], link: str, delay_time: float) -> None:
        """اجرای واقعی عملیات جوین در Task جداگانه"""
        try:
            await self._execute_batch_operation(
                chat_id=chat_id,
                sessions=sessions,
                operation="join",
                target=link,
                delay=delay_time
            )
        except Exception as e:
            await self.bot.send_message(chat_id, f"❌ خطا در عملیات جوین: {e}")
        finally:
            await self.finish_operation("join")

    async def process_leave_command(self, chat_id: int, command_text: str) -> None:
        """پردازش دستور لفت - اجرا در Task جداگانه"""
        
        # بررسی مجاز بودن
        allowed, msg = await self.can_start_operation("leave")
        if not allowed:
            await self.bot.send_message(chat_id, msg)
            return
        
        parts = command_text.split("\n")
        
        if len(parts) < 3:
            await self.bot.send_message(chat_id=chat_id, text="📝 فرمت صحیح:\nلفت بده\nتعداد\nچت آیدی عددی")
            return
        
        try:
            count = int(parts[1].strip())
            chat_id_target = int(parts[2].strip())
        except ValueError:
            await self.bot.send_message(chat_id=chat_id, text="❌ تعداد و چت آیدی باید عدد باشند!")
            return
        
        if count <= 0:
            await self.bot.send_message(chat_id=chat_id, text="❌ تعداد باید بزرگتر از صفر باشد!")
            return
        
        # گرفتن سشن‌های 1.bale تا count.bale
        sessions = []
        for i in range(1, count + 1):
            session_file = f"{i}.bale"
            if os.path.exists(os.path.join(self.acc_dir, session_file)):
                sessions.append(session_file)
        
        if not sessions:
            await self.bot.send_message(chat_id=chat_id, text=f"❌ سشن‌های 1 تا {count} یافت نشد!\nلطفاً ابتدا سشن‌ها را مرتب کنید.")
            return
        
        delay_time = await self.panel.get_delay()
        
        # شروع عملیات (افزایش شمارنده)
        await self.start_operation("leave")
        
        # اجرا در Task جداگانه
        asyncio.create_task(self._run_leave_operation(chat_id, sessions, chat_id_target, delay_time))
        
        await self.bot.send_message(chat_id, f"✅ عملیات لفت {count} ممبر در پس‌زمینه شروع شد!\n⏳ لطفاً منتظر بمانید...")


    async def _run_leave_operation(self, chat_id: int, sessions: List[str], chat_id_target: int, delay_time: float) -> None:
        """اجرای واقعی عملیات لفت در Task جداگانه"""
        try:
            await self._execute_batch_operation(
                chat_id=chat_id,
                sessions=sessions,
                operation="leave",
                target=str(chat_id_target),
                delay=delay_time
            )
        except Exception as e:
            await self.bot.send_message(chat_id, f"❌ خطا در عملیات لفت: {e}")
        finally:
            await self.finish_operation("leave")
            
    def _parse_command(self, command_text: str) -> Tuple[Optional[int], Optional[str]]:
        """تجزیه دستور"""
        parts = command_text.split("\n")
        
        try:
            if len(parts) >= 3:
                return int(parts[1].strip()), parts[2].strip()
            elif len(parts) == 2:
                sub_parts = parts[1].split()
                if len(sub_parts) >= 2:
                    return int(sub_parts[0]), sub_parts[1]
            return None, None
        except (ValueError, IndexError):
            return None, None
    
    async def _execute_batch_operation(self, chat_id: int, sessions: List[str], 
                                operation: str, target: str, delay: float) -> int:
        """اجرای عملیات گروهی به صورت دسته‌ای و همزمان"""
        success_count = 0
        total = len(sessions)
        
        # تنظیم تاخیر بر اساس مقدار delay (callback_data)
        if delay <= 0.9:      # گزینه 1: سوپر سریع
            min_sleep, max_sleep = 1.5, 5
            batch_sleep = 2
        elif delay <= 1.5:    # گزینه 2: خیلی سریع
            min_sleep, max_sleep = 5, 10
            batch_sleep = 4
        elif delay <= 2.5:    # گزینه 3: سریع
            min_sleep, max_sleep = 10, 20
            batch_sleep = 8
        elif delay <= 7:      # گزینه 4: معمولی
            min_sleep, max_sleep = 20, 30
            batch_sleep = 12
        elif delay <= 15:     # گزینه 5: کند
            min_sleep, max_sleep = 30, 50
            batch_sleep = 16
        else:                 # گزینه 6: امن (30)
            min_sleep, max_sleep = 50, 100
            batch_sleep = 20
        
        batch_size = 50
        
        msg = await self.bot.send_message(
            chat_id=chat_id,
            text=f"🔄 شروع عملیات {operation}...\n0/{total} انجام شد\n⚡ تاخیر بین سشن: {min_sleep}-{max_sleep} ثانیه\n📦 حجم دسته: {batch_size}\n⏱ تاخیر بین دسته‌ها: {batch_sleep} ثانیه"
        )
        
        processed = 0
        
        for batch_start in range(0, total, batch_size):
            batch = sessions[batch_start:batch_start + batch_size]
            
            tasks = []
            for session_file in batch:
                if operation == "join":
                    task = self.sessions.execute_join(session_file, target)
                else:
                    task = self.sessions.execute_leave(session_file, target)
                tasks.append(task)
            
            results = await asyncio.gather(*tasks, return_exceptions=True)
            
            for result in results:
                if result is True:
                    success_count += 1
            
            processed += len(batch)
            
            await asyncio.sleep(batch_sleep)
            
            percent = int((processed / total) * 100)
            await self.bot.edit_message_text(
                chat_id=chat_id,
                message_id=msg.message_id,
                text=(
                    f"🔄 عملیات {operation} در حال اجرا...\n"
                    f"📊 پیشرفت: {processed}/{total} ({percent}%)\n"
                    f"✅ موفق: {success_count}\n"
                    f"❌ ناموفق: {processed - success_count}\n"
                    f"⏱ تاخیر بین سشن: {min_sleep}-{max_sleep} ثانیه\n"
                    f"📦 دسته: {len(batch)} سشن\n"
                    f"⏱ تاخیر بین دسته‌ها: {batch_sleep} ثانیه"
                )
            )
        
        await self.bot.edit_message_text(
            chat_id=chat_id,
            message_id=msg.message_id,
            text=(
                f"🎉 عملیات {operation} تکمیل شد!\n\n"
                f"📊 نتایج نهایی:\n"
                f"✅ موفق: {success_count}\n"
                f"❌ ناموفق: {total - success_count}\n"
                f"📁 کل: {total}"
            )
        )
        
        return success_count

# ==================== BOT INITIALIZATION ====================
bot = Bot(token=TOKEN)
admember_manager = AdMemberManager(bot)

# ==================== MESSAGE HANDLERS ====================
@bot.Message(commands=['start'])
async def start_command(bot: Bot, message: Message) -> None:
    """مدیریت دستور start"""
    chat_id = message.chat.id
    
    if not await admember_manager.admin_manager.is_admin(chat_id):
        await bot.send_message(chat_id=chat_id, text="❌ دسترسی مجاز نیست!")
        return
    
    welcome_text = "به پنل مدیریت خوش اومدی!\n\nبزن روی شروع کار تا اطلاعات بالا بیاد."
    
    keyboard = InlineKeyboardMarkup()
    keyboard.add_row(InlineKeyboardButton("🚀 شروع کار", callback_data="admember_start"))
    
    await bot.send_message(chat_id=chat_id, text=welcome_text, reply_markup=keyboard)


@bot.CallbackQuery()
async def handle_callback_queries(bot: Bot, callback_query: CallbackQuery) -> None:
    """مدیریت callbackها"""
    await admember_manager.handle_callback(callback_query)


@bot.Message()
async def handle_messages(bot: Bot, message: Message) -> None:
    """مدیریت پیام‌های متنی"""
    chat_id = message.chat.id
    text = message.text.strip() if message.text else ""

    # بررسی وضعیت pending برای افزودن/حذف ادمین
    if chat_id in admember_manager.pending_admin:
        await admember_manager.process_admin_action(chat_id, text)
        return
    
    # ========== پردازش گفتگوی جوین ==========
    if chat_id in admember_manager.pending_join:
        await admember_manager.process_join_conversation(chat_id, text)
        return
    
    # ========== پردازش گفتگوی لفت ==========
    if chat_id in admember_manager.pending_leave:
        await admember_manager.process_leave_conversation(chat_id, text)
        return
    
    # بررسی دسترسی
    if not await admember_manager.admin_manager.is_admin(chat_id):
        return
    
    is_owner = await admember_manager.admin_manager.is_owner(chat_id)
    
    if text.startswith("عضو شو"):
        await admember_manager.process_join_command(chat_id, text)
    elif text.startswith("لفت بده"):
        if is_owner:
            await admember_manager.process_leave_command(chat_id, text)
        else:
            await bot.send_message(chat_id, "❌ فقط مالک می‌تواند لفت بدهد!")
    elif text == "بررسی" and is_owner:
        await admember_manager._handle_check_sessions(chat_id)
    elif text == "راهنما":
        help_text = "📚 *راهنما*\n\n• `عضو شو` - جوین کردن\n"
        if is_owner:
            help_text += "• `لفت بده` - لفت دادن\n• `بررسی` - بررسی سشن‌ها\n"
        await message.reply(help_text)

# ==================== MAIN ====================
if __name__ == "__main__":
    print("🚀 ربات اد ممبر در حال اجرا...")
    
    # پاک کردن offset
    try:
        bot.get_updates(offset=-1, timeout=1)
    except:
        pass
    
    loop = asyncio.get_event_loop()
    bot.start()