"""GenBoost Store — Telegram Digital Marketplace Bot
Entrypoint. Run with: python main.py
"""
import logging
from telegram import Update
from telegram.ext import (Application, CommandHandler,
                          CallbackQueryHandler, ContextTypes)

from config import BOT_TOKEN
from database.db import DB
from utils.premium_emoji import install_bot_patch

# Install premium-emoji auto-wrapping on every outgoing HTML message.
# Must run BEFORE any handler is registered / any Bot instance is created.
install_bot_patch()

from handlers.start import start_cmd, join_callback_handlers
from handlers.dashboard import dashboard, menu_callback_handlers
from handlers.wallet import wallet_menu, wallet_history
from handlers.deposits import (conversation as deposit_conv,
                               status_handler as deposit_status_handler,
                               approve_cmd, reject_cmd)
from services import chain_watcher
from handlers.products import categories as products_menu, callback_handlers as prod_cbs
from handlers.orders import my_orders
from handlers.referrals import referrals
from handlers.support import (support_menu, show_faq, conversation as support_conv,
                              reply_cmd)
from handlers import admin as admin_h
from handlers.broadcast import broadcast as broadcast_cmd

logging.basicConfig(
    format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
    level=logging.INFO,
)
log = logging.getLogger("genboost")

# Inline-menu callback adapters
async def menu_products(update, context):
    await products_menu(update, context)

async def menu_orders(update, context):
    q = update.callback_query; await q.answer()
    # my_orders expects update.message; build a small adapter
    await my_orders.__wrapped__(_FakeUpdate(q), context) if False else await _orders_inline(update, context)

async def _orders_inline(update, context):
    q = update.callback_query
    uid = q.from_user.id
    from utils.helpers import money
    rows = await DB.fetchall(
        "SELECT id, product_name, amount, quantity, delivery_status, delivery_content, created_at "
        "FROM orders WHERE user_id=? ORDER BY id DESC LIMIT 20", (uid,))
    if not rows:
        text = "📦 You have no orders yet."
    else:
        parts = ["📦 <b>Your Orders</b>\n"]
        for r in rows:
            qty = r["quantity"] if "quantity" in r.keys() else 1
            parts.append(
                f"#{r['id']} — {r['product_name']} x{qty}\n"
                f"  {money(r['amount'])} • {r['delivery_status']} • {r['created_at'][:16]}")
        text = "\n".join(parts)
    from utils.keyboards import inline
    await q.edit_message_text(text, parse_mode="HTML",
        reply_markup=inline([[("⬅ Back", "menu:home")]]))

async def _referrals_inline(update, context):
    q = update.callback_query; await q.answer()
    uid = q.from_user.id
    from utils.helpers import referral_link, money
    from utils.keyboards import inline
    link = referral_link(uid)
    total = (await DB.fetchone("SELECT COUNT(*) AS c FROM users WHERE referred_by=?", (uid,)))["c"]
    active = (await DB.fetchone("SELECT COUNT(*) AS c FROM users WHERE referred_by=? AND is_active=1", (uid,)))["c"]
    earnings = (await DB.fetchone(
        "SELECT COALESCE(SUM(amount),0) AS s FROM referral_rewards WHERE referrer_id=?",
        (uid,)))["s"]
    bal = (await DB.fetchone("SELECT referral_earnings FROM users WHERE user_id=?", (uid,)))["referral_earnings"]
    text = (
        "🎁 <b>Referral Program</b>\n\n"
        "Invite your friends and earn real cash rewards! 💸\n\n"
        f"🔗 <b>Your invite link:</b>\n<code>{link}</code>\n\n"
        f"👥 Total Referrals: <b>{total}</b>\n"
        f"✅ Active Referrals: <b>{active}</b>\n"
        f"💰 Total Earnings: <b>{money(earnings)}</b>\n"
        f"💼 Available in Wallet: <b>{money(bal)}</b>\n\n"
        "💎 <b>How it works:</b>\n"
        "• Earn <b>$0.40</b> for every <b>$5</b> your referral spends on the bot.\n"
        "• Rewards are added to your wallet automatically.\n"
        "• You'll get a notification each time a reward is earned. 🔔"
    )
    await q.edit_message_text(text, parse_mode="HTML", disable_web_page_preview=True,
        reply_markup=inline([[("⬅ Back", "menu:home")]]))

