#!/usr/bin/env python3
"""
Hyperliquid Manual Trading Bot - Main Launcher

A robust launcher with error handling, auto-restart, and telegram notifications.
This is the ONLY file you need to run - it handles everything.
"""

import sys
import os
import asyncio
import logging
import traceback
import signal
import time
from datetime import datetime
from pathlib import Path

# Add src directory to Python path
sys.path.insert(0, str(Path(__file__).parent / "src"))

try:
    from config import Config
    from telegram_bot import TelegramTradingBot
    from trading_stats import TradingStats
except ImportError as e:
    print(f"āŒ Import error: {e}")
    print("šŸ’” Make sure you're in the correct directory and dependencies are installed")
    sys.exit(1)

# Global variables for graceful shutdown
bot_instance = None
is_shutting_down = False

class BotManager:
    """Manages the trading bot with error handling and auto-restart."""
    
    def __init__(self):
        self.bot = None
        self.restart_count = 0
        self.max_restarts = 10
        self.restart_delay = 5  # seconds
        self.error_log_file = "logs/bot_errors.log"
        self.setup_logging()
        
        # Ensure logs directory exists
        os.makedirs("logs", exist_ok=True)
    
    def setup_logging(self):
        """Set up comprehensive logging."""
        # Create logs directory
        os.makedirs("logs", exist_ok=True)
        
        # Set up file logging
        log_file = f"logs/trading_bot_{datetime.now().strftime('%Y%m%d')}.log"
        
        logging.basicConfig(
            level=getattr(logging, Config.LOG_LEVEL if hasattr(Config, 'LOG_LEVEL') else 'INFO'),
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(log_file),
                logging.StreamHandler(sys.stdout)
            ]
        )
        
        self.logger = logging.getLogger(__name__)
        self.logger.info(f"Logging initialized - Log file: {log_file}")
    
    def print_banner(self):
        """Print startup banner."""
        banner = f"""
╔══════════════════════════════════════════════════════════════╗
ā•‘                    šŸ“± HYPERLIQUID TRADING BOT                ā•‘
ā•‘                     Single Command Launcher                   ā•‘
╠══════════════════════════════════════════════════════════════╣
ā•‘                                                              ā•‘
ā•‘  šŸ¤– Manual phone control via Telegram                       ā•‘
ā•‘  šŸ“Š Comprehensive trading statistics                        ā•‘
ā•‘  šŸ›”ļø Auto-restart & error notifications                      ā•‘
ā•‘  šŸ’¾ Persistent data between restarts                        ā•‘
ā•‘  šŸ“± Professional mobile interface                            ā•‘
ā•‘                                                              ā•‘
ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•

šŸš€ Starting at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
šŸ“ Working directory: {os.getcwd()}
🌐 Network: {'Testnet' if Config.HYPERLIQUID_TESTNET else '🚨 MAINNET 🚨'}
        """
        print(banner)
    
    def validate_configuration(self):
        """Validate bot configuration."""
        self.logger.info("šŸ” Validating configuration...")
        
        missing_config = []
        
        if not hasattr(Config, 'HYPERLIQUID_PRIVATE_KEY') or not Config.HYPERLIQUID_PRIVATE_KEY:
            missing_config.append("HYPERLIQUID_PRIVATE_KEY")
        
        if not hasattr(Config, 'TELEGRAM_BOT_TOKEN') or not Config.TELEGRAM_BOT_TOKEN:
            missing_config.append("TELEGRAM_BOT_TOKEN")
        
        if not hasattr(Config, 'TELEGRAM_CHAT_ID') or not Config.TELEGRAM_CHAT_ID:
            missing_config.append("TELEGRAM_CHAT_ID")
        
        if not hasattr(Config, 'TELEGRAM_ENABLED') or not Config.TELEGRAM_ENABLED:
            missing_config.append("TELEGRAM_ENABLED (must be true)")
        
        if missing_config:
            error_msg = f"āŒ Missing configuration: {', '.join(missing_config)}"
            self.logger.error(error_msg)
            print(f"\n{error_msg}")
            print("\nšŸ’” Setup steps:")
            print("1. Copy config: cp config/env.example .env")
            print("2. Get Telegram setup: python utils/get_telegram_chat_id.py")
            print("3. Edit .env with your details")
            print("4. See: SETUP_GUIDE.md for detailed instructions")
            return False
        
        self.logger.info("āœ… Configuration validation passed")
        return True
    
    def check_stats_persistence(self):
        """Check and report on statistics persistence."""
        stats_file = "trading_stats.json"
        if os.path.exists(stats_file):
            try:
                stats = TradingStats()
                basic_stats = stats.get_basic_stats()
                self.logger.info(f"šŸ“Š Existing stats found - {basic_stats['total_trades']} trades since {basic_stats.get('start_date', 'unknown')}")
                return True
            except Exception as e:
                self.logger.warning(f"āš ļø Stats file exists but couldn't load: {e}")
                return False
        else:
            self.logger.info("šŸ“Š No existing stats - will create new tracking from launch")
            return False
    
    async def send_error_notification(self, error_message: str, error_details: str = None):
        """Send error notification via Telegram."""
        try:
            if hasattr(Config, 'TELEGRAM_BOT_TOKEN') and hasattr(Config, 'TELEGRAM_CHAT_ID'):
                from telegram import Bot
                
                bot = Bot(token=Config.TELEGRAM_BOT_TOKEN)
                
                notification = f"""
🚨 <b>Trading Bot Error</b>

ā° <b>Time:</b> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
āŒ <b>Error:</b> {error_message}

šŸ”„ <b>Status:</b> Attempting restart...
šŸ“Š <b>Restart Count:</b> {self.restart_count}/{self.max_restarts}

{f'<b>Details:</b> <code>{error_details[:500]}...</code>' if error_details else ''}
                """
                
                await bot.send_message(
                    chat_id=Config.TELEGRAM_CHAT_ID,
                    text=notification.strip(),
                    parse_mode='HTML'
                )
                
                self.logger.info("šŸ“± Error notification sent via Telegram")
                
        except Exception as e:
            self.logger.error(f"Failed to send error notification: {e}")
    
    async def send_startup_notification(self):
        """Send startup notification via Telegram."""
        try:
            if self.bot and hasattr(self.bot, 'send_message'):
                message = f"""
🟢 <b>Trading Bot Started Successfully</b>

ā° <b>Started:</b> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
🌐 <b>Network:</b> {'Testnet' if Config.HYPERLIQUID_TESTNET else 'Mainnet'}
šŸ“Š <b>Symbol:</b> {Config.DEFAULT_TRADING_SYMBOL}
šŸ’° <b>Default Amount:</b> {Config.DEFAULT_TRADE_AMOUNT}
šŸ”„ <b>Restart #:</b> {self.restart_count}

šŸ“± Bot is ready for manual trading!
Send /start for quick actions.
                """
                await self.bot.send_message(message.strip())
                
        except Exception as e:
            self.logger.error(f"Failed to send startup notification: {e}")
    
    async def run_bot(self):
        """Run the main bot with error handling."""
        try:
            self.logger.info("šŸ¤– Creating TelegramTradingBot instance...")
            self.bot = TelegramTradingBot()
            
            self.logger.info("šŸ“Š Checking statistics persistence...")
            self.check_stats_persistence()
            
            self.logger.info("šŸš€ Starting Telegram bot...")
            
            # Send startup notification
            await self.send_startup_notification()
            
            # Run the bot
            await self.bot.run()
            
        except KeyboardInterrupt:
            self.logger.info("šŸ‘‹ Bot stopped by user (Ctrl+C)")
            raise  # Re-raise to handle gracefully
            
        except Exception as e:
            self.logger.error(f"āŒ Bot error: {e}")
            
            # Get detailed error info
            error_details = traceback.format_exc()
            self.logger.error(f"Error details:\n{error_details}")
            
            # Log to error file
            with open(self.error_log_file, 'a') as f:
                f.write(f"\n{datetime.now().isoformat()} - {e}\n{error_details}\n{'='*50}\n")
            
            # Send error notification
            await self.send_error_notification(str(e), error_details)
            
            raise  # Re-raise for restart logic
    
    async def run_with_restart(self):
        """Run bot with auto-restart capability."""
        global is_shutting_down
        
        while not is_shutting_down and self.restart_count < self.max_restarts:
            try:
                if self.restart_count > 0:
                    self.logger.info(f"šŸ”„ Restarting bot (attempt {self.restart_count + 1}/{self.max_restarts})")
                    self.logger.info(f"ā³ Waiting {self.restart_delay} seconds before restart...")
                    await asyncio.sleep(self.restart_delay)
                
                await self.run_bot()
                
                # If we get here, bot exited normally
                break
                
            except KeyboardInterrupt:
                self.logger.info("šŸ‘‹ Graceful shutdown requested")
                is_shutting_down = True
                break
                
            except Exception as e:
                self.restart_count += 1
                self.logger.error(f"šŸ’„ Bot crashed: {e}")
                
                if self.restart_count >= self.max_restarts:
                    self.logger.error(f"āŒ Max restart attempts ({self.max_restarts}) reached. Giving up.")
                    
                    # Send final error notification
                    await self.send_error_notification(
                        f"Bot failed permanently after {self.max_restarts} restart attempts",
                        f"Last error: {str(e)}"
                    )
                    break
                
                # Exponential backoff for restart delay
                self.restart_delay = min(self.restart_delay * 1.5, 60)
    
    async def start(self):
        """Main entry point."""
        try:
            self.print_banner()
            
            if not self.validate_configuration():
                return False
            
            self.logger.info("šŸŽÆ All systems ready - starting trading bot...")
            print("šŸ’” Send /start to your Telegram bot for quick actions")
            print("šŸ›‘ Press Ctrl+C to stop\n")
            
            await self.run_with_restart()
            
            return True
            
        except Exception as e:
            self.logger.error(f"āŒ Fatal error in bot manager: {e}")
            print(f"\nšŸ’„ Fatal error: {e}")
            return False

def signal_handler(signum, frame):
    """Handle shutdown signals gracefully."""
    global is_shutting_down, bot_instance
    
    print("\nšŸ›‘ Shutdown signal received...")
    is_shutting_down = True
    
    if bot_instance:
        try:
            asyncio.create_task(bot_instance.send_error_notification("Bot shutdown requested", "Graceful shutdown"))
        except:
            pass

def main():
    """Main function."""
    global bot_instance
    
    # Set up signal handlers for graceful shutdown
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    try:
        bot_manager = BotManager()
        bot_instance = bot_manager
        
        # Run the bot
        success = asyncio.run(bot_manager.start())
        
        if success:
            print("\nāœ… Bot session completed successfully")
        else:
            print("\nāŒ Bot session failed")
            sys.exit(1)
            
    except KeyboardInterrupt:
        print("\nšŸ‘‹ Bot stopped by user")
    except Exception as e:
        print(f"\nšŸ’„ Unexpected error: {e}")
        sys.exit(1)
    finally:
        print("šŸ“Š Your trading statistics have been saved")
        print("šŸ”„ Run again anytime to continue tracking!")

if __name__ == "__main__":
    main()