import logging
import re
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes
from web3 import Web3
import requests
import time
import threading
import asyncio
from datetime import datetime

# Add this after the existing imports and before the RPCS config
def get_token_price_usd(token_symbol):
    """Get current USD price for a token from CoinGecko API"""
    try:
        # Map symbols to CoinGecko IDs
        coingecko_ids = {
            "ETH": "ethereum",
            "BNB": "binancecoin", 
            "MATIC": "matic-network",
            "BTC": "bitcoin"
        }
        
        coin_id = coingecko_ids.get(token_symbol.upper())
        if not coin_id:
            return None
            
        url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd"
        response = requests.get(url, timeout=10)
        
        if response.status_code == 200:
            data = response.json()
            return data.get(coin_id, {}).get('usd')
    except Exception as e:
        print(f"Error fetching price for {token_symbol}: {e}")
    return None

def format_usd_value(usd_value):
    """Format USD value with appropriate units"""
    if usd_value >= 1_000_000_000:
        return f"${usd_value/1_000_000_000:.2f}B"
    elif usd_value >= 1_000_000:
        return f"${usd_value/1_000_000:.2f}M"
    elif usd_value >= 1_000:
        return f"${usd_value/1_000:.2f}K"
    else:
        return f"${usd_value:.2f}"

# Configure logging
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

# === CONFIG ===
RPCS = {
    "ethereum": {
        "url": "https://mainnet.infura.io/v3/da244af5cf2a432fae2e242e308b5e63",
        "threshold": 300,  # ETH
        "explorer": "https://etherscan.io/tx/",
        "is_poa": False,
        "symbol": "ETH",
        "name": "Ethereum",
        "emoji": "🔷"
    },
    "bsc": {
        "url": "https://bsc-dataseed.binance.org/",
        "threshold": 3000,  # BNB
        "explorer": "https://bscscan.com/tx/",
        "is_poa": True,
        "symbol": "BNB",
        "name": "Binance Smart Chain",
        "emoji": "🟡"
    },
    "polygon": {
        "url": "https://polygon-rpc.com",
        "threshold": 1_000_000,  # MATIC
        "explorer": "https://polygonscan.com/tx/",
        "is_poa": True,
        "symbol": "MATIC",
        "name": "Polygon",
        "emoji": "🟣"
    },
    "bitcoin": {
        "url": "https://blockstream.info/api",  # Bitcoin REST API
        "threshold": 1.0,  # BTC
        "explorer": "https://blockstream.info/tx/",
        "is_poa": False,
        "symbol": "BTC",
        "name": "Bitcoin",
        "emoji": "🟠"
    },
}
TELEGRAM_BOT_TOKEN = "7527361997:AAEWCLh8j92_W1BMZUzEiG_7q9HwhqjP5p4"
TELEGRAM_CHAT_ID = "1206830002"

# Bot state management
bot_state = {
    "watchers": {},
    "active_chains": set(),
    "application": None,
    "user_thresholds": {}
}

# Request timeout configurations
REQUEST_TIMEOUTS = {
    "telegram": 30,  # Telegram API timeout
    "rpc": 15,       # RPC endpoint timeout
    "connection": 10  # Connection timeout
}

def send_telegram_alert(message):
    url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
    data = {"chat_id": TELEGRAM_CHAT_ID, "text": message, "parse_mode": "Markdown"}
    try:
        r = requests.post(url, data=data, timeout=REQUEST_TIMEOUTS["telegram"])
        if r.status_code != 200:
            print("Failed to send Telegram message:", r.text)
    except requests.exceptions.Timeout:
        print("Telegram API timeout - message may not have been sent")
    except Exception as e:
        print("Telegram error:", e)

async def send_bot_message(application, message):
    """Send message through bot with timeout handling"""
    try:
        await asyncio.wait_for(
            application.bot.send_message(
                chat_id=TELEGRAM_CHAT_ID, 
                text=message, 
                parse_mode="Markdown"
            ),
            timeout=REQUEST_TIMEOUTS["telegram"]
        )
    except asyncio.TimeoutError:
        logger.error("Bot message timeout")
    except Exception as e:
        logger.error(f"Bot message error: {e}")

