import asyncio
import logging
import re
# pyrefly: ignore [missing-import]
from telethon import events
from handlers.middleware import permission_check, is_admin
from database.manager import DatabaseManager
from utils.templates import (
    profile_template, balance_template, due_template, limit_info_template, product_stock_template, 
    product_rate_template, order_success_template, error_template, signup_success, signout_success,
    success_template, payment_template, prefix_info_template, uid_info_template, DIVIDER
)
from config import PAYMENT_INFO, USDT_RATE, COMMAND_PREFIX
from utils.api_helpers import get_uid_info

db = DatabaseManager()
logger = logging.getLogger("UserHandler")

async def deliver_stock(prod_name, qty):
    try:
        vouchers = await db.get_vouchers(prod_name, qty)
        if not vouchers:
            return None
        return vouchers
    except Exception as e:
        logger.error(f"Error delivering stock: {e}")
        return None

def register_user_handlers(client):
    
    @client.on(events.NewMessage)
    async def user_handler(event):
        try:
            if not await permission_check(event): return
            
            user_id = event.sender_id
            text = event.raw_text.strip()
            cmd_parts = text.split()
            if not cmd_parts: return
            
            cmd = cmd_parts[0].lower()
            prefix = COMMAND_PREFIX.lower()

            # --- Allow seeing prefix without ! or with prefix command ---
            if event.raw_text.lower().strip() == "prefix" or cmd == f"{prefix}prefix":
                return await event.reply(prefix_info_template(COMMAND_PREFIX))

            # 1. Fetch User Data
            user = await db.get_user(user_id)
            
            # --- AUTO UID DETECTION (Registered users/Admins only, no prefix) ---
            if event.raw_text.strip().isdigit() and 5 <= len(event.raw_text.strip()) <= 15:
                if user or is_admin(user_id):
                    uid = event.raw_text.strip()
                    msg = await event.reply("🔍 **Cʜᴇᴄᴋɪɴɢ...**")
                    result = await get_uid_info(uid)
                    
                    if result['status'] == 'success':
                        return await msg.edit(uid_info_template(result['uid'], result['name'], result['server']))
                    else:
                        err_msg = "❌ **Pʟᴀʏᴇʀ Nᴏᴛ Fᴏᴜɴᴅ**" if "not found" in result['message'].lower() else result['message']
                        return await msg.edit(error_template(err_msg))
                return

            # --- AUTO MATH CALCULATION ---
            math_text = event.raw_text.strip()
            # Must contain at least one number and one math operator, allowing floats/spaces
            if '**' not in math_text and re.match(r'^[\d\s\+\-\*\/\.]+$', math_text) and any(op in math_text for op in "+-*/") and any(c.isdigit() for c in math_text):
                try:
                    # Safe eval with no builtins
                    calc_result = eval(math_text, {"__builtins__": None}, {})
                    if isinstance(calc_result, float) and calc_result.is_integer():
                        calc_result = int(calc_result)
                    
                    calc_result_str = str(calc_result)
                    if len(calc_result_str) > 100:
                        calc_result_str = "Rᴇsᴜʟᴛ ᴛᴏᴏ ʟᴀʀɢᴇ"
                        
                    return await event.reply(f"🧮 **Cᴀʟᴄᴜʟᴀᴛɪᴏɴ**\n`{math_text}` = **{calc_result_str}**")
                except Exception:
                    pass

            # Registration Check: All user commands (except prefix) require registration
            # EXCEPT for ADMINS (they can bypass this)
            if not user and not is_admin(user_id):
                # List of all user commands to prevent responding to random prefix messages
                user_commands = ['profile', 'balance', 'due', 'limit', 'currency', 'stock', 'rate', 'number', 'verify', 'uc', 'uclimit', 'check']
                if cmd.replace(prefix, "") in user_commands:
                    return await event.reply(error_template("You are not registered. Please contact an admin."))
                
                # If not a recognized command, just return (don't show error to avoid spam)
                if event.raw_text.lower().startswith(prefix):
                    return
                return

            # --- COMMANDS ---

            # --- !profile ---
            if cmd == f"{prefix}profile":
                await event.reply(profile_template(
                    user['fullname'], user['user_id'], user['role'], user['status']
                ))

            # --- !balance ---
            elif cmd == f"{prefix}balance":
                db_usdt_rate = float(await db.get_setting("usdt_rate", 125))
                
                # Show balance based on user's preferred currency
                if user['currency'] == "BDT":
                    await event.reply(balance_template(
                        user['fullname'], user['balance'], user['due'], user['due_limit'], "BDT"
                    ))
                else:
                    # Convert BDT to USDT for display
                    usdt_balance = user['balance'] / db_usdt_rate
                    usdt_due = user['due'] / db_usdt_rate
                    usdt_limit = user['due_limit'] / db_usdt_rate
                    await event.reply(balance_template(
                        user['fullname'], usdt_balance, usdt_due, usdt_limit, "USDT"
                    ))

            # --- !due ---
            elif cmd == f"{prefix}due":
                await event.reply(due_template(user['fullname'], user['due'], user['currency']))

            # --- !limit ---
            elif cmd == f"{prefix}limit":
                await event.reply(limit_info_template(user['fullname'], user['due_limit'], user['currency']))

            # --- !currency [BDT/USDT] ---
            elif cmd == f"{prefix}currency":
                try:
                    new_curr = cmd_parts[1].upper()
                    if new_curr in ["BDT", "USDT"]:
                        await db.update_user_currency(user_id, new_curr)
                        await event.reply(success_template(f"Cᴜʀʀᴇɴᴄʏ sᴇᴛ ᴛᴏ `{new_curr}`"))
                    else:
                        await event.reply(error_template("Usᴇ `!currency BDT` ᴏʀ `!currency USDT`"))
                except IndexError:
                    await event.reply(error_template("Usage: `!currency BDT`"))

            # --- !stock ---
            elif cmd == f"{prefix}stock":
                products = await db.get_all_products()
                if not products:
                    return await event.reply(error_template("Nᴏ ᴘʀᴏᴅᴜᴄᴛs ᴀᴠᴀɪʟᴀʙʟᴇ."))
                await event.reply(product_stock_template(products))

            # --- !rate ---
            elif cmd == f"{prefix}rate":
                products = await db.get_all_products()
                if not products:
                    return await event.reply(error_template("Nᴏ ᴘʀᴏᴅᴜᴄᴛs ᴀᴠᴀɪʟᴀʙʟᴇ."))
                await event.reply(product_rate_template(products))

            # --- !number ---
            elif cmd == f"{prefix}number":
                info = await db.get_setting("payment_info", "No payment info set.")
                await event.reply(payment_template(info))

            # --- !verify [txnid] ---
            elif cmd == f"{prefix}verify":
                try:
                    txnid = cmd_parts[1]
                    # This would typically call an external API to verify
                    await event.reply(error_template("Tʀᴀɴsᴀᴄᴛɪᴏɴ Vᴇʀɪғɪᴄᴀᴛɪᴏɴ API ɴᴏᴛ ᴄᴏɴғɪɢᴜʀᴇᴅ."))
                except IndexError:
                    await event.reply(error_template("Usage: `!verify TXN_ID`"))

            # --- !uc [product_name] [qty] ---
            elif cmd == f"{prefix}uc":
                try:
                    prod_name = cmd_parts[1]
                    qty = int(cmd_parts[2]) if len(cmd_parts) > 2 else 1
                    
                    if qty <= 0:
                        return await event.reply(error_template("Qᴜᴀɴᴛɪᴛʏ ᴍᴜsᴛ ʙᴇ 1 ᴏʀ ᴍᴏʀᴇ."))
                        
                    product = await db.get_product(prod_name)
                    if not product:
                        return await event.reply(error_template(f"Pʀᴏᴅᴜᴄᴛ `{prod_name}` ɴᴏᴛ ғᴏᴜɴᴅ."))
                    
                    if product['stock'] < qty:
                        return await event.reply(error_template(f"Iɴsᴜғғɪᴄɪᴇɴᴛ sᴛᴏᴄᴋ! Aᴠᴀɪʟᴀʙʟᴇ: {product['stock']}"))
                    
                    total_price = product['rate'] * qty
                    
                    # Check Balance
                    if user['balance'] < total_price:
                        return await event.reply(error_template(f"Iɴsᴜғғɪᴄɪᴇɴᴛ Bᴀʟᴀɴᴄᴇ! Rᴇǫᴜɪʀᴇᴅ: {total_price} BDT"))
                    
                    # Deduct Balance and Stock
                    await db.update_balance(user_id, total_price, is_add=False)
                    await db.update_product(prod_name, increment_stock=-qty)
                    
                    # Deliver Stock
                    codes = await deliver_stock(prod_name, qty)
                    if codes:
                        code_text = "\n".join(codes)
                        await client.send_message(user_id, f"🎁 **Yᴏᴜʀ PᴜʀᴄʜᴀsᴇD Iᴛᴇᴍs**:\n\n{code_text}")
                        await event.reply(order_success_template(user['fullname'], prod_name, qty, total_price, user['balance'], codes, curr=user['currency']))
                    else:
                        # Refund if delivery failed
                        await db.update_balance(user_id, total_price, is_add=True)
                        await db.update_product(prod_name, increment_stock=qty)
                        await event.reply(error_template("Dᴇʟɪᴠᴇʀʏ ғᴀɪʟᴇᴅ. Bᴀʟᴀɴᴄᴇ ʀᴇғᴜɴᴅᴇᴅ."))

                except (IndexError, ValueError):
                    await event.reply(error_template(f"Usage: `{prefix}uc [product] [qty]`"))

            # --- !uclimit [product_name] [qty] ---
            elif cmd == f"{prefix}uclimit":
                try:
                    prod_name = cmd_parts[1]
                    qty = int(cmd_parts[2]) if len(cmd_parts) > 2 else 1
                    
                    if qty <= 0:
                        return await event.reply(error_template("Qᴜᴀɴᴛɪᴛʏ ᴍᴜsᴛ ʙᴇ 1 ᴏʀ ᴍᴏʀᴇ."))
                        
                    product = await db.get_product(prod_name)
                    if not product:
                        return await event.reply(error_template(f"Pʀᴏᴅᴜᴄᴛ `{prod_name}` ɴᴏᴛ ғᴏᴜɴᴅ."))
                    
                    if product['stock'] < qty:
                        return await event.reply(error_template(f"Iɴsᴜғғɪᴄɪᴇɴᴛ sᴛᴏᴄᴋ! Aᴠᴀɪʟᴀʙʟᴇ: {product['stock']}"))
                    
                    total_price = product['rate'] * qty
                    
                    # Check Due Limit
                    new_due = user['due'] + total_price
                    if new_due > user['due_limit']:
                        return await event.reply(error_template(f"Dᴜᴇ Lɪᴍɪᴛ Exᴄᴇᴇᴅᴇᴅ! Cᴀɴ'ᴛ ᴛᴀᴋᴇ ᴍᴏʀᴇ ᴛʜᴀɴ {user['due_limit']} BDT"))
                    
                    # Add to Due and Deduct Stock
                    await db.update_due(user_id, total_price, is_add=True)
                    await db.update_product(prod_name, increment_stock=-qty)
                    
                    # Deliver Stock
                    codes = await deliver_stock(prod_name, qty)
                    if codes:
                        code_text = "\n".join(codes)
                        await client.send_message(user_id, f"🎁 **Yᴏᴜʀ Pᴜʀᴄʜᴀsᴇᴅ Iᴛᴇᴍs (Dᴜᴇ)**:\n\n{code_text}")
                        await event.reply(order_success_template(user['fullname'], prod_name, qty, total_price, user['due'], codes, is_credit=True, curr=user['currency']))
                    else:
                        # Refund if delivery failed
                        await db.update_due(user_id, total_price, is_add=False)
                        await db.update_product(prod_name, increment_stock=qty)
                        await event.reply(error_template("Dᴇʟɪᴠᴇʀʏ ғᴀɪʟᴇᴅ. Dᴜᴇ ʀᴇᴠᴇʀᴛᴇᴅ."))

                except (IndexError, ValueError):
                    await event.reply(error_template(f"Usage: `{prefix}uclimit [product] [qty]`"))

            # --- !check [UID] [SERVER] ---
            elif cmd == f"{prefix}check":
                if len(cmd_parts) < 2:
                    return await event.reply(error_template(f"Usage: `{prefix}check [UID]`"))
                
                uid = cmd_parts[1]
                server = cmd_parts[2] if len(cmd_parts) > 2 else None
                
                msg = await event.reply("🔍 **Cʜᴇᴄᴋɪɴɢ...**")
                result = await get_uid_info(uid, server)
                
                if result['status'] == 'success':
                    await msg.edit(uid_info_template(result['uid'], result['name'], result['server']))
                else:
                    await msg.edit(error_template(result['message']))

            # --- !prefix ---
            elif cmd == f"{prefix}prefix":
                await event.reply(prefix_info_template(COMMAND_PREFIX))

            # --- Unknown Command Catch-all ---
            else:
                if is_admin(user_id): return
                if not text.lower().startswith(prefix): return

                p = COMMAND_PREFIX
                valid_cmds = f"""
❌ Iɴᴠᴀʟɪᴅ Cᴏᴍᴍᴀɴᴅ
━━━━━━━━━━━━━━━
Aᴠᴀɪʟᴀʙʟᴇ Cᴏᴍᴍᴀɴᴅs:
➪ `{p}profile`, `{p}balance`
➪ `{p}stock`, `{p}rate`, `{p}number`, `{p}check`
➪ `{p}verify`, `{p}uc`, `{p}uclimit`
➪ `{p}due`, `{p}limit`
━━━━━━━━━━━━━━━
"""
                await event.reply(valid_cmds)
        
        except Exception as e:
            logger.error(f"Error processing user message: {e}")
            try:
                await event.reply(error_template("Aɴ ɪɴᴛᴇʀɴᴀʟ ᴇʀʀᴏʀ ᴏᴄᴄᴜʀʀᴇᴅ. Pʟᴇᴀsᴇ ᴛʀʏ ʟᴀᴛᴇʀ."))
            except:
                pass
