import sqlite3
import random
import string
from datetime import datetime
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO

from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
from telegram.ext import (
    Updater,
    CommandHandler,
    MessageHandler,
    Filters,
    CallbackQueryHandler,
    CallbackContext,
    ConversationHandler,
)

# Constants
BOT_TOKEN = "7664933547:AAGYUrDodrlFasmeG6sP-xLblBa8M2_Bz74"
ADMIN_IDS = [6254562772, 5187944932]
PAYMENT_CHANNEL_ID = -1002532301939
DB_NAME = "referral_bot.db"

# Conversation states
(
    TYPING_REPLY,
    TYPING_CHOICE,
    ADD_CHANNEL_ID,
    ADD_CHANNEL_URL,
    REMOVE_CHANNEL_ID,
    SET_REFER_BONUS,
    SET_MIN_WITHDRAWAL,
    SET_EXCHANGE_RATE_USD,
    SET_EXCHANGE_RATE_BDT,
    BROADCAST_MESSAGE,
    ADD_WALLET_ADDRESS,
    WITHDRAW_AMOUNT,
    CAPTCHA_VERIFICATION,
) = range(13)


# Database setup
def setup_database():
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    # Users table
    c.execute(
        """CREATE TABLE IF NOT EXISTS users (
                    user_id INTEGER PRIMARY KEY,
                    first_name TEXT,
                    username TEXT,
                    balance REAL DEFAULT 0,
                    referred_by INTEGER,
                    referral_count INTEGER DEFAULT 0,
                    usdt_wallet TEXT,
                    bdt_wallet TEXT
                )"""
    )
    # Channels table
    c.execute(
        """CREATE TABLE IF NOT EXISTS channels (
                    channel_id INTEGER PRIMARY KEY,
                    channel_url TEXT NOT NULL
                )"""
    )
    # Settings table
    c.execute(
        """CREATE TABLE IF NOT EXISTS settings (
                    key TEXT PRIMARY KEY,
                    value TEXT
                )"""
    )
    # Set default settings
    default_settings = {
        "refer_bonus": "10",
        "min_withdrawal": "100",
        "exchange_rate_usd": "110",
        "exchange_rate_bdt": "1",
    }
    for key, value in default_settings.items():
        c.execute("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)", (key, value))

    conn.commit()
    conn.close()


def get_setting(key):
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT value FROM settings WHERE key=?", (key,))
    result = c.fetchone()
    conn.close()
    return result[0] if result else None


def update_setting(key, value):
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("UPDATE settings SET value=? WHERE key=?", (value, key))
    conn.commit()
    conn.close()


# Helper Functions
def is_admin(user_id):
    return user_id in ADMIN_IDS


def generate_captcha():
    num1 = random.randint(1, 10)
    num2 = random.randint(1, 10)
    operator = random.choice(["+", "-"])
    if operator == "+":
        question = f"{num1} + {num2}"
        answer = num1 + num2
    else:
        # Ensure the result is not negative
        if num1 < num2:
            num1, num2 = num2, num1
        question = f"{num1} - {num2}"
        answer = num1 - num2
    
    # Create an image for the captcha
    img = Image.new('RGB', (150, 50), color = (255, 255, 255))
    d = ImageDraw.Draw(img)
    try:
        font = ImageFont.truetype("arial.ttf", 25)
    except IOError:
        font = ImageFont.load_default()
    d.text((10,10), question, fill=(0,0,0), font=font)
    
    # Add some noise
    for _ in range(500):
        x = random.randint(0, 149)
        y = random.randint(0, 49)
        d.point((x,y), fill=(random.randint(0,255), random.randint(0,255), random.randint(0,255)))

    bio = BytesIO()
    bio.name = 'captcha.jpeg'
    img.save(bio, 'JPEG')
    bio.seek(0)
    return bio, answer


def check_channel_join(user_id, context: CallbackContext):
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT channel_id FROM channels")
    channels = c.fetchall()
    conn.close()

    if not channels:
        return True  # No channels to join

    for channel in channels:
        try:
            member = context.bot.get_chat_member(chat_id=channel[0], user_id=user_id)
            if member.status not in ["member", "administrator", "creator"]:
                return False
        except Exception:
            return False  # Bot is not admin in the channel or channel is invalid
    return True


def show_join_channels_message(update: Update, context: CallbackContext):
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT channel_id, channel_url FROM channels")
    channels = c.fetchall()
    conn.close()

    if not channels:
        return  # No channels to show

    keyboard = []
    text = "➡️ আমাদের বট ব্যবহার করার জন্য আপনাকে অবশ্যই নিচের চ্যানেলগুলোতে জয়েন করতে হবে:\n\n"
    for i, (channel_id, channel_url) in enumerate(channels):
        text += f"{i+1}. {channel_url}\n"
        keyboard.append([InlineKeyboardButton(f"চ্যানেল {i+1}", url=f"https://t.me/{channel_url.split('/')[-1]}")])
    
    keyboard.append([InlineKeyboardButton("✅ সম্পন্ন হয়েছে", callback_data="check_join")])
    update.message.reply_text(text, reply_markup=InlineKeyboardMarkup(keyboard))

# Start command
def start(update: Update, context: CallbackContext):
    user_id = update.effective_user.id
    first_name = update.effective_user.first_name
    username = update.effective_user.username

    # Captcha Verification
    bio, answer = generate_captcha()
    context.user_data['captcha_answer'] = answer
    
    update.message.reply_photo(
        photo=bio,
        caption="🤖 আমি যে মানুষ, তা যাচাই করতে উপরের সহজ প্রশ্নের উত্তর দিন:",
    )
    return CAPTCHA_VERIFICATION

def captcha_handler(update: Update, context: CallbackContext):
    user_id = update.effective_user.id
    first_name = update.effective_user.first_name
    username = update.effective_user.username
    
    try:
        user_answer = int(update.message.text)
        correct_answer = context.user_data.get('captcha_answer')
        
        if user_answer != correct_answer:
            update.message.reply_text("❌ ভুল উত্তর! আবার চেষ্টা করুন।")
            return start(update, context) # Resend captcha
            
    except (ValueError, TypeError):
        update.message.reply_text("❌ অনুগ্রহ করে শুধু সংখ্যায় উত্তর দিন।")
        return start(update, context) # Resend captcha

    # Connect to DB
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT * FROM users WHERE user_id=?", (user_id,))
    user_exists = c.fetchone()

    if not user_exists:
        referred_by = None
        if context.args and context.args[0].isdigit():
            referrer_id = int(context.args[0])
            c.execute("SELECT * FROM users WHERE user_id=?", (referrer_id,))
            if c.fetchone() and referrer_id != user_id:
                referred_by = referrer_id
                # Update referrer's balance and referral count
                bonus = float(get_setting("refer_bonus"))
                c.execute("UPDATE users SET balance = balance + ?, referral_count = referral_count + 1 WHERE user_id = ?", (bonus, referrer_id))
                context.bot.send_message(
                    chat_id=referrer_id,
                    text=f"🎉 অভিনন্দন! আপনি {first_name} কে রেফার করার জন্য {bonus} পয়েন্ট পেয়েছেন।"
                )

        c.execute(
            "INSERT INTO users (user_id, first_name, username, referred_by) VALUES (?, ?, ?, ?)",
            (user_id, first_name, username, referred_by),
        )
        conn.commit()

    conn.close()

    # Check for channel join
    if not check_channel_join(user_id, context):
        show_join_channels_message(update, context)
        return

    send_main_menu(update, context)
    return ConversationHandler.END