def watch_chain(name, rpc_url, threshold, explorer_base, is_poa=False):
    # Use custom threshold if set, otherwise use the passed threshold
    effective_threshold = bot_state["user_thresholds"].get(name, threshold)
    
    # Create Web3 instance with timeout
    w3 = Web3(Web3.HTTPProvider(
        rpc_url, 
        request_kwargs={'timeout': REQUEST_TIMEOUTS["rpc"]}
    ))
    
    # Add POA middleware for chains that need it
    if is_poa:
        poa_middleware_injected = False
        
        # Try multiple import paths for different web3.py versions
        try:
            from web3.middleware import geth_poa_middleware
            w3.middleware_onion.inject(geth_poa_middleware, layer=0)
            poa_middleware_injected = True
            print(f"POA middleware (geth_poa_middleware) injected for {name}")
        except ImportError:
            try:
                from web3.middleware import ExtraDataToPOAMiddleware
                w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
                poa_middleware_injected = True
                print(f"POA middleware (ExtraDataToPOAMiddleware) injected for {name}")
            except ImportError:
                print(f"Warning: POA middleware not available for {name}. Will handle POA errors gracefully.")
        
        if not poa_middleware_injected:
            print(f"Failed to inject POA middleware for {name}")
    
    if not w3.is_connected():
        print(f"Failed to connect to {name}!")
        return
    print(f"Connected to {name} node.")

    print(f"Watching {name} for transactions over {effective_threshold} native tokens...")

    last_processed_block = w3.eth.block_number
    print(f"Starting to watch {name} from block {last_processed_block + 1}")

    while name in bot_state["active_chains"]:
        try:
            latest_block_number = w3.eth.block_number
            if latest_block_number > last_processed_block:
                for block_num in range(last_processed_block + 1, latest_block_number + 1):
                    if name not in bot_state["active_chains"]:
                        break
                    try:
                        block = w3.eth.get_block(block_num, full_transactions=True)
                        print(f"Scanning block {block.number} on {name} ({len(block.transactions)} txs)")
                        for tx in block.transactions:
                            value_native = w3.from_wei(tx['value'], 'ether')
                            # Use effective_threshold instead of threshold
                            if value_native >= effective_threshold:
                                # Get chain config for enhanced message
                                chain_config = RPCS.get(name, {})
                                chain_emoji = chain_config.get("emoji", "🔗")
                                chain_symbol = chain_config.get("symbol", "TOKEN")
                                chain_name = chain_config.get("name", name.title())
                                
                                explorer_link = f"{explorer_base}{tx['hash'].hex()}"
                                from_address = tx.get('from', 'N/A')
                                to_address = tx.get('to', 'N/A')
                                
                                # Get current gas price and calculate USD value (if possible)
                                gas_price = tx.get('gasPrice', 0)
                                gas_used = tx.get('gas', 0)
                                gas_fee_wei = gas_price * gas_used if gas_price and gas_used else 0
                                gas_fee_native = w3.from_wei(gas_fee_wei, 'ether') if gas_fee_wei > 0 else 0
                                
                                # Get USD price for the token
                                token_price_usd = get_token_price_usd(chain_symbol)
                                usd_value = None
                                gas_fee_usd = None
                                
                                if token_price_usd:
                                    # Convert Decimal to float before multiplication
                                    usd_value = float(value_native) * token_price_usd
                                    if gas_fee_native > 0:
                                        gas_fee_usd = float(gas_fee_native) * token_price_usd
                                
                                # Format the transaction value with proper decimals
                                if value_native >= 1000000:
                                    value_formatted = f"{value_native/1000000:.2f}M"
                                elif value_native >= 1000:
                                    value_formatted = f"{value_native/1000:.2f}K"
                                else:
                                    value_formatted = f"{value_native:.4f}"
                                
                                # Create detailed message with USD values
                                message = (
                                    f"🐋 *WHALE ALERT* {chain_emoji}\n"
                                    f"━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
                                    f"🌐 *Network:* {chain_name}\n"
                                    f"💰 *Amount:* `{value_formatted} {chain_symbol}`\n"
                                    f"📊 *Exact Value:* `{value_native:,.6f} {chain_symbol}`\n"
                                )
                                
                                # Add USD value if available
                                if usd_value:
                                    formatted_usd = format_usd_value(usd_value)
                                    message += f"💵 *USD Value:* `{formatted_usd}` (≈ ${usd_value:,.2f})\n"
                                    message += f"📈 *Token Price:* `${token_price_usd:.2f} USD`\n"
                                else:
                                    message += f"💵 *USD Value:* `Price data unavailable`\n"
                                
                                message += (
                                    f"\n📤 *From:*\n`{from_address}`\n\n"
                                    f"📥 *To:*\n`{to_address}`\n\n"
                                    f"🧱 *Block:* `{block.number:,}`\n"
                                    f"⛽ *Gas Price:* `{w3.from_wei(gas_price, 'gwei'):.2f} Gwei`\n"
                                )
                                
                                if gas_fee_native > 0:
                                    message += f"💸 *Gas Fee:* `{gas_fee_native:.6f} {chain_symbol}`"
                                    if gas_fee_usd:
                                        message += f" (${gas_fee_usd:.2f})"
                                    message += "\n"
                                
                                # Add whale classification based on USD value
                                whale_type = ""
                                if usd_value:
                                    if usd_value >= 10_000_000:  # $10M+
                                        whale_type = "🦈 *MEGA WHALE*"
                                    elif usd_value >= 1_000_000:  # $1M+
                                        whale_type = "🐋 *WHALE*"
                                    elif usd_value >= 100_000:   # $100K+
                                        whale_type = "🐟 *BIG FISH*"
                                    else:
                                        whale_type = "🐠 *FISH*"
                                    
                                    message += f"🏷️ *Classification:* {whale_type}\n"
                                
                                message += (
                                    f"🕐 *Time:* `{datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}`\n"
                                    f"🔍 *Transaction Hash:*\n`{tx['hash'].hex()}`\n\n"
                                    f"[🔗 View on Explorer]({explorer_link})\n"
                                    f"━━━━━━━━━━━━━━━━━━━━━━━━━━"
                                )
                                
                                print(message)
                                send_telegram_alert(message)
                                
                                # Also send through bot if available
                                if bot_state["application"]:
                                    asyncio.run_coroutine_threadsafe(
                                        send_bot_message(bot_state["application"], message),
                                        bot_state["application"]._loop
                                    )
                    except Exception as e:
                        # Handle extraData errors more specifically
                        if "extraData" in str(e):
                            print(f"Skipping block {block_num} on {name} due to extraData issue: {str(e)[:100]}...")
                            continue
                        else:
                            print(f"Error processing block {block_num} on {name}: {e}")
                            continue
                last_processed_block = latest_block_number

            # A short sleep to prevent spamming the RPC endpoint
            time.sleep(5)

        except Exception as e:
            print(f"{name} watcher error: {e}")
            time.sleep(15)
    
    print(f"Stopped watching {name}")

