#!/usr/bin/env python3
"""
Automated Trading Strategy Bot

This bot runs continuously and implements automated trading strategies.
It can run alongside the Telegram bot for monitoring and control.
"""

import asyncio
import time
import logging
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from hyperliquid_client import HyperliquidClient
from config import Config

# Set up logging
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=getattr(logging, Config.LOG_LEVEL)
)
logger = logging.getLogger(__name__)

class TradingStrategy:
    """Base class for trading strategies."""
    
    def __init__(self, client: HyperliquidClient):
        self.client = client
        self.symbol = Config.DEFAULT_TRADING_SYMBOL
        self.trade_amount = Config.DEFAULT_TRADE_AMOUNT
        
    async def analyze_market(self) -> Dict[str, Any]:
        """Analyze market conditions. Override in subclasses."""
        market_data = self.client.get_market_data(self.symbol)
        return {
            'signal': 'HOLD',  # BUY, SELL, HOLD
            'confidence': 0.0,  # 0.0 to 1.0
            'market_data': market_data
        }
    
    async def execute_strategy(self) -> bool:
        """Execute the trading strategy. Override in subclasses."""
        analysis = await self.analyze_market()
        logger.info(f"Strategy analysis: {analysis['signal']} (confidence: {analysis['confidence']:.2f})")
        return True

class SimpleMovingAverageStrategy(TradingStrategy):
    """Example: Simple Moving Average Crossover Strategy."""
    
    def __init__(self, client: HyperliquidClient):
        super().__init__(client)
        self.price_history = []
        self.short_period = 5  # 5 minute MA
        self.long_period = 20  # 20 minute MA
        
    async def analyze_market(self) -> Dict[str, Any]:
        """Analyze using moving average crossover."""
        market_data = self.client.get_market_data(self.symbol)
        
        if not market_data:
            return {'signal': 'HOLD', 'confidence': 0.0, 'market_data': None}
        
        current_price = float(market_data['ticker'].get('last', 0))
        if current_price == 0:
            return {'signal': 'HOLD', 'confidence': 0.0, 'market_data': market_data}
        
        # Add current price to history
        self.price_history.append(current_price)
        
        # Keep only what we need
        max_history = max(self.short_period, self.long_period) + 5
        if len(self.price_history) > max_history:
            self.price_history = self.price_history[-max_history:]
        
        # Need enough data for analysis
        if len(self.price_history) < self.long_period:
            return {'signal': 'HOLD', 'confidence': 0.0, 'market_data': market_data}
        
        # Calculate moving averages
        short_ma = sum(self.price_history[-self.short_period:]) / self.short_period
        long_ma = sum(self.price_history[-self.long_period:]) / self.long_period
        
        # Previous MAs for crossover detection
        if len(self.price_history) >= self.long_period + 1:
            prev_short_ma = sum(self.price_history[-self.short_period-1:-1]) / self.short_period
            prev_long_ma = sum(self.price_history[-self.long_period-1:-1]) / self.long_period
            
            # Bullish crossover: short MA crosses above long MA
            if prev_short_ma <= prev_long_ma and short_ma > long_ma:
                return {'signal': 'BUY', 'confidence': 0.7, 'market_data': market_data}
            
            # Bearish crossover: short MA crosses below long MA
            if prev_short_ma >= prev_long_ma and short_ma < long_ma:
                return {'signal': 'SELL', 'confidence': 0.7, 'market_data': market_data}
        
        return {'signal': 'HOLD', 'confidence': 0.5, 'market_data': market_data}
    
    async def execute_strategy(self) -> bool:
        """Execute the moving average strategy."""
        analysis = await self.analyze_market()
        signal = analysis['signal']
        confidence = analysis['confidence']
        
        logger.info(f"MA Strategy: {signal} (confidence: {confidence:.2f})")
        
        # Only trade with high confidence
        if confidence < 0.6:
            return True
        
        # Get current positions to avoid overtrading
        positions = self.client.get_positions(self.symbol)
        current_position = 0
        if positions:
            for pos in positions:
                if pos.get('symbol') == self.symbol:
                    current_position = float(pos.get('contracts', 0))
                    break
        
        market_data = analysis['market_data']
        current_price = float(market_data['ticker'].get('last', 0))
        
        if signal == 'BUY' and current_position <= 0:
            # Place buy order slightly below market price
            buy_price = current_price * 0.999  # 0.1% below market
            logger.info(f"🟢 Placing BUY order: {self.trade_amount} {self.symbol} @ ${buy_price:.2f}")
            
            # Uncomment to enable real trading:
            # order = self.client.place_limit_order(self.symbol, 'buy', self.trade_amount, buy_price)
            # if order:
            #     logger.info(f"✅ Buy order placed: {order}")
            # else:
            #     logger.error("❌ Failed to place buy order")
            
        elif signal == 'SELL' and current_position >= 0:
            # Place sell order slightly above market price
            sell_price = current_price * 1.001  # 0.1% above market
            logger.info(f"🔴 Placing SELL order: {self.trade_amount} {self.symbol} @ ${sell_price:.2f}")
            
            # Uncomment to enable real trading:
            # order = self.client.place_limit_order(self.symbol, 'sell', self.trade_amount, sell_price)
            # if order:
            #     logger.info(f"✅ Sell order placed: {order}")
            # else:
            #     logger.error("❌ Failed to place sell order")
        
        return True