async def on_error(update, context):
    log.exception("Unhandled error: %s", context.error)

async def post_init(app: Application):
    await DB.connect()
    log.info("Database ready.")
    chain_watcher.start(app.bot)

async def post_shutdown(app: Application):
    await chain_watcher.stop()
    await DB.close()

def build_app() -> Application:
    if not BOT_TOKEN:
        raise SystemExit("BOT_TOKEN missing. Copy .env.example to .env and fill it in.")
    app = (Application.builder()
           .token(BOT_TOKEN)
           .post_init(post_init)
           .post_shutdown(post_shutdown)
           .build())

    # Conversations FIRST
    app.add_handler(deposit_conv())
    app.add_handler(deposit_status_handler())
    app.add_handler(support_conv())
    app.add_handler(admin_h.product_wizard())

    # User commands
    app.add_handler(CommandHandler("start", start_cmd))
    app.add_handler(CommandHandler("menu", dashboard))
    app.add_handler(CommandHandler("dashboard", dashboard))

    # Admin commands
    app.add_handler(CommandHandler("admin", admin_h.admin_panel))
    app.add_handler(CommandHandler("stats", admin_h.stats))
    app.add_handler(CommandHandler("users", admin_h.users_cmd))
    app.add_handler(CommandHandler("setbal", admin_h.setbal))
    app.add_handler(CommandHandler("ban", admin_h.ban))
    app.add_handler(CommandHandler("unban", admin_h.unban))
    app.add_handler(CommandHandler("addcat", admin_h.addcat))
    app.add_handler(CommandHandler("cats", admin_h.cats_cmd))
    app.add_handler(CommandHandler("products", admin_h.products_cmd))
    app.add_handler(CommandHandler("delproduct", admin_h.delproduct))
    app.add_handler(CommandHandler("toggleproduct", admin_h.toggleproduct))
    app.add_handler(CommandHandler("setstock", admin_h.setstock))
    app.add_handler(CommandHandler("setprice", admin_h.setprice))
    app.add_handler(CommandHandler("rename", admin_h.rename_product))
    app.add_handler(CommandHandler("editdesc", admin_h.editdesc))
    app.add_handler(CommandHandler("editcontent", admin_h.editcontent))
    app.add_handler(CommandHandler("rencat", admin_h.rencat))
    app.add_handler(CommandHandler("delcat", admin_h.delcat))
    app.add_handler(CommandHandler("ids", admin_h.ids_cmd))
    app.add_handler(CommandHandler("pending", admin_h.pending))
    app.add_handler(CommandHandler("tickets", admin_h.tickets))
    app.add_handler(CommandHandler("announce", admin_h.announce))
    app.add_handler(CommandHandler("approve", approve_cmd))
    app.add_handler(CommandHandler("reject", reject_cmd))
    app.add_handler(CommandHandler("reply", reply_cmd))
    app.add_handler(CommandHandler("broadcast", broadcast_cmd))

    # Join gate callbacks
    for h in join_callback_handlers():
        app.add_handler(h)

    # Main menu callbacks
    for h in menu_callback_handlers():
        app.add_handler(h)
    app.add_handler(CallbackQueryHandler(menu_products, pattern=r"^menu:products$"))
    app.add_handler(CallbackQueryHandler(_orders_inline, pattern=r"^menu:orders$"))
    app.add_handler(CallbackQueryHandler(_referrals_inline, pattern=r"^menu:referrals$"))
    app.add_handler(CallbackQueryHandler(support_menu, pattern=r"^menu:support$"))

    # Product callbacks
    for h in prod_cbs():
        app.add_handler(h)

    # Wallet callbacks (kept for compatibility with /admin tools)
    app.add_handler(CallbackQueryHandler(wallet_history, pattern=r"^wallet:(deps|buys)$"))
    app.add_handler(CallbackQueryHandler(lambda u,c: wallet_menu(u,c), pattern=r"^wallet:menu$"))
    app.add_handler(CallbackQueryHandler(show_faq, pattern=r"^sup:faq$"))
    app.add_handler(CallbackQueryHandler(support_menu, pattern=r"^sup:menu$"))

    app.add_error_handler(on_error)
    return app

def main():
    app = build_app()
    log.info("Starting GenBoost Store bot (long polling)…")
    app.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == "__main__":
    main()