def watch_bitcoin_chain(name, api_base_url, threshold, explorer_base):
    """Watch Bitcoin blockchain using REST API"""
    effective_threshold = bot_state["user_thresholds"].get(name, threshold)
    
    print(f"Connected to {name} API.")
    print(f"Watching {name} for transactions over {effective_threshold} BTC...")
    print(f"Debug: Effective threshold = {effective_threshold} BTC")
    
    last_processed_block = None
    
    # Get initial block height
    try:
        response = requests.get(f"{api_base_url}/blocks/tip/height", timeout=REQUEST_TIMEOUTS["rpc"])
        if response.status_code == 200:
            last_processed_block = int(response.text)
            print(f"Starting to watch {name} from block {last_processed_block + 1}")
        else:
            print(f"Failed to get initial block height for {name}")
            return
    except Exception as e:
        print(f"Error getting initial block height for {name}: {e}")
        return
    
    consecutive_same_blocks = 0
    
    while name in bot_state["active_chains"]:
        try:
            # Get latest block height
            response = requests.get(f"{api_base_url}/blocks/tip/height", timeout=REQUEST_TIMEOUTS["rpc"])
            if response.status_code != 200:
                print(f"Failed to get latest block height for {name}")
                time.sleep(15)
                continue
                
            latest_block_height = int(response.text)
            
            # Enhanced debug logging
            if latest_block_height == last_processed_block:
                consecutive_same_blocks += 1
                if consecutive_same_blocks % 10 == 0:  # Log every 10th time
                    print(f"Debug: Still waiting for new block. Current: {latest_block_height}, checked {consecutive_same_blocks} times")
            else:
                consecutive_same_blocks = 0
                print(f"Debug: New block detected! Height: {latest_block_height}, Last processed: {last_processed_block}")
            
            if latest_block_height > last_processed_block:
                for block_height in range(last_processed_block + 1, latest_block_height + 1):
                    if name not in bot_state["active_chains"]:
                        break
                    
                    try:
                        print(f"Processing Bitcoin block {block_height}...")
                        
                        # Get block hash using block height
                        block_hash_response = requests.get(f"{api_base_url}/block-height/{block_height}", timeout=REQUEST_TIMEOUTS["rpc"])
                        if block_hash_response.status_code != 200:
                            print(f"Failed to get block hash for block height {block_height}")
                            continue

                        block_hash = block_hash_response.text.strip()

                        # # Get block data using block hash
                        # block_response = requests.get(f"{api_base_url}/block/{block_hash}", timeout=REQUEST_TIMEOUTS["rpc"])
                        # if block_response.status_code != 200:
                        #     print(f"Failed to get block {block_height} data")
                        #     continue

                        # block_data = block_response.json()
                        # block_hash = block_data.get('id')
                        
                        if not block_hash:
                            print(f"No block hash found for block {block_height}")
                            continue
                        
                        # Get block transactions
                        txs_response = requests.get(f"{api_base_url}/block/{block_hash}/txs", timeout=REQUEST_TIMEOUTS["rpc"])
                        if txs_response.status_code != 200:
                            print(f"Failed to get transactions for block {block_height}")
                            continue
                            
                        transactions = txs_response.json()
                        print(f"Scanning block {block_height} on {name} ({len(transactions)} txs)")
                        
                        large_tx_count = 0
                        
                        for tx in transactions:
                            try:
                                # Calculate total output value
                                total_output_satoshis = sum(output.get('value', 0) for output in tx.get('vout', []))
                                total_output_btc = total_output_satoshis / 100_000_000  # Convert satoshis to BTC
                                
                                # Debug output for transactions over 0.001 BTC
                                if total_output_btc >= 1:
                                    large_tx_count += 1
                                    print(f"Debug: Large tx #{large_tx_count}: {total_output_btc:.8f} BTC (threshold: {effective_threshold})")
                                
                                if total_output_btc >= effective_threshold:
                                    print(f"🚨 WHALE TRANSACTION FOUND! {total_output_btc:.8f} BTC")
                                    
                                    # Get chain config for enhanced message
                                    chain_config = RPCS.get(name, {})
                                    chain_emoji = chain_config.get("emoji", "🟠")
                                    chain_symbol = chain_config.get("symbol", "BTC")
                                    chain_name = chain_config.get("name", name.title())
                                    
                                    tx_hash = tx.get('txid', 'N/A')
                                    explorer_link = f"{explorer_base}{tx_hash}"
                                    
                                    # Get input and output addresses (simplified)
                                    input_addresses = []
                                    output_addresses = []
                                    
                                    for vin in tx.get('vin', []):
                                        if 'prevout' in vin and 'scriptpubkey_address' in vin['prevout']:
                                            input_addresses.append(vin['prevout']['scriptpubkey_address'])
                                    
                                    for vout in tx.get('vout', []):
                                        if 'scriptpubkey_address' in vout:
                                            output_addresses.append(vout['scriptpubkey_address'])
                                    
                                    from_address = input_addresses[0] if input_addresses else 'Coinbase/Unknown'
                                    to_address = output_addresses[0] if output_addresses else 'Unknown'
                                    
                                    # Get USD price for Bitcoin
                                    token_price_usd = get_token_price_usd(chain_symbol)
                                    usd_value = None
                                    
                                    if token_price_usd:
                                        usd_value = total_output_btc * token_price_usd
                                    
                                    # Format the transaction value
                                    if total_output_btc >= 1000:
                                        value_formatted = f"{total_output_btc/1000:.2f}K"
                                    else:
                                        value_formatted = f"{total_output_btc:.6f}"
                                    
                                    # Create detailed message
                                    message = (
                                        f"🐋 *WHALE ALERT* {chain_emoji}\n"
                                        f"━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
                                        f"🌐 *Network:* {chain_name}\n"
                                        f"💰 *Amount:* `{value_formatted} {chain_symbol}`\n"
                                        f"📊 *Exact Value:* `{total_output_btc:.8f} {chain_symbol}`\n"
                                    )
                                    
                                    # Add USD value if available
                                    if usd_value:
                                        formatted_usd = format_usd_value(usd_value)
                                        message += f"💵 *USD Value:* `{formatted_usd}` (≈ ${usd_value:,.2f})\n"
                                        message += f"📈 *Token Price:* `${token_price_usd:.2f} USD`\n"
                                    else:
                                        message += f"💵 *USD Value:* `Price data unavailable`\n"
                                    
                                    message += (
                                        f"\n📤 *From:*\n`{from_address}`\n\n"
                                        f"📥 *To:*\n`{to_address}`\n\n"
                                        f"🧱 *Block:* `{block_height:,}`\n"
                                        f"📊 *Outputs:* `{len(tx.get('vout', []))}`\n"
                                        f"📊 *Inputs:* `{len(tx.get('vin', []))}`\n"
                                    )
                                    
                                    # Add whale classification based on USD value
                                    if usd_value:
                                        if usd_value >= 10_000_000:  # $10M+
                                            whale_type = "🦈 *MEGA WHALE*"
                                        elif usd_value >= 1_000_000:  # $1M+
                                            whale_type = "🐋 *WHALE*"
                                        elif usd_value >= 100_000:   # $100K+
                                            whale_type = "🐟 *BIG FISH*"
                                        else:
                                            whale_type = "🐠 *FISH*"
                                        
                                        message += f"🏷️ *Classification:* {whale_type}\n"
                                    
                                    message += (
                                        f"🕐 *Time:* `{datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}`\n"
                                        f"🔍 *Transaction Hash:*\n`{tx_hash}`\n\n"
                                        f"[🔗 View on Explorer]({explorer_link})\n"
                                        f"━━━━━━━━━━━━━━━━━━━━━━━━━━"
                                    )
                                    
                                    print(message)
                                    send_telegram_alert(message)
                                    
                                    # Also send through bot if available
                                    if bot_state["application"]:
                                        asyncio.run_coroutine_threadsafe(
                                            send_bot_message(bot_state["application"], message),
                                            bot_state["application"]._loop
                                        )
                            except Exception as e:
                                print(f"Error processing Bitcoin transaction: {e}")
                                continue
                        
                        if large_tx_count > 0:
                            print(f"Block {block_height} summary: {large_tx_count} transactions over 0.001 BTC found")
                        else:
                            print(f"Block {block_height} summary: No large transactions found")
                                
                    except Exception as e:
                        print(f"Error processing Bitcoin block {block_height}: {e}")
                        continue
                        
                last_processed_block = latest_block_height
            
            # Sleep to prevent API rate limiting
            time.sleep(10)  # Bitcoin blocks are ~10 minutes apart
            
        except Exception as e:
            print(f"{name} watcher error: {e}")
            time.sleep(30)  # Longer sleep on error for Bitcoin
    
    print(f"Stopped watching {name}")

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Start command handler"""
    welcome_message = (
        "🐋 *WHALE TRACKER BOT* 🐋\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        "🌊 *Monitor Large Transactions Across Multiple Blockchains*\n\n"
        "📊 *Current Monitoring Thresholds:*\n"
        f"🔷 Ethereum: `≥{bot_state['user_thresholds'].get('ethereum', RPCS['ethereum']['threshold']):,} ETH`\n"
        f"🟡 BSC: `≥{bot_state['user_thresholds'].get('bsc', RPCS['bsc']['threshold']):,} BNB`\n"
        f"🟣 Polygon: `≥{bot_state['user_thresholds'].get('polygon', RPCS['polygon']['threshold']):,} MATIC`\n"
        f"🟠 Bitcoin: `≥{bot_state['user_thresholds'].get('bitcoin', RPCS['bitcoin']['threshold']):,} BTC`\n\n"
        "🎛️ *Control Panel:*\n"
        "Use the buttons below to manage your whale watchers"
    )
    
    keyboard = [
        [InlineKeyboardButton("📊 Status Dashboard", callback_data="status")],
        [InlineKeyboardButton("🎯 Threshold Settings", callback_data="threshold_menu")],
        [InlineKeyboardButton("▶️ Start All Watchers", callback_data="start_all"),
         InlineKeyboardButton("⏹️ Stop All Watchers", callback_data="stop_all")],
        [InlineKeyboardButton("⚙️ Individual Chain Controls", callback_data="chain_controls")]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await update.message.reply_text(welcome_message, reply_markup=reply_markup, parse_mode="Markdown")

async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Handle button callbacks"""
    query = update.callback_query
    await query.answer()
    
    if query.data == "status":
        await show_status(query)
    elif query.data == "start_all":
        await start_all_watchers(query)
    elif query.data == "stop_all":
        await stop_all_watchers(query)
    elif query.data == "chain_controls":
        await show_chain_controls(query)
    elif query.data == "threshold_menu":
        await show_threshold_menu(query)
    elif query.data.startswith("set_threshold_"):
        chain = query.data.replace("set_threshold_", "")
        await show_threshold_input(query, chain)
    elif query.data.startswith("reset_threshold_"):
        chain = query.data.replace("reset_threshold_", "")
        await reset_threshold_via_menu(query, chain)
    elif query.data.startswith("quick_set_"):
        # Handle quick set buttons
        parts = query.data.replace("quick_set_", "").split("_")
        if len(parts) >= 2:
            chain = parts[0]
            try:
                threshold = float("_".join(parts[1:]))  # Handle values with underscores
                await quick_set_threshold(query, chain, threshold)
            except ValueError:
                await query.edit_message_text("❌ Invalid threshold value", parse_mode="Markdown")
    elif query.data.startswith("start_"):
        chain = query.data.replace("start_", "")
        await start_chain_watcher(query, chain)
    elif query.data.startswith("stop_"):
        chain = query.data.replace("stop_", "")
        await stop_chain_watcher(query, chain)
    elif query.data == "back_main":
        await show_main_menu(query)
    elif query.data == "back_threshold":
        await show_threshold_menu(query)