class StrategyBot:
    """Main automated trading bot that runs strategies continuously."""
    
    def __init__(self):
        """Initialize the strategy bot."""
        self.client = HyperliquidClient(use_testnet=Config.HYPERLIQUID_TESTNET)
        self.strategies = []
        self.is_running = False
        self.loop_interval = 60  # Run every 60 seconds
        
        # Add strategies
        self.add_strategy(SimpleMovingAverageStrategy(self.client))
    
    def add_strategy(self, strategy: TradingStrategy):
        """Add a trading strategy to the bot."""
        self.strategies.append(strategy)
        logger.info(f"Added strategy: {strategy.__class__.__name__}")
    
    async def run_strategies(self):
        """Run all strategies once."""
        for strategy in self.strategies:
            try:
                await strategy.execute_strategy()
            except Exception as e:
                logger.error(f"Error in strategy {strategy.__class__.__name__}: {e}")
    
    async def health_check(self):
        """Check bot health and connection."""
        # Test connection
        market_data = self.client.get_market_data(Config.DEFAULT_TRADING_SYMBOL)
        if not market_data:
            logger.error("❌ Health check failed - cannot connect to Hyperliquid")
            return False
        
        # Check balance
        balance = self.client.get_balance()
        if not balance:
            logger.warning("⚠️ Could not fetch balance")
        
        logger.info("✅ Health check passed")
        return True
    
    async def run(self):
        """Main bot loop."""
        logger.info("🚀 Starting Strategy Bot...")
        logger.info(f"📊 Default Symbol: {Config.DEFAULT_TRADING_SYMBOL}")
        logger.info(f"💰 Trade Amount: {Config.DEFAULT_TRADE_AMOUNT}")
        logger.info(f"⏰ Loop Interval: {self.loop_interval} seconds")
        logger.info(f"🌐 Network: {'Testnet' if Config.HYPERLIQUID_TESTNET else 'Mainnet'}")
        
        # Initial health check
        if not await self.health_check():
            logger.error("❌ Initial health check failed. Exiting.")
            return
        
        self.is_running = True
        iteration = 0
        
        try:
            while self.is_running:
                iteration += 1
                start_time = time.time()
                
                logger.info(f"🔄 Strategy iteration #{iteration} started")
                
                # Run strategies
                await self.run_strategies()
                
                # Periodic health check (every 10 iterations)
                if iteration % 10 == 0:
                    await self.health_check()
                
                # Calculate sleep time
                execution_time = time.time() - start_time
                sleep_time = max(0, self.loop_interval - execution_time)
                
                logger.info(f"✅ Iteration #{iteration} completed in {execution_time:.2f}s. Sleeping {sleep_time:.2f}s")
                
                if sleep_time > 0:
                    await asyncio.sleep(sleep_time)
                
        except KeyboardInterrupt:
            logger.info("👋 Strategy bot stopped by user")
        except Exception as e:
            logger.error(f"❌ Unexpected error in strategy bot: {e}")
        finally:
            self.is_running = False
            logger.info("🛑 Strategy bot stopped")

def main():
    """Main entry point."""
    try:
        # Validate configuration
        if not Config.validate():
            logger.error("❌ Configuration validation failed!")
            return
        
        # Create and run the bot
        bot = StrategyBot()
        asyncio.run(bot.run())
        
    except KeyboardInterrupt:
        logger.info("👋 Bot stopped by user")
    except Exception as e:
        logger.error(f"❌ Unexpected error: {e}")

if __name__ == "__main__":
    main()