def check_join_callback(update: Update, context: CallbackContext):
    query = update.callback_query
    user_id = query.from_user.id

    if check_channel_join(user_id, context):
        query.answer("✅ ধন্যবাদ! আপনি এখন বটটি ব্যবহার করতে পারেন।")
        send_main_menu(update, context)
    else:
        query.answer("❌ আপনি এখনও সব চ্যানেলে জয়েন করেননি।", show_alert=True)


# Main Menu
def send_main_menu(update: Update, context: CallbackContext):
    user_id = update.effective_user.id
    keyboard = [
        [InlineKeyboardButton("🔗 রেফারেল লিংক", callback_data="referral_link")],
        [InlineKeyboardButton("💰 আমার ব্যালেন্স", callback_data="my_balance")],
        [InlineKeyboardButton("💸 উইথড্র", callback_data="withdraw")],
        [InlineKeyboardButton("🏆 লিডারবোর্ড", callback_data="leaderboard")],
        [InlineKeyboardButton("⚙️ ওয়ালেট সেটআপ", callback_data="setup_wallet")],
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    welcome_message = f"""
👋 স্বাগতম, {update.effective_user.first_name}!

আমাদের রেফার এন্ড আর্ন বটে আপনাকে স্বাগতম। আপনার বন্ধুদের রেফার করে পয়েন্ট আয় করুন এবং টাকা বা ডলারে উইথড্র করুন।
"""
    # Use query.message.reply_text for callbacks and update.message.reply_text for commands
    if update.callback_query:
        update.callback_query.message.reply_text(welcome_message, reply_markup=reply_markup)
    else:
        update.message.reply_text(welcome_message, reply_markup=reply_markup)


def main_menu_callback(update: Update, context: CallbackContext):
    query = update.callback_query
    query.answer()
    send_main_menu(update, context)


def referral_link(update: Update, context: CallbackContext):
    query = update.callback_query
    user_id = query.from_user.id
    bot_username = context.bot.username
    referral_link = f"https://t.me/{bot_username}?start={user_id}"
    text = f"""
🔗 আপনার রেফারেল লিংক:
`{referral_link}`

আপনার বন্ধুদের সাথে এই লিংকটি শেয়ার করুন। প্রতি সফল রেফারে আপনি পাবেন {get_setting('refer_bonus')} পয়েন্ট।
"""
    query.edit_message_text(text, parse_mode=ParseMode.MARKDOWN)


def my_balance(update: Update, context: CallbackContext):
    query = update.callback_query
    user_id = query.from_user.id
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT balance, referral_count FROM users WHERE user_id=?", (user_id,))
    result = c.fetchone()
    conn.close()

    balance = result[0] if result else 0
    referral_count = result[1] if result else 0
    
    usd_rate = float(get_setting("exchange_rate_usd"))
    bdt_rate = float(get_setting("exchange_rate_bdt"))

    balance_usd = balance / usd_rate
    balance_bdt = balance * bdt_rate

    text = f"""
💰 আপনার একাউন্ট তথ্য:

- আপনার বর্তমান ব্যালেন্স: {balance:.2f} পয়েন্ট
- মোট রেফারেল: {referral_count} জন

- সমতুল্য USDT: ${balance_usd:.2f}
- সমতুল্য BDT: ৳{balance_bdt:.2f}
"""
    query.edit_message_text(text)


def leaderboard(update: Update, context: CallbackContext):
    query = update.callback_query
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT first_name, referral_count FROM users ORDER BY referral_count DESC LIMIT 10")
    top_users = c.fetchall()
    conn.close()

    text = "🏆 সেরা ১০ রেফারকারী:\n\n"
    for i, user in enumerate(top_users):
        text += f"{i+1}. {user[0]} - {user[1]} রেফার\n"

    query.edit_message_text(text)

# Wallet Setup
def setup_wallet(update: Update, context: CallbackContext):
    query = update.callback_query
    keyboard = [
        [InlineKeyboardButton("USDT ওয়ালেট সেট করুন", callback_data="set_usdt_wallet")],
        [InlineKeyboardButton("BDT ওয়ালেট সেট করুন", callback_data="set_bdt_wallet")],
        [InlineKeyboardButton("⬅️ পেছনে", callback_data="main_menu")],
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    query.edit_message_text("আপনি কোন ওয়ালেট সেট করতে চান তা নির্বাচন করুন:", reply_markup=reply_markup)


def set_wallet_prompt(update: Update, context: CallbackContext):
    query = update.callback_query
    wallet_type = query.data.split('_')[1] # usdt or bdt
    context.user_data['wallet_type'] = wallet_type
    
    if wallet_type == "usdt":
        prompt_text = "আপনার Binance Pay ID অথবা USDT (TRC20) ওয়ালেট এড্রেস দিন:"
    else:
        prompt_text = "আপনার বিকাশ/নগদ/উপায় নম্বর দিন:"
        
    query.edit_message_text(prompt_text)
    return ADD_WALLET_ADDRESS

def add_wallet_address(update: Update, context: CallbackContext):
    user_id = update.effective_user.id
    wallet_address = update.message.text
    wallet_type = context.user_data['wallet_type']

    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    if wallet_type == 'usdt':
        c.execute("UPDATE users SET usdt_wallet=? WHERE user_id=?", (wallet_address, user_id))
    else:
        c.execute("UPDATE users SET bdt_wallet=? WHERE user_id=?", (wallet_address, user_id))
    conn.commit()
    conn.close()

    update.message.reply_text("✅ আপনার ওয়ালেট সফলভাবে আপডেট করা হয়েছে।")
    send_main_menu(update, context)
    return ConversationHandler.END


# Withdrawal
def withdraw(update: Update, context: CallbackContext):
    query = update.callback_query
    user_id = query.from_user.id
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT balance, usdt_wallet, bdt_wallet FROM users WHERE user_id=?", (user_id,))
    result = c.fetchone()
    conn.close()

    min_withdrawal = float(get_setting("min_withdrawal"))
    balance = result[0]
    usdt_wallet = result[1]
    bdt_wallet = result[2]

    if balance < min_withdrawal:
        query.answer(f"❌ আপনার পর্যাপ্ত ব্যালেন্স নেই। সর্বনিম্ন উইথড্র পরিমাণ {min_withdrawal} পয়েন্ট।", show_alert=True)
        return

    keyboard = []
    if usdt_wallet:
        keyboard.append([InlineKeyboardButton("USDT দিয়ে উইথড্র", callback_data="withdraw_usdt")])
    if bdt_wallet:
        keyboard.append([InlineKeyboardButton("BDT দিয়ে উইথড্র", callback_data="withdraw_bdt")])

    if not keyboard:
        query.answer("❌ উইথড্র করার আগে অনুগ্রহ করে আপনার ওয়ালেট সেটআপ করুন।", show_alert=True)
        return

    keyboard.append([InlineKeyboardButton("⬅️ পেছনে", callback_data="main_menu")])
    reply_markup = InlineKeyboardMarkup(keyboard)
    query.edit_message_text("আপনি কোন মাধ্যমে উইথড্র করতে চান?", reply_markup=reply_markup)


def withdraw_prompt(update: Update, context: CallbackContext):
    query = update.callback_query
    withdraw_method = query.data.split('_')[1] # usdt or bdt
    context.user_data['withdraw_method'] = withdraw_method

    usd_rate = float(get_setting("exchange_rate_usd"))
    bdt_rate = float(get_setting("exchange_rate_bdt"))
    
    if withdraw_method == "usdt":
        prompt_text = f"আপনি কত পয়েন্ট উইথড্র করতে চান? (1 USDT = {usd_rate} পয়েন্ট)"
    else:
        prompt_text = f"আপনি কত পয়েন্ট উইথড্র করতে চান? (1 BDT = {bdt_rate} পয়েন্ট)"
        
    query.edit_message_text(prompt_text)
    return WITHDRAW_AMOUNT


def process_withdraw_amount(update: Update, context: CallbackContext):
    user_id = update.effective_user.id
    user_name = update.effective_user.first_name
    username = f"@{update.effective_user.username}" if update.effective_user.username else "N/A"
    withdraw_method = context.user_data['withdraw_method']

    try:
        amount = float(update.message.text)
    except ValueError:
        update.message.reply_text("❌ অনুগ্রহ করে সঠিক সংখ্যায় পরিমাণ লিখুন।")
        return WITHDRAW_AMOUNT

    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT balance, usdt_wallet, bdt_wallet FROM users WHERE user_id=?", (user_id,))
    result = c.fetchone()
    balance = result[0]
    usdt_wallet = result[1]
    bdt_wallet = result[2]
    conn.close()

    min_withdrawal = float(get_setting("min_withdrawal"))

    if amount < min_withdrawal:
        update.message.reply_text(f"❌ সর্বনিম্ন উইথড্র পরিমাণ {min_withdrawal} পয়েন্ট।")
        return ConversationHandler.END
    if amount > balance:
        update.message.reply_text("❌ আপনার একাউন্টে পর্যাপ্ত ব্যালেন্স নেই।")
        return ConversationHandler.END

    # Deduct balance
    new_balance = balance - amount
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("UPDATE users SET balance=? WHERE user_id=?", (new_balance, user_id))
    conn.commit()
    conn.close()

    # Calculate final amount
    usd_rate = float(get_setting("exchange_rate_usd"))
    bdt_rate = float(get_setting("exchange_rate_bdt"))
    
    if withdraw_method == "usdt":
        final_amount = f"${amount / usd_rate:.2f}"
        wallet_info = f"USDT Wallet: {usdt_wallet}"
    else:
        final_amount = f"৳{amount * bdt_rate:.2f}"
        wallet_info = f"BDT Wallet: {bdt_wallet}"
        
    # Send to payment channel
    text = f"""
 নতুন উইথড্র রিকোয়েস্ট!

ব্যবহারকারী: {user_name}
ইউজারনেম: {username}
ইউজার আইডি: `{user_id}`

পরিমাণ (পয়েন্ট): {amount}
পরিমাণ (কারেন্সি): {final_amount}
{wallet_info}
তারিখ: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
    keyboard = [
        [
            InlineKeyboardButton("✅ একসেপ্ট", callback_data=f"accept_withdraw_{user_id}_{amount}"),
            InlineKeyboardButton("❌ বাতিল", callback_data=f"cancel_withdraw_{user_id}_{amount}"),
        ]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)

    context.bot.send_message(
        chat_id=PAYMENT_CHANNEL_ID,
        text=text,
        reply_markup=reply_markup,
        parse_mode=ParseMode.MARKDOWN,
    )

    update.message.reply_text("✅ আপনার উইথড্র রিকোয়েস্ট সফলভাবে পাঠানো হয়েছে। এডমিন পর্যালোচনার পর আপনাকে জানানো হবে।")
    send_main_menu(update, context)
    return ConversationHandler.END


def handle_withdraw_callback(update: Update, context: CallbackContext):
    query = update.callback_query
    admin_id = query.from_user.id

    if not is_admin(admin_id):
        query.answer("❌ শুধুমাত্র এডমিন এই কাজটি করতে পারবে।", show_alert=True)
        return

    data = query.data.split("_")
    action = data[0]
    user_id = int(data[2])
    amount = float(data[3])

    original_message = query.message.text
    
    if action == "accept":
        context.bot.send_message(user_id, "🎉 অভিনন্দন! আপনার উইথড্র রিকোয়েস্টটি একসেপ্ট করা হয়েছে।")
        query.edit_message_text(f"{original_message}\n\n✅ এডমিন দ্বারা একসেপ্ট করা হয়েছে।")
    elif action == "cancel":
        # Refund the amount
        conn = sqlite3.connect(DB_NAME)
        c = conn.cursor()
        c.execute("UPDATE users SET balance = balance + ? WHERE user_id = ?", (amount, user_id))
        conn.commit()
        conn.close()
        context.bot.send_message(user_id, f"দুঃখিত! আপনার উইথড্র রিকোয়েস্টটি বাতিল করা হয়েছে। {amount} পয়েন্ট আপনার একাউন্টে ফেরত দেওয়া হয়েছে।")
        query.edit_message_text(f"{original_message}\n\n❌ এডমিন দ্বারা বাতিল করা হয়েছে।")


# Admin Panel
def admin_panel(update: Update, context: CallbackContext):
    user_id = update.effective_user.id
    if not is_admin(user_id):
        update.message.reply_text("❌ আপনার এই কমান্ড ব্যবহারের অনুমতি নেই।")
        return

    keyboard = [
        [
            InlineKeyboardButton("📢 ব্রডকাস্ট", callback_data="admin_broadcast"),
            InlineKeyboardButton("📊 পরিসংখ্যান", callback_data="admin_stats"),
        ],
        [
            InlineKeyboardButton("➕ চ্যানেল যোগ", callback_data="admin_add_channel"),
            InlineKeyboardButton("➖ চ্যানেল মুছুন", callback_data="admin_remove_channel"),
        ],
        [
            InlineKeyboardButton("💰 রেফার বোনাস", callback_data="admin_refer_bonus"),
            InlineKeyboardButton("💸 মিনিমাম উইথড্র", callback_data="admin_min_withdrawal"),
        ],
        [
            InlineKeyboardButton("💱 এক্সচেঞ্জ রেট", callback_data="admin_exchange_rate"),
        ],
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    update.message.reply_text("🔑 এডমিন প্যানেল", reply_markup=reply_markup)


def admin_callback_handler(update: Update, context: CallbackContext):
    query = update.callback_query
    data = query.data

    if data == "admin_stats":
        conn = sqlite3.connect(DB_NAME)
        c = conn.cursor()
        c.execute("SELECT COUNT(*) FROM users")
        total_users = c.fetchone()[0]
        conn.close()
        query.edit_message_text(f"📊 মোট ব্যবহারকারী: {total_users}")
        return

    if data == "admin_add_channel":
        query.edit_message_text("➕ যে চ্যানেলটি যোগ করতে চান তার আইডি দিন (@username অথবা -100...):")
        return ADD_CHANNEL_ID
    if data == "admin_remove_channel":
        query.edit_message_text("➖ যে চ্যানেলটি মুছতে চান তার আইডি দিন:")
        return REMOVE_CHANNEL_ID
    if data == "admin_refer_bonus":
        query.edit_message_text("💰 নতুন রেফার বোনাস পরিমাণ দিন:")
        return SET_REFER_BONUS
    if data == "admin_min_withdrawal":
        query.edit_message_text("💸 নতুন মিনিমাম উইথড্র পরিমাণ দিন:")
        return SET_MIN_WITHDRAWAL
    if data == "admin_broadcast":
        query.edit_message_text("📢 আপনার ব্রডকাস্ট মেসেজটি লিখুন:")
        return BROADCAST_MESSAGE
    if data == "admin_exchange_rate":
        keyboard = [
            [InlineKeyboardButton("USD রেট সেট করুন", callback_data="set_rate_usd")],
            [InlineKeyboardButton("BDT রেট সেট করুন", callback_data="set_rate_bdt")],
        ]
        query.edit_message_text("💱 কোন কারেন্সির রেট সেট করতে চান?", reply_markup=InlineKeyboardMarkup(keyboard))
        return

def set_rate_callback(update: Update, context: CallbackContext):
    query = update.callback_query
    rate_type = query.data.split('_')[2] # usd or bdt
    if rate_type == "usd":
        query.edit_message_text("💵 1 USD সমান কত পয়েন্ট হবে তা লিখুন:")
        return SET_EXCHANGE_RATE_USD
    else:
        query.edit_message_text("💵 1 BDT সমান কত পয়েন্ট হবে তা লিখুন:")
        return SET_EXCHANGE_RATE_BDT
        

def get_channel_id(update: Update, context: CallbackContext):
    channel_id = update.message.text
    context.user_data["channel_id"] = channel_id
    update.message.reply_text("🔗 এবার চ্যানেলটির লিংক দিন (e.g., https://t.me/channelname):")
    return ADD_CHANNEL_URL


def add_channel_url(update: Update, context: CallbackContext):
    channel_id = context.user_data["channel_id"]
    channel_url = update.message.text
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    try:
        c.execute("INSERT INTO channels (channel_id, channel_url) VALUES (?, ?)", (channel_id, channel_url))
        conn.commit()
        update.message.reply_text("✅ চ্যানেল সফলভাবে যোগ করা হয়েছে।")
    except sqlite3.IntegrityError:
        update.message.reply_text("❌ এই চ্যানেলটি আগে থেকেই যোগ করা আছে।")
    conn.close()
    return ConversationHandler.END


def remove_channel(update: Update, context: CallbackContext):
    channel_id = update.message.text
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("DELETE FROM channels WHERE channel_id=?", (channel_id,))
    if c.rowcount > 0:
        update.message.reply_text("✅ চ্যানেলটি সফলভাবে মুছে ফেলা হয়েছে।")
    else:
        update.message.reply_text("❌ এই আইডি দিয়ে কোনো চ্যানেল খুঁজে পাওয়া যায়নি।")
    conn.commit()
    conn.close()
    return ConversationHandler.END


def set_refer_bonus(update: Update, context: CallbackContext):
    bonus = update.message.text
    try:
        float(bonus)
        update_setting("refer_bonus", bonus)
        update.message.reply_text(f"✅ রেফার বোনাস সফলভাবে {bonus} এ সেট করা হয়েছে।")
    except ValueError:
        update.message.reply_text("❌ অনুগ্রহ করে একটি সঠিক সংখ্যা দিন।")
    return ConversationHandler.END


def set_min_withdrawal(update: Update, context: CallbackContext):
    amount = update.message.text
    try:
        float(amount)
        update_setting("min_withdrawal", amount)
        update.message.reply_text(f"✅ মিনিমাম উইথড্র পরিমাণ সফলভাবে {amount} এ সেট করা হয়েছে।")
    except ValueError:
        update.message.reply_text("❌ অনুগ্রহ করে একটি সঠিক সংখ্যা দিন।")
    return ConversationHandler.END

def set_exchange_rate_usd(update: Update, context: CallbackContext):
    rate = update.message.text
    try:
        float(rate)
        update_setting("exchange_rate_usd", rate)
        update.message.reply_text(f"✅ USD এক্সচেঞ্জ রেট সফলভাবে {rate} এ সেট করা হয়েছে।")
    except ValueError:
        update.message.reply_text("❌ অনুগ্রহ করে একটি সঠিক সংখ্যা দিন।")
    return ConversationHandler.END

def set_exchange_rate_bdt(update: Update, context: CallbackContext):
    rate = update.message.text
    try:
        float(rate)
        update_setting("exchange_rate_bdt", rate)
        update.message.reply_text(f"✅ BDT এক্সচেঞ্জ রেট সফলভাবে {rate} এ সেট করা হয়েছে।")
    except ValueError:
        update.message.reply_text("❌ অনুগ্রহ করে একটি সঠিক সংখ্যা দিন।")
    return ConversationHandler.END


def broadcast_message(update: Update, context: CallbackContext):
    message = update.message
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT user_id FROM users")
    users = c.fetchall()
    conn.close()

    for user in users:
        try:
            message.copy(chat_id=user[0])
        except Exception as e:
            print(f"Failed to send message to {user[0]}: {e}")

    update.message.reply_text(f"✅ মেসেজটি {len(users)} জন ব্যবহারকারীকে পাঠানো হয়েছে।")
    return ConversationHandler.END


def cancel(update: Update, context: CallbackContext):
    update.message.reply_text("বাতিল করা হয়েছে।")
    return ConversationHandler.END


def main():
    setup_database()
    updater = Updater(BOT_TOKEN, use_context=True)
    dp = updater.dispatcher

    # Conversation handler for admin settings
    admin_conv_handler = ConversationHandler(
        entry_points=[CallbackQueryHandler(admin_callback_handler, pattern="^admin_")],
        states={
            ADD_CHANNEL_ID: [MessageHandler(Filters.text & ~Filters.command, get_channel_id)],
            ADD_CHANNEL_URL: [MessageHandler(Filters.text & ~Filters.command, add_channel_url)],
            REMOVE_CHANNEL_ID: [MessageHandler(Filters.text & ~Filters.command, remove_channel)],
            SET_REFER_BONUS: [MessageHandler(Filters.text & ~Filters.command, set_refer_bonus)],
            SET_MIN_WITHDRAWAL: [MessageHandler(Filters.text & ~Filters.command, set_min_withdrawal)],
            BROADCAST_MESSAGE: [MessageHandler(Filters.all & ~Filters.command, broadcast_message)],
            SET_EXCHANGE_RATE_USD: [MessageHandler(Filters.text & ~Filters.command, set_exchange_rate_usd)],
            SET_EXCHANGE_RATE_BDT: [MessageHandler(Filters.text & ~Filters.command, set_exchange_rate_bdt)],
        },
        fallbacks=[CommandHandler("cancel", cancel)],
        map_to_parent={
             ConversationHandler.END: ConversationHandler.END
        }
    )
    
    set_wallet_conv = ConversationHandler(
        entry_points=[CallbackQueryHandler(set_wallet_prompt, pattern="^set_.*_wallet")],
        states={
            ADD_WALLET_ADDRESS: [MessageHandler(Filters.text & ~Filters.command, add_wallet_address)]
        },
        fallbacks=[CommandHandler("cancel", cancel)],
    )

    withdraw_conv = ConversationHandler(
        entry_points=[CallbackQueryHandler(withdraw_prompt, pattern="^withdraw_")],
        states={
            WITHDRAW_AMOUNT: [MessageHandler(Filters.text & ~Filters.command, process_withdraw_amount)]
        },
        fallbacks=[CommandHandler("cancel", cancel)],
    )
    
    start_conv = ConversationHandler(
        entry_points=[CommandHandler("start", start)],
        states={
            CAPTCHA_VERIFICATION: [MessageHandler(Filters.text & ~Filters.command, captcha_handler)]
        },
        fallbacks=[CommandHandler("cancel", cancel)],
    )

    dp.add_handler(start_conv)
    dp.add_handler(CommandHandler("admin", admin_panel))

    dp.add_handler(CallbackQueryHandler(check_join_callback, pattern="check_join"))
    dp.add_handler(CallbackQueryHandler(referral_link, pattern="referral_link"))
    dp.add_handler(CallbackQueryHandler(my_balance, pattern="my_balance"))
    dp.add_handler(CallbackQueryHandler(leaderboard, pattern="leaderboard"))
    dp.add_handler(CallbackQueryHandler(withdraw, pattern="withdraw"))
    dp.add_handler(CallbackQueryHandler(setup_wallet, pattern="setup_wallet"))
    dp.add_handler(CallbackQueryHandler(main_menu_callback, pattern="main_menu"))
    dp.add_handler(CallbackQueryHandler(handle_withdraw_callback, pattern="^(accept|cancel)_withdraw"))
    
    dp.add_handler(admin_conv_handler)
    dp.add_handler(set_wallet_conv)
    dp.add_handler(withdraw_conv)
    dp.add_handler(CallbackQueryHandler(set_rate_callback, pattern="^set_rate_"))


    updater.start_polling()
    updater.idle()


if __name__ == "__main__":
    main()