import sqlite3
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
    Application,
    CommandHandler,
    CallbackQueryHandler,
    MessageHandler, 
    ContextTypes,
    filters,
)
from telegram.error import TelegramError

BOT_TOKEN = "توکن_ربات_اینجا"
ADMIN_ID = 7855791991

REQUIRED_CHANNEL = "@proxy_shah"
CHANNEL_LINK = "https://t.me/proxy_shah"

DB_FILE = "bot.db"

db = sqlite3.connect(DB_FILE, check_same_thread=False)
cur = db.cursor()

cur.execute("""
CREATE TABLE IF NOT EXISTS users (
    user_id INTEGER PRIMARY KEY,
    username TEXT,
    first_name TEXT,
    inviter_id INTEGER,
    referrals INTEGER DEFAULT 0,
    claimed_rewards INTEGER DEFAULT 0
)
""")

cur.execute("""
CREATE TABLE IF NOT EXISTS configs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    config TEXT NOT NULL,
    used INTEGER DEFAULT 0,
    used_by INTEGER
)
""")

db.commit()


def is_admin(user_id):
    return user_id == ADMIN_ID


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


def add_user(user_id, username, first_name, inviter_id=None):
    cur.execute(
        "SELECT user_id FROM users WHERE user_id = ?",
        (user_id,)
    )

    if cur.fetchone():
        return False

    cur.execute("""
        INSERT INTO users
        (user_id, username, first_name, inviter_id)
        VALUES (?, ?, ?, ?)
    """, (user_id, username, first_name, inviter_id))

    db.commit()
    return True


async def check_membership(user_id, context):
    if is_admin(user_id):
        return True

    try:
        member = await context.bot.get_chat_member(
            REQUIRED_CHANNEL,
            user_id
        )

        return member.status in (
            "member",
            "administrator",
            "creator"
        )

    except TelegramError:
        return False


async def force_join_message(update, context):
    keyboard = [
        [
            InlineKeyboardButton(
                "📣 عضویت در کانال",
                url=CHANNEL_LINK
            )
        ],
        [
            InlineKeyboardButton(
                "✅ بررسی عضویت",
                callback_data="check_join"
            )
        ]
    ]

    text = (
        "🔒 برای استفاده از ربات ابتدا باید عضو کانال شوید.\n\n"
        f"📣 کانال: {REQUIRED_CHANNEL}\n\n"
        "بعد از عضویت روی «✅ بررسی عضویت» بزنید."
    )

    if update.callback_query:
        await update.callback_query.message.reply_text(
            text,
            reply_markup=InlineKeyboardMarkup(keyboard)
        )
    else:
        await update.message.reply_text(
            text,
            reply_markup=InlineKeyboardMarkup(keyboard)
        )


async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user

    if not await check_membership(user.id, context):
        await force_join_message(update, context)
        return

    inviter_id = None

    if context.args:
        try:
            possible_inviter = int(context.args[0])

            if possible_inviter != user.id:
                inviter_id = possible_inviter

        except ValueError:
            pass

    is_new = add_user(
        user.id,
        user.username or "",
        user.first_name or "",
        inviter_id
    )

    if is_new and inviter_id:
        inviter = get_user(inviter_id)

        if inviter:
            cur.execute("""
                UPDATE users
                SET referrals = referrals + 1
                WHERE user_id = ?
            """, (inviter_id,))

            db.commit()

            try:
                inviter_user = get_user(inviter_id)
                new_count = inviter_user[4]

                if new_count % 5 == 0:
                    await context.bot.send_message(
                        inviter_id,
                        "🎉 تبریک!\n\n"
                        f"👥 دعوت‌های شما: {new_count}\n"
                        "🎁 یک جایزه ۵ گیگ برای شما فعال شد!"
                    )
                else:
                    await context.bot.send_message(
                        inviter_id,
                        "👤 یک نفر با لینک دعوت شما وارد شد!\n\n"
                        f"📊 دعوت‌های شما: {new_count}\n"
                        f"🎯 تا جایزه بعدی: {5 - (new_count % 5)} نفر"
                    )

            except TelegramError:
                pass

    bot_username = (await context.bot.get_me()).username
    referral_link = f"https://t.me/{bot_username}?start={user.id}"

    keyboard = [
        [
            InlineKeyboardButton(
                "🔗 لینک دعوت من",
                callback_data="my_link"
            )
        ],
        [
            InlineKeyboardButton(
                "📊 آمار من",
                callback_data="stats"
            )
        ],
        [
            InlineKeyboardButton(
                "🎁 دریافت جایزه",
                callback_data="reward"
            )
        ]
    ]

    if is_admin(user.id):
        keyboard.append([
            InlineKeyboardButton(
                "👑 مدیریت",
                callback_data="admin"
            )
        ])

    await update.message.reply_text(
        "🎉 خوش اومدی!\n\n"
        "👥 دوستانت رو دعوت کن و جایزه بگیر.\n\n"
        "🎁 هر ۵ دعوت موفق = ۵ گیگ کانفیگ\n\n"
        "🔗 لینک دعوت اختصاصی تو:\n"
        f"{referral_link}",
        reply_markup=InlineKeyboardMarkup(keyboard)
    )


async def check_join(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if await check_membership(query.from_user.id, context):
        await query.message.reply_text(
            "✅ عضویت شما تأیید شد!\n\n"
            "حالا /start را بزنید."
        )
    else:
        await query.message.reply_text(
            "❌ هنوز عضو کانال نیستید."
        )


async def my_link(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not await check_membership(query.from_user.id, context):
        await force_join_message(update, context)
        return

    bot_username = (await context.bot.get_me()).username
    user_id = query.from_user.id

    link = f"https://t.me/{bot_username}?start={user_id}"

    await query.message.reply_text(
        "🔗 لینک دعوت شما:\n\n"
        f"{link}"
    )


async def stats(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not await check_membership(query.from_user.id, context):
        await force_join_message(update, context)
        return

    user = get_user(query.from_user.id)

    if not user:
        await query.message.reply_text(
            "ابتدا /start را بزنید."
        )
        return

    referrals = user[4]
    claimed = user[5]

    earned = referrals // 5
    available = earned - claimed
    remaining = 5 - (referrals % 5)

    await query.message.reply_text(
        "📊 آمار شما\n\n"
        f"👥 دعوت موفق: {referrals}\n"
        f"🎁 جوایز کسب‌شده: {earned}\n"
        f"📦 جوایز دریافت‌شده: {claimed}\n"
        f"🎯 قابل دریافت: {available}\n\n"
        f"👤 دعوت تا جایزه بعدی: {remaining}"
    )


async def reward(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not await check_membership(query.from_user.id, context):
        await force_join_message(update, context)
        return

    user_id = query.from_user.id
    user = get_user(user_id)

    if not user:
        await query.message.reply_text(
            "ابتدا /start را بزنید."
        )
        return

    referrals = user[4]
    claimed = user[5]

    earned = referrals // 5
    available = earned - claimed

    if available <= 0:
        remaining = 5 - (referrals % 5)

        await query.message.reply_text(
            "❌ هنوز جایزه‌ای برای دریافت نداری.\n\n"
            f"👥 دعوت فعلی: {referrals}\n"
            f"🎯 دعوت لازم: {remaining}"
        )
        return

    cur.execute("""
        SELECT id, config
        FROM configs
        WHERE used = 0
        ORDER BY id ASC
        LIMIT 1
    """)

    config = cur.fetchone()

    if not config:
        await query.message.reply_text(
            "⏳ جایزه شما ثبت شده، ولی موجودی کانفیگ تمام شده است."
        )
        return

    config_id = config[0]
    config_text = config[1]

    cur.execute("""
        UPDATE configs
        SET used = 1,
            used_by = ?
        WHERE id = ?
    """, (user_id, config_id))

    cur.execute("""
        UPDATE users
        SET claimed_rewards = claimed_rewards + 1
        WHERE user_id = ?
    """, (user_id,))

    db.commit()

    await query.message.reply_text(
        "🎁 تبریک!\n\n"
        "⭐ جایزه شما: ۵ گیگ کانفیگ\n\n"
        "🔐 کانفیگ:\n\n"
        f"{config_text}"
    )


async def admin_panel(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    cur.execute("SELECT COUNT(*) FROM users")
    users = cur.fetchone()[0]

    cur.execute("SELECT COUNT(*) FROM configs WHERE used = 0")
    configs = cur.fetchone()[0]

    cur.execute("SELECT SUM(referrals) FROM users")
    referrals = cur.fetchone()[0] or 0

    keyboard = [
        [InlineKeyboardButton("➕ شارژ کانفیگ", callback_data="add_config")],
        [InlineKeyboardButton("📦 موجودی کانفیگ", callback_data="inventory")],
        [InlineKeyboardButton("🗑 حذف همه کانفیگ‌ها", callback_data="delete_all")],
        [InlineKeyboardButton("📢 ارسال همگانی", callback_data="broadcast")],
        [InlineKeyboardButton("📣 عضویت اجباری", callback_data="force_join_info")],
        [InlineKeyboardButton("📊 آمار ربات", callback_data="bot_stats")]
    ]

    await query.message.reply_text(
        "👑 پنل مدیریت\n\n"
        f"👤 کاربران: {users}\n"
        f"👥 مجموع دعوت‌ها: {referrals}\n"
        f"📦 کانفیگ آماده: {configs}",
        reply_markup=InlineKeyboardMarkup(keyboard)
    )


async def force_join_info(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    await query.message.reply_text(
        "📣 عضویت اجباری\n\n"
        f"کانال فعال: {REQUIRED_CHANNEL}\n\n"
        f"🔗 {CHANNEL_LINK}\n\n"
        "ربات باید داخل کانال ادمین باشد."
    )


async def add_config_request(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    context.user_data["waiting_config"] = True
    context.user_data["waiting_broadcast"] = False

    await query.message.reply_text(
        "➕ شارژ کانفیگ\n\n"
        "هر خط = یک کانفیگ ۵ گیگی.\n\n"
        "مثال:\n"
        "vless://config1\n"
        "vless://config2\n"
        "vless://config3\n\n"
        "برای لغو /cancel را بزن."
    )


async def receive_config(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if update.effective_user.id != ADMIN_ID:
        return

    if not context.user_data.get("waiting_config"):
        return

    text = update.message.text.strip()

    configs = [
        line.strip()
        for line in text.splitlines()
        if line.strip()
    ]

    for config in configs:
        cur.execute(
            "INSERT INTO configs (config) VALUES (?)",
            (config,)
        )

    db.commit()

    context.user_data["waiting_config"] = False

    await update.message.reply_text(
        f"✅ {len(configs)} کانفیگ اضافه شد.\n\n"
        f"🎁 ظرفیت اضافه‌شده: {len(configs) * 5} گیگ"
    )


async def delete_all_confirm(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    cur.execute("SELECT COUNT(*) FROM configs")
    count = cur.fetchone()[0]

    keyboard = [[
        InlineKeyboardButton("✅ بله، حذف کن", callback_data="delete_all_yes"),
        InlineKeyboardButton("❌ لغو", callback_data="delete_all_no")
    ]]

    await query.message.reply_text(
        f"⚠️ هشدار!\n\nتعداد {count} کانفیگ موجود است.\n\n"
        "آیا مطمئنی همه حذف شوند؟",
        reply_markup=InlineKeyboardMarkup(keyboard)
    )


async def delete_all_yes(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    cur.execute("DELETE FROM configs")
    db.commit()

    await query.message.reply_text("🗑 همه کانفیگ‌ها حذف شدند.")


async def delete_all_no(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    await query.message.reply_text("❌ حذف لغو شد.")


async def inventory(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    cur.execute("SELECT COUNT(*) FROM configs WHERE used = 0")
    available = cur.fetchone()[0]

    cur.execute("SELECT COUNT(*) FROM configs WHERE used = 1")
    used = cur.fetchone()[0]

    await query.message.reply_text(
        "📦 موجودی\n\n"
        f"🟢 آماده: {available}\n"
        f"🔴 استفاده‌شده: {used}\n"
        f"📊 مجموع: {available + used}\n\n"
        f"💾 حجم قابل توزیع: {available * 5} گیگ"
    )


async def broadcast_request(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    context.user_data["waiting_broadcast"] = True
    context.user_data["waiting_config"] = False

    await query.message.reply_text(
        "📢 ارسال همگانی\n\n"
        "پیامت را بفرست تا برای تمام کاربران ارسال شود.\n\n"
        "برای لغو /cancel را بزن."
    )


async def broadcast_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if update.effective_user.id != ADMIN_ID:
        return

    if not context.user_data.get("waiting_broadcast"):
        return

    text = update.message.text.strip()
    context.user_data["waiting_broadcast"] = False

    cur.execute("SELECT user_id FROM users")
    users = cur.fetchall()

    sent = 0
    failed = 0

    for row in users:
        try:
            await context.bot.send_message(
                chat_id=row[0],
                text=text
            )
            sent += 1
        except TelegramError:
            failed += 1

    await update.message.reply_text(
        "📢 ارسال همگانی تمام شد.\n\n"
        f"✅ موفق: {sent}\n"
        f"❌ ناموفق: {failed}\n"
        f"👥 کل کاربران: {len(users)}"
    )


async def bot_stats(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if not is_admin(query.from_user.id):
        return

    cur.execute("SELECT COUNT(*) FROM users")
    users = cur.fetchone()[0]

    cur.execute("SELECT SUM(referrals) FROM users")
    referrals = cur.fetchone()[0] or 0

    cur.execute("SELECT SUM(claimed_rewards) FROM users")
    rewards = cur.fetchone()[0] or 0

    cur.execute("SELECT COUNT(*) FROM configs WHERE used = 0")
    configs = cur.fetchone()[0]

    await query.message.reply_text(
        "📊 آمار ربات\n\n"
        f"👤 کاربران: {users}\n"
        f"👥 مجموع دعوت‌ها: {referrals}\n"
        f"🎁 جوایز تحویل‌شده: {rewards}\n"
        f"💾 حجم تحویل‌شده: {rewards * 5} گیگ\n"
        f"📦 کانفیگ آماده: {configs}"
    )


async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if update.effective_user.id != ADMIN_ID:
        return

    context.user_data["waiting_config"] = False
    context.user_data["waiting_broadcast"] = False

    await update.message.reply_text("❌ عملیات لغو شد.")


async def handle_admin_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if update.effective_user.id != ADMIN_ID:
        return

    if context.user_data.get("waiting_config"):
        await receive_config(update, context)
        return

    if context.user_data.get("waiting_broadcast"):
        await broadcast_message(update, context)
        return


async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query

    if query.data == "check_join":
        await check_join(update, context)
    elif query.data == "my_link":
        await my_link(update, context)
    elif query.data == "stats":
        await stats(update, context)
    elif query.data == "reward":
        await reward(update, context)
    elif query.data == "admin":
        await admin_panel(update, context)
    elif query.data == "add_config":
        await add_config_request(update, context)
    elif query.data == "inventory":
        await inventory(update, context)
    elif query.data == "delete_all":
        await delete_all_confirm(update, context)
    elif query.data == "delete_all_yes":
        await delete_all_yes(update, context)
    elif query.data == "delete_all_no":
        await delete_all_no(update, context)
    elif query.data == "broadcast":
        await broadcast_request(update, context)
    elif query.data == "force_join_info":
        await force_join_info(update, context)
    elif query.data == "bot_stats":
        await bot_stats(update, context)


def main():
    app = Application.builder().token(BOT_TOKEN).build()

    app.add_handler(CommandHandler("start", start))
    app.add_handler(CommandHandler("cancel", cancel))
    app.add_handler(CallbackQueryHandler(button_handler))

    app.add_handler(
        MessageHandler(
            filters.TEXT & ~filters.COMMAND,
            handle_admin_text
        )
    )

    print("🤖 ربات با موفقیت اجرا شد...")
    app.run_polling()


if __name__ == "__main__":
    main()