from telegram import Update
from telegram.ext import ContextTypes, CallbackQueryHandler
from database.db import DB
from utils.keyboards import inline, main_menu_inline, remove_reply_kb
from utils.helpers import money
from utils.decorators import anti_flood
from services.notifications import notify_staff
from services.membership import is_member
from config import (REQUIRED_CHANNEL_LINK, REQUIRED_CHANNEL_ID,
                    FORCE_JOIN_ALWAYS, ADMIN_USERNAME, ADMIN_IDS)

WELCOME_HEAD = (
    "👋 Welcome to <b>GenBoost Store</b>!\n"
    "Your one-stop digital marketplace.\n"
)

def _join_kb():
    rows = [
        [("📢 Join Channel", REQUIRED_CHANNEL_LINK)],
        [("✅ Verify Join", "join:verify")],
    ]
    return inline(rows)

async def _show_join_gate(target_msg, first_time: bool):
    text = (
        "🔒 <b>Join Required</b>\n\n"
        "To use GenBoost Store, please join our official channel first.\n\n"
        "1. Tap <b>Join Channel</b> below\n"
        "2. Then tap <b>Verify Join</b> to continue"
    )
    if not first_time:
        text = "❌ You haven\u2019t joined yet. Please join the channel and tap Verify again.\n\n" + text
    await target_msg.reply_html(text, reply_markup=_join_kb())

async def _show_main_menu(target_msg, user_row, tg_user):
    from utils.premium_emoji import (pe, PE_NAME, PE_USER_ID, PE_WALLET,
                                     PE_REF_EARNINGS)
    text = (
        f"{pe('👤', PE_NAME)} <b>Name:</b> {tg_user.full_name}\n"
        f"{pe('🆔', PE_USER_ID)} <b>ID:</b> <code>{tg_user.id}</code>\n"
        f"{pe('💰', PE_WALLET)} <b>Wallet Balance:</b> {money(user_row['balance'])}\n"
        f"{pe('🎁', PE_REF_EARNINGS)} <b>Referral Earnings:</b> {money(user_row['referral_earnings'])}\n\n"
        "Choose an option below 👇"
    )
    await target_msg.reply_html(
        text,
        reply_markup=main_menu_inline(REQUIRED_CHANNEL_LINK),
    )

@anti_flood
async def start_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    u = update.effective_user
    args = context.args or []
    ref_id = None
    if args:
        try:
            cand = int(args[0])
            if cand != u.id:
                ref_id = cand
        except ValueError:
            pass

    existing = await DB.fetchone("SELECT * FROM users WHERE user_id=?", (u.id,))
    first_time = not existing
    if first_time:
        if ref_id:
            r = await DB.fetchone("SELECT user_id FROM users WHERE user_id=?", (ref_id,))
            if not r:
                ref_id = None
        await DB.execute(
            "INSERT INTO users(user_id, username, first_name, last_name, referred_by) "
            "VALUES (?,?,?,?,?)",
            (u.id, u.username, u.first_name, u.last_name, ref_id))
        await notify_staff(
            context.bot,
            f"🆕 <b>New User</b>\nID: <code>{u.id}</code>\n"
            f"Name: {u.full_name}\nUsername: @{u.username or '\u2014'}\n"
            f"Referred by: <code>{ref_id or '\u2014'}</code>")
        # Notify the inviter that someone joined through their link
        if ref_id:
            try:
                await context.bot.send_message(
                    ref_id,
                    f"👥 <b>New Referral Joined!</b>\n\n"
                    f"<b>{u.full_name}</b> just joined using your link.\n"
                    f"You'll earn rewards once they deposit or purchase.",
                    parse_mode="HTML")
            except Exception:
                pass
        existing = await DB.fetchone("SELECT * FROM users WHERE user_id=?", (u.id,))
    else:
        await DB.execute(
            "UPDATE users SET username=?, first_name=?, last_name=? WHERE user_id=?",
            (u.username, u.first_name, u.last_name, u.id))

    # Clear any old reply keyboard from previous versions
    try:
        await update.message.reply_text("\u2063", reply_markup=remove_reply_kb())
    except Exception:
        pass

    # Channel gate — ALWAYS re-check when REQUIRED_CHANNEL_ID is set,
    # so a user who later leaves the channel loses access on next /start.
    if REQUIRED_CHANNEL_ID and u.id not in ADMIN_IDS:
        if not await is_member(context.bot, u.id):
            await DB.execute("UPDATE users SET channel_verified=0 WHERE user_id=?", (u.id,))
            await _show_join_gate(update.message, first_time=True)
            return
        await DB.execute("UPDATE users SET channel_verified=1 WHERE user_id=?", (u.id,))
    elif REQUIRED_CHANNEL_ID and u.id in ADMIN_IDS:
        await DB.execute("UPDATE users SET channel_verified=1 WHERE user_id=?", (u.id,))

    existing = await DB.fetchone("SELECT * FROM users WHERE user_id=?", (u.id,))
    await _show_main_menu(update.message, existing, u)

async def verify_join_cb(update: Update, context: ContextTypes.DEFAULT_TYPE):
    q = update.callback_query
    u = q.from_user
    if u.id in ADMIN_IDS:
        await DB.execute("UPDATE users SET channel_verified=1 WHERE user_id=?", (u.id,))
        await q.answer("✅ Admin bypass verified.")
        existing = await DB.fetchone("SELECT * FROM users WHERE user_id=?", (u.id,))
        try:
            await q.message.delete()
        except Exception:
            pass
        await context.bot.send_message(
            chat_id=u.id,
            text=(
                f"<b>Name:</b> {u.full_name}\n"
                f"<b>ID:</b> <code>{u.id}</code>\n"
                f"<b>Wallet Balance:</b> {money(existing['balance'])}\n"
                f"<b>Referral Earnings:</b> {money(existing['referral_earnings'])}\n\n"
                "Choose an option below 👇"
            ),
            parse_mode="HTML",
            reply_markup=main_menu_inline(REQUIRED_CHANNEL_LINK),
        )
        return
    if not REQUIRED_CHANNEL_ID:
        await q.answer("Channel check is disabled.")
        return
    if await is_member(context.bot, u.id):
        await DB.execute("UPDATE users SET channel_verified=1 WHERE user_id=?", (u.id,))
        await q.answer("✅ Verified! Welcome.")
        existing = await DB.fetchone("SELECT * FROM users WHERE user_id=?", (u.id,))
        try:
            await q.message.delete()
        except Exception:
            pass
        # Send a fresh main-menu message via the bot (the original was deleted).
        from utils.helpers import money
        from utils.premium_emoji import (pe, PE_NAME, PE_USER_ID, PE_WALLET,
                                         PE_REF_EARNINGS)
        text = (
            f"{pe('👤', PE_NAME)} <b>Name:</b> {u.full_name}\n"
            f"{pe('🆔', PE_USER_ID)} <b>ID:</b> <code>{u.id}</code>\n"
            f"{pe('💰', PE_WALLET)} <b>Wallet Balance:</b> {money(existing['balance'])}\n"
            f"{pe('🎁', PE_REF_EARNINGS)} <b>Referral Earnings:</b> {money(existing['referral_earnings'])}\n\n"
            "Choose an option below 👇"
        )
        await context.bot.send_message(
            chat_id=u.id, text=text, parse_mode="HTML",
            reply_markup=main_menu_inline(REQUIRED_CHANNEL_LINK),
        )
    else:
        await q.answer("❌ Not joined yet. Please join the channel first.", show_alert=True)

def join_callback_handlers():
    return [CallbackQueryHandler(verify_join_cb, pattern=r"^join:verify$")]