async def show_status(query) -> None:
    """Show current status of all watchers"""
    active_count = len(bot_state["active_chains"])
    total_count = len(RPCS)
    
    status_text = (
        "📊 *WATCHER STATUS DASHBOARD*\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        f"🎯 *Overview:* {active_count}/{total_count} watchers active\n\n"
    )
    
    for chain, config in RPCS.items():
        chain_emoji = config.get("emoji", "🔗")
        chain_name = config.get("name", chain.title())
        chain_symbol = config.get("symbol", "TOKEN")
        
        status = "🟢 *ACTIVE*" if chain in bot_state["active_chains"] else "🔴 *STOPPED*"
        current_threshold = bot_state["user_thresholds"].get(chain, config["threshold"])
        default_threshold = config["threshold"]
        
        status_text += f"{chain_emoji} *{chain_name}:*\n"
        status_text += f"   Status: {status}\n"
        status_text += f"   Threshold: `{current_threshold:,} {chain_symbol}`"
        
        if current_threshold != default_threshold:
            status_text += f" ⚠️ *(Custom)*"
        else:
            status_text += f" ✅ *(Default)*"
        status_text += "\n\n"
    
    status_text += (
        f"━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
        f"🕐 *Last Updated:* `{datetime.now().strftime('%H:%M:%S UTC')}`\n"
        f"📱 *Chat ID:* `{TELEGRAM_CHAT_ID}`"
    )
    
    keyboard = [
        [InlineKeyboardButton("🎯 Manage Thresholds", callback_data="threshold_menu")],
        [InlineKeyboardButton("🔄 Refresh Status", callback_data="status")],
        [InlineKeyboardButton("🔙 Back to Main", callback_data="back_main")]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(status_text, reply_markup=reply_markup, parse_mode="Markdown")


async def start_all_watchers(query) -> None:
    """Start all chain watchers"""
    started_chains = []
    
    for chain, cfg in RPCS.items():
        if chain not in bot_state["active_chains"]:
            bot_state["active_chains"].add(chain)
            if chain == "bitcoin":
                t = threading.Thread(
                    target=watch_bitcoin_chain, 
                    args=(chain, cfg["url"], cfg["threshold"], cfg["explorer"])
                )
            else:
                t = threading.Thread(
                    target=watch_chain, 
                    args=(chain, cfg["url"], cfg["threshold"], cfg["explorer"], cfg.get("is_poa", False))
                )
            t.daemon = True
            t.start()
            bot_state["watchers"][chain] = t
            started_chains.append(f"{cfg.get('emoji', '🔗')} {cfg.get('name', chain.title())}")
    
    if started_chains:
        message = (
            "✅ *WATCHERS STARTED SUCCESSFULLY*\n"
            "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
            f"🚀 *Started watchers for:*\n"
            f"{'• ' + chr(10) + '• '.join(started_chains)}\n\n"
            f"🔍 *Now monitoring for whale transactions...*\n"
            f"📱 *Alerts will be sent to this chat*"
        )
    else:
        message = (
            "ℹ️ *ALL WATCHERS ALREADY RUNNING*\n"
            "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
            "🟢 All blockchain watchers are currently active\n"
            "🔍 Monitoring for whale transactions across all networks"
        )
    
    keyboard = [
        [InlineKeyboardButton("📊 View Status", callback_data="status")],
        [InlineKeyboardButton("🔙 Back to Main", callback_data="back_main")]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def stop_all_watchers(query) -> None:
    """Stop all chain watchers"""
    stopped_chains = []
    for chain in list(bot_state["active_chains"]):
        config = RPCS.get(chain, {})
        stopped_chains.append(f"{config.get('emoji', '🔗')} {config.get('name', chain.title())}")
    
    bot_state["active_chains"].clear()
    
    if stopped_chains:
        message = (
            "⏹️ *WATCHERS STOPPED SUCCESSFULLY*\n"
            "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
            f"🛑 *Stopped watchers for:*\n"
            f"{'• ' + chr(10) + '• '.join(stopped_chains)}\n\n"
            f"💤 *No longer monitoring for whale transactions*\n"
            f"▶️ *Use 'Start All Watchers' to resume monitoring*"
        )
    else:
        message = (
            "ℹ️ *NO WATCHERS WERE RUNNING*\n"
            "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
            "🔴 All blockchain watchers were already stopped\n"
            "▶️ Use 'Start All Watchers' to begin monitoring"
        )
    
    keyboard = [
        [InlineKeyboardButton("▶️ Start All Watchers", callback_data="start_all")],
        [InlineKeyboardButton("🔙 Back to Main", callback_data="back_main")]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def show_chain_controls(query) -> None:
    """Show individual chain controls"""
    message = (
        "⚙️ *INDIVIDUAL CHAIN CONTROLS*\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        "🎛️ *Start or stop watchers for specific blockchains:*\n\n"
    )
    
    keyboard = []
    
    for chain, config in RPCS.items():
        chain_emoji = config.get("emoji", "🔗")
        chain_name = config.get("name", chain.title())
        status_emoji = "🟢" if chain in bot_state["active_chains"] else "🔴"
        
        message += f"{chain_emoji} *{chain_name}:* {status_emoji}\n"
        
        start_btn = InlineKeyboardButton(f"▶️ Start {chain_name}", callback_data=f"start_{chain}")
        stop_btn = InlineKeyboardButton(f"⏹️ Stop {chain_name}", callback_data=f"stop_{chain}")
        keyboard.append([start_btn, stop_btn])
    
    message += (
        f"\n━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
        f"💡 *Tip:* Individual controls allow you to monitor\n"
        f"specific networks based on your preferences"
    )
    
    keyboard.append([InlineKeyboardButton("🔙 Back to Main", callback_data="back_main")])
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def start_chain_watcher(query, chain: str) -> None:
    """Start a specific chain watcher"""
    config = RPCS.get(chain, {})
    chain_emoji = config.get("emoji", "🔗")
    chain_name = config.get("name", chain.title())
    chain_symbol = config.get("symbol", "TOKEN")
    
    if chain in bot_state["active_chains"]:
        message = (
            f"ℹ️ *WATCHER ALREADY RUNNING*\n"
            f"━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
            f"{chain_emoji} *{chain_name}* watcher is already active\n"
            f"🔍 Currently monitoring for transactions ≥ "
            f"`{bot_state['user_thresholds'].get(chain, config['threshold']):,} {chain_symbol}`"
        )
    else:
        cfg = RPCS[chain]
        bot_state["active_chains"].add(chain)
        if chain == "bitcoin":
            t = threading.Thread(
                target=watch_bitcoin_chain, 
                args=(chain, cfg["url"], cfg["threshold"], cfg["explorer"])
            )
        else:
            t = threading.Thread(
                target=watch_chain, 
                args=(chain, cfg["url"], cfg["threshold"], cfg["explorer"], cfg.get("is_poa", False))
            )
        t.daemon = True
        t.start()
        bot_state["watchers"][chain] = t
        
        current_threshold = bot_state["user_thresholds"].get(chain, config["threshold"])
        message = (
            f"✅ *WATCHER STARTED SUCCESSFULLY*\n"
            f"━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
            f"{chain_emoji} *{chain_name}* watcher is now active\n"
            f"🎯 *Threshold:* `{current_threshold:,} {chain_symbol}`\n"
            f"🔍 *Monitoring:* Large transactions on {chain_name}\n"
            f"📱 *Alerts:* Will be sent to this chat"
        )
    
    keyboard = [
        [InlineKeyboardButton("📊 View Status", callback_data="status")],
        [InlineKeyboardButton("🔙 Back to Controls", callback_data="chain_controls")]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def stop_chain_watcher(query, chain: str) -> None:
    """Stop a specific chain watcher"""
    config = RPCS.get(chain, {})
    chain_emoji = config.get("emoji", "🔗")
    chain_name = config.get("name", chain.title())
    
    if chain not in bot_state["active_chains"]:
        message = (
            f"ℹ️ *WATCHER NOT RUNNING*\n"
            f"━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
            f"{chain_emoji} *{chain_name}* watcher is not currently active\n"
            f"▶️ Use the start button to begin monitoring"
        )
    else:
        bot_state["active_chains"].discard(chain)
        message = (
            f"⏹️ *WATCHER STOPPED SUCCESSFULLY*\n"
            f"━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
            f"{chain_emoji} *{chain_name}* watcher has been stopped\n"
            f"💤 No longer monitoring {chain_name} transactions\n"
            f"▶️ Use the start button to resume monitoring"
        )
    
    keyboard = [
        [InlineKeyboardButton("📊 View Status", callback_data="status")],
        [InlineKeyboardButton("🔙 Back to Controls", callback_data="chain_controls")]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def show_main_menu(query) -> None:
    """Show main menu"""
    keyboard = [
        [InlineKeyboardButton("📊 Status Dashboard", callback_data="status")],
        [InlineKeyboardButton("🎯 Threshold Settings", callback_data="threshold_menu")],
        [InlineKeyboardButton("▶️ Start All Watchers", callback_data="start_all"),
         InlineKeyboardButton("⏹️ Stop All Watchers", callback_data="stop_all")],
        [InlineKeyboardButton("⚙️ Individual Chain Controls", callback_data="chain_controls")]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    welcome_message = (
        "🐋 *WHALE TRACKER BOT* 🐋\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        "🌊 *Monitor Large Transactions Across Multiple Blockchains*\n\n"
        "📊 *Current Monitoring Thresholds:*\n"
        f"🔷 Ethereum: `≥{bot_state['user_thresholds'].get('ethereum', RPCS['ethereum']['threshold']):,} ETH`\n"
        f"🟡 BSC: `≥{bot_state['user_thresholds'].get('bsc', RPCS['bsc']['threshold']):,} BNB`\n"
        f"🟣 Polygon: `≥{bot_state['user_thresholds'].get('polygon', RPCS['polygon']['threshold']):,} MATIC`\n"
        f"🟠 Bitcoin: `≥{bot_state['user_thresholds'].get('bitcoin', RPCS['bitcoin']['threshold']):,} BTC`\n\n"
        "🎛️ *Control Panel:*\n"
        "Use the buttons below to manage your whale watchers"
    )
    
    await query.edit_message_text(welcome_message, reply_markup=reply_markup, parse_mode="Markdown")

async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Help command handler"""
    help_text = (
        "🐋 *WHALE TRACKER BOT HELP* 🐋\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        "📖 *COMMAND REFERENCE:*\n\n"
        "🎛️ *Main Commands:*\n"
        "`/start` - Show main control panel\n"
        "`/help` - Display this help message\n"
        "`/status` - Quick status overview\n"
        "`/thresholds` - Show current thresholds\n\n"
        "🎯 *Threshold Management:*\n"
        "`/threshold_menu` - Visual threshold settings\n"
        "`/setthreshold <chain> <amount>` - Set custom threshold\n"
        "`/resetthreshold <chain>` - Reset to default\n\n"
        "💡 *Example Commands:*\n"
        "`/setthreshold ethereum 100`\n"
        "`/setthreshold bsc 5000`\n"
        "`/resetthreshold polygon`\n\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        "🌟 *KEY FEATURES:*\n\n"
        "🔍 *Real-time Monitoring:*\n"
        "• Live whale transaction detection\n"
        "• Multi-blockchain support\n"
        "• Instant Telegram notifications\n\n"
        "⚙️ *Advanced Controls:*\n"
        "• Individual chain management\n"
        "• Custom threshold settings\n"
        "• Visual control interface\n"
        "• Automatic error recovery\n\n"
        "📊 *Supported Networks:*\n"
        f"🔷 *Ethereum* - Default: `{RPCS['ethereum']['threshold']:,} ETH`\n"
        f"🟡 *BSC* - Default: `{RPCS['bsc']['threshold']:,} BNB`\n"
        f"🟣 *Polygon* - Default: `{RPCS['polygon']['threshold']:,} MATIC`\n"
        f"🟠 *Bitcoin* - Default: `{RPCS['bitcoin']['threshold']:,} BTC`\n\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        "🎯 *Quick Start:*\n"
        "1️⃣ Use `/start` to open control panel\n"
        "2️⃣ Set your preferred thresholds\n"
        "3️⃣ Start watchers for desired chains\n"
        "4️⃣ Receive whale alerts instantly!\n\n"
        "💬 *Need help?* Use `/start` to access the interactive control panel"
    )
    
    await update.message.reply_text(help_text, parse_mode="Markdown")

async def status_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Quick status command"""
    active_count = len(bot_state["active_chains"])
    total_count = len(RPCS)
    
    status_text = (
        "📊 *QUICK STATUS OVERVIEW*\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        f"🎯 *Active Watchers:* {active_count}/{total_count}\n\n"
    )
    
    for chain, config in RPCS.items():
        chain_emoji = config.get("emoji", "🔗")
        chain_name = config.get("name", chain.title())
        status_emoji = "🟢" if chain in bot_state["active_chains"] else "🔴"
        current_threshold = bot_state["user_thresholds"].get(chain, config["threshold"])
        chain_symbol = config.get("symbol", "TOKEN")
        
        status_text += f"{status_emoji} {chain_emoji} *{chain_name}*\n"
        status_text += f"   Threshold: `{current_threshold:,} {chain_symbol}`\n"
    
    status_text += (
        f"\n━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
        f"🕐 *Updated:* `{datetime.now().strftime('%H:%M:%S UTC')}`\n\n"
        f"💡 Use `/start` for full control panel"
    )
    
    await update.message.reply_text(status_text, parse_mode="Markdown")

async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Log errors caused by Updates."""
    logger.warning('Update "%s" caused error "%s"', update, context.error)

async def set_threshold_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Handle /setthreshold command"""
    if not context.args or len(context.args) != 2:
        help_text = (
            "🔧 *Set Threshold Help*\n\n"
            "*Usage:* `/setthreshold <chain> <amount>`\n\n"
            "*Examples:*\n"
            "• `/setthreshold ethereum 100` - Set ETH threshold to 100\n"
            "• `/setthreshold bsc 5000` - Set BNB threshold to 5000\n"
            "• `/setthreshold polygon 500000` - Set MATIC threshold to 500,000\n"
            "• `/setthreshold bitcoin 1` - Set BTC threshold to 1\n\n"
            "*Available chains:*\n"
            "• ethereum\n"
            "• bsc\n"
            "• polygon\n"
            "• bitcoin\n\n"
            "*Current thresholds:*\n"
        )
        
        for chain, config in RPCS.items():
            current_threshold = bot_state["user_thresholds"].get(chain, config["threshold"])
            help_text += f"• {chain}: {current_threshold:,}\n"
        
        await update.message.reply_text(help_text, parse_mode="Markdown")
        return
    
    chain = context.args[0].lower()
    try:
        threshold = float(context.args[1])
        if threshold <= 0:
            raise ValueError("Threshold must be positive")
    except ValueError:
        await update.message.reply_text(
            "❌ Invalid threshold amount. Please enter a positive number.",
            parse_mode="Markdown"
        )
        return
    
    if chain not in RPCS:
        available_chains = ", ".join(RPCS.keys())
        await update.message.reply_text(
            f"❌ Unknown chain '{chain}'. Available chains: {available_chains}",
            parse_mode="Markdown"
        )
        return
    
    # Store the custom threshold
    bot_state["user_thresholds"][chain] = threshold
    
    # If the chain is currently active, we need to restart it with the new threshold
    restart_needed = chain in bot_state["active_chains"]
    if restart_needed:
        # Stop the current watcher
        bot_state["active_chains"].discard(chain)
        await asyncio.sleep(1)  # Give it a moment to stop
        
        # Start with new threshold
        bot_state["active_chains"].add(chain)
        cfg = RPCS[chain]
        if chain == "bitcoin":
            t = threading.Thread(
                target=watch_bitcoin_chain, 
                args=(chain, cfg["url"], threshold, cfg["explorer"])
            )
        else:
            t = threading.Thread(
                target=watch_chain, 
                args=(chain, cfg["url"], threshold, cfg["explorer"], cfg.get("is_poa", False))
            )
        t.daemon = True
        t.start()
        bot_state["watchers"][chain] = t
    
    message = (
        f"✅ *Threshold Updated*\n\n"
        f"Chain: {chain.title()}\n"
        f"New threshold: {threshold:,} tokens\n"
    )
    
    if restart_needed:
        message += f"\n🔄 Watcher restarted with new threshold"
    else:
        message += f"\n💡 Start the {chain} watcher to use the new threshold"
    
    await update.message.reply_text(message, parse_mode="Markdown")

async def show_thresholds(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Show current thresholds"""
    message = (
        "🎯 *CURRENT THRESHOLD SETTINGS*\n"
        "━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
    )
    
    for chain, config in RPCS.items():
        chain_emoji = config.get("emoji", "🔗")
        chain_name = config.get("name", chain.title())
        chain_symbol = config.get("symbol", "TOKEN")
        current_threshold = bot_state["user_thresholds"].get(chain, config["threshold"])
        default_threshold = config["threshold"]
        status_emoji = "🟢" if chain in bot_state["active_chains"] else "🔴"
        
        message += f"{chain_emoji} *{chain_name}:*\n"
        message += f"   Status: {status_emoji}\n"
        message += f"   Current: `{current_threshold:,} {chain_symbol}`\n"
        
        if current_threshold != default_threshold:
            message += f"   Default: `{default_threshold:,} {chain_symbol}` ⚠️ *Custom*\n"
        else:
            message += f"   ✅ *Using Default Value*\n"
        message += "\n"
    
    message += (
        f"━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
        f"🔧 *Management Commands:*\n"
        f"• `/setthreshold <chain> <amount>` - Set custom threshold\n"
        f"• `/resetthreshold <chain>` - Reset to default\n"
        f"• `/threshold_menu` - Visual threshold manager\n\n"
        f"💡 *Examples:*\n"
        f"• `/setthreshold ethereum 100`\n"
        f"• `/setthreshold bsc 5000`\n"
        f"• `/resetthreshold polygon`\n\n"
        f"📖 Use `/help` for complete command reference"
    )
    
    await update.message.reply_text(message, parse_mode="Markdown")

async def reset_threshold_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Reset threshold to default"""
    if not context.args or len(context.args) != 1:
        await update.message.reply_text(
            "🔧 *Reset Threshold Help*\n\n"
            "*Usage:* `/resetthreshold <chain>`\n\n"
            "*Examples:*\n"
            "• `/resetthreshold ethereum`\n"
            "• `/resetthreshold bsc`\n"
            "• `/resetthreshold polygon`\n"
            "• `/resetthreshold bitcoin`",
            parse_mode="Markdown"
        )
        return
    
    chain = context.args[0].lower()
    
    if chain not in RPCS:
        available_chains = ", ".join(RPCS.keys())
        await update.message.reply_text(
            f"❌ Unknown chain '{chain}'. Available chains: {available_chains}",
            parse_mode="Markdown"
        )
        return
    
    # Remove custom threshold (will fall back to default)
    if chain in bot_state["user_thresholds"]:
        del bot_state["user_thresholds"][chain]
    
    default_threshold = RPCS[chain]["threshold"]
    
    # Restart watcher if active
    restart_needed = chain in bot_state["active_chains"]
    if restart_needed:
        bot_state["active_chains"].discard(chain)
        await asyncio.sleep(1)
        
        bot_state["active_chains"].add(chain)
        cfg = RPCS[chain]
        if chain == "bitcoin":
            t = threading.Thread(
                target=watch_bitcoin_chain, 
                args=(chain, cfg["url"], default_threshold, cfg["explorer"])
            )
        else:
            t = threading.Thread(
                target=watch_chain, 
                args=(chain, cfg["url"], default_threshold, cfg["explorer"], cfg.get("is_poa", False))
            )
        t.daemon = True
        t.start()
        bot_state["watchers"][chain] = t
    
    message = (
        f"✅ *Threshold Reset*\n\n"
        f"Chain: {chain.title()}\n"
        f"Reset to default: {default_threshold:,} tokens\n"
    )
    
    if restart_needed:
        message += f"\n🔄 Watcher restarted with default threshold"
    
    await update.message.reply_text(message, parse_mode="Markdown")

async def show_threshold_menu(query) -> None:
    """Show threshold management menu"""
    message = "🎯 *Threshold Settings*\n\n"
    
    for chain, config in RPCS.items():
        current_threshold = bot_state["user_thresholds"].get(chain, config["threshold"])
        default_threshold = config["threshold"]
        status = "🟢 Active" if chain in bot_state["active_chains"] else "🔴 Stopped"
        
        message += f"*{chain.title()}:* {current_threshold:,}"
        if current_threshold != default_threshold:
            message += f" ⚠️ (default: {default_threshold:,})"
        else:
            message += f" ✅ (default)"
        message += f" - {status}\n"
    
    message += "\n💡 Select a chain to modify its threshold:"
    
    keyboard = []
    for chain in RPCS.keys():
        current_threshold = bot_state["user_thresholds"].get(chain, RPCS[chain]["threshold"])
        is_custom = chain in bot_state["user_thresholds"]
        
        # Create row with set and reset buttons
        set_btn = InlineKeyboardButton(
            f"📝 {chain.title()} ({current_threshold:,})", 
            callback_data=f"set_threshold_{chain}"
        )
        
        if is_custom:
            reset_btn = InlineKeyboardButton(
                f"🔄 Reset", 
                callback_data=f"reset_threshold_{chain}"
            )
            keyboard.append([set_btn, reset_btn])
        else:
            keyboard.append([set_btn])
    
    keyboard.append([InlineKeyboardButton("🏠 Main Menu", callback_data="back_main")])
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def show_threshold_input(query, chain: str) -> None:
    """Show threshold input instructions for a specific chain"""
    current_threshold = bot_state["user_thresholds"].get(chain, RPCS[chain]["threshold"])
    default_threshold = RPCS[chain]["threshold"]
    
    # Get some example values based on the chain
    examples = {
        "ethereum": ["50", "100", "500"],
        "bsc": ["1000", "5000", "10000"],
        "polygon": ["100000", "500000", "1000000"],
        "bitcoin": ["0.1", "1", "10"]
    }
    
    example_values = examples.get(chain, ["100", "1000", "10000"])
    
    message = (
        f"🎯 *Set {chain.title()} Threshold*\n\n"
        f"Current: {current_threshold:,} tokens\n"
        f"Default: {default_threshold:,} tokens\n\n"
        f"💡 *How to set a new threshold:*\n"
        f"Type: `/setthreshold {chain} <amount>`\n\n"
        f"*Examples:*\n"
    )
    
    for example in example_values:
        message += f"• `/setthreshold {chain} {example}`\n"
    
    message += (
        f"\n📝 *Quick Set Options:*\n"
        f"Choose a preset value below or use the command above for custom amounts."
    )
    
    # Create quick-set buttons
    keyboard = []
    quick_values = []
    
    if chain == "ethereum":
        quick_values = [10, 50, 100, 300, 500, 1000, 1500, 2000, 2500, 3000]
    elif chain == "bsc":
        quick_values = [1000, 3000, 5000, 10000, 20000]
    elif chain == "polygon":
        quick_values = [100000, 500000, 1000000, 2000000, 5000000]
    elif chain == "bitcoin":
        quick_values = [0.1, 1, 10, 50, 100]
    
    # Create rows of 2 buttons each
    for i in range(0, len(quick_values), 2):
        row = []
        for j in range(2):
            if i + j < len(quick_values):
                value = quick_values[i + j]
                row.append(InlineKeyboardButton(
                    f"{value:,}", 
                    callback_data=f"quick_set_{chain}_{value}"
                ))
        keyboard.append(row)
    
    keyboard.append([InlineKeyboardButton("🔙 Back to Thresholds", callback_data="back_threshold")])
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def reset_threshold_via_menu(query, chain: str) -> None:
    """Reset threshold to default via menu"""
    if chain not in bot_state["user_thresholds"]:
        message = f"ℹ️ {chain.title()} is already using the default threshold"
    else:
        # Remove custom threshold
        del bot_state["user_thresholds"][chain]
        default_threshold = RPCS[chain]["threshold"]
        
        # Restart watcher if active
        restart_needed = chain in bot_state["active_chains"]
        if restart_needed:
            bot_state["active_chains"].discard(chain)
            await asyncio.sleep(1)
            
            bot_state["active_chains"].add(chain)
            cfg = RPCS[chain]
            if chain == "bitcoin":
                t = threading.Thread(
                    target=watch_bitcoin_chain, 
                    args=(chain, cfg["url"], default_threshold, cfg["explorer"])
                )
            else:
                t = threading.Thread(
                    target=watch_chain, 
                    args=(chain, cfg["url"], default_threshold, cfg["explorer"], cfg.get("is_poa", False))
                )
            t.daemon = True
            t.start()
            bot_state["watchers"][chain] = t
        
        message = (
            f"✅ *{chain.title()} Threshold Reset*\n\n"
            f"Reset to default: {default_threshold:,} tokens\n"
        )
        
        if restart_needed:
            message += f"\n🔄 Watcher restarted with default threshold"
    
    keyboard = [[InlineKeyboardButton("🔙 Back to Thresholds", callback_data="back_threshold")]]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def set_threshold_via_menu(query, chain: str, value: float) -> None:
    """Set threshold via menu"""
    # Store the custom threshold
    bot_state["user_thresholds"][chain] = value
    
    # If the chain is currently active, we need to restart it with the new threshold
    restart_needed = chain in bot_state["active_chains"]
    if restart_needed:
        # Stop the current watcher
        bot_state["active_chains"].discard(chain)
        await asyncio.sleep(1)  # Give it a moment to stop
        
        # Start with new threshold
        bot_state["active_chains"].add(chain)
        cfg = RPCS[chain]
        if chain == "bitcoin":
            t = threading.Thread(
                target=watch_bitcoin_chain, 
                args=(chain, cfg["url"], value, cfg["explorer"])
            )
        else:
            t = threading.Thread(
                target=watch_chain, 
                args=(chain, cfg["url"], value, cfg["explorer"], cfg.get("is_poa", False))
            )
        t.daemon = True
        t.start()
        bot_state["watchers"][chain] = t
    
    message = (
        f"✅ *Threshold Updated*\n\n"
        f"Chain: {chain.title()}\n"
        f"New threshold: {value:,} tokens\n"
    )
    
    if restart_needed:
        message += f"\n🔄 Watcher restarted with new threshold"
    else:
        message += f"\n💡 Start the {chain} watcher to use the new threshold"
    
    keyboard = [[InlineKeyboardButton("🔙 Back to Thresholds", callback_data="back_threshold")]]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def quick_set_threshold(query, chain: str, threshold: float) -> None:
    """Quick set threshold via button"""
    if chain not in RPCS:
        await query.edit_message_text("❌ Invalid chain", parse_mode="Markdown")
        return
    
    # Store the custom threshold
    bot_state["user_thresholds"][chain] = threshold
    
    # If the chain is currently active, restart it with the new threshold
    restart_needed = chain in bot_state["active_chains"]
    if restart_needed:
        # Stop the current watcher
        bot_state["active_chains"].discard(chain)
        await asyncio.sleep(1)  # Give it a moment to stop
        
        # Start with new threshold
        bot_state["active_chains"].add(chain)
        cfg = RPCS[chain]
        if chain == "bitcoin":
            t = threading.Thread(
                target=watch_bitcoin_chain, 
                args=(chain, cfg["url"], threshold, cfg["explorer"])
            )
        else:
            t = threading.Thread(
                target=watch_chain, 
                args=(chain, cfg["url"], threshold, cfg["explorer"], cfg.get("is_poa", False))
            )
        t.daemon = True
        t.start()
        bot_state["watchers"][chain] = t
    
    message = (
        f"✅ *{chain.title()} Threshold Set*\n\n"
        f"New threshold: {threshold:,} tokens\n"
    )
    
    if restart_needed:
        message += f"\n🔄 Watcher restarted with new threshold"
    else:
        message += f"\n💡 Start the {chain} watcher to use the new threshold"
    
    keyboard = [
        [InlineKeyboardButton("🔙 Back to Thresholds", callback_data="back_threshold")],
        [InlineKeyboardButton("🏠 Main Menu", callback_data="back_main")]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await query.edit_message_text(message, reply_markup=reply_markup, parse_mode="Markdown")

async def threshold_menu_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Show threshold menu via command"""
    message = "🎯 *Threshold Settings*\n\n"
    
    for chain, config in RPCS.items():
        current_threshold = bot_state["user_thresholds"].get(chain, config["threshold"])
        default_threshold = config["threshold"]
        status = "🟢 Active" if chain in bot_state["active_chains"] else "🔴 Stopped"
        
        message += f"*{chain.title()}:* {current_threshold:,}"
        if current_threshold != default_threshold:
            message += f" ⚠️ (default: {default_threshold:,})"
        else:
            message += f" ✅ (default)"
        message += f" - {status}\n"
    
    message += "\n💡 Select a chain to modify its threshold:"
    
    keyboard = []
    for chain in RPCS.keys():
        current_threshold = bot_state["user_thresholds"].get(chain, RPCS[chain]["threshold"])
        is_custom = chain in bot_state["user_thresholds"]
        
        # Create row with set and reset buttons
        set_btn = InlineKeyboardButton(
            f"📝 {chain.title()} ({current_threshold:,})", 
            callback_data=f"set_threshold_{chain}"
        )
        
        if is_custom:
            reset_btn = InlineKeyboardButton(
                f"🔄 Reset", 
                callback_data=f"reset_threshold_{chain}"
            )
            keyboard.append([set_btn, reset_btn])
        else:
            keyboard.append([set_btn])
    
    keyboard.append([InlineKeyboardButton("🏠 Main Menu", callback_data="back_main")])
    reply_markup = InlineKeyboardMarkup(keyboard)
    
    await update.message.reply_text(message, reply_markup=reply_markup, parse_mode="Markdown")

def main() -> None:
    """Start the bot"""
    # Create the Application
    application = Application.builder().token(TELEGRAM_BOT_TOKEN).build()
    
    # Store application reference for use in watchers
    bot_state["application"] = application
    
    # Add handlers
    application.add_handler(CommandHandler("start", start))
    application.add_handler(CommandHandler("help", help_command))
    application.add_handler(CommandHandler("status", status_command))
    application.add_handler(CommandHandler("thresholds", show_thresholds))
    application.add_handler(CommandHandler("threshold_menu", threshold_menu_command))
    application.add_handler(CommandHandler("setthreshold", set_threshold_command))
    application.add_handler(CommandHandler("resetthreshold", reset_threshold_command))
    application.add_handler(CallbackQueryHandler(button_handler))
    
    # Add error handler
    application.add_error_handler(error_handler)
    
    # Start the bot
    print("🤖 Starting Whale Tracker Bot...")
    print(f"📱 Bot will send alerts to chat ID: {TELEGRAM_CHAT_ID}")
    print("🔧 Use /start command to access the control panel")
    print("🎯 Use /threshold_menu for quick threshold management")
    
    # Run the bot until the user presses Ctrl-C
    application.run_polling(
        allowed_updates=Update.ALL_TYPES,
        timeout=REQUEST_TIMEOUTS["telegram"],
    )

if __name__ == '__main__':
    main()