"""
Script execution engine for ZebuBot.
"""

import os
import sys
import subprocess
import importlib.util
from pathlib import Path
from typing import Optional, Dict, Any
import logging

from .config import ConfigManager
from .core import ZebuBot


class ScriptExecutor:
    """Handles creation and execution of trading scripts."""
    
    def __init__(self):
        """Initialize the script executor."""
        self.config_manager = ConfigManager()
        self.logger = logging.getLogger(__name__)
    
    def create_script(self, script_name: str, template: Optional[str] = None, output_dir: str = "scripts") -> Path:
        """Create a new trading script from template."""
        # Ensure output directory exists
        scripts_dir = Path(output_dir)
        scripts_dir.mkdir(parents=True, exist_ok=True)
        
        script_path = scripts_dir / script_name
        
        if script_path.exists():
            raise FileExistsError(f"Script {script_name} already exists")
        
        # Get template content
        if template:
            template_content = self._get_template_content(template)
        else:
            template_content = self._get_default_template(script_name)
        
        # Write script file
        with open(script_path, 'w') as f:
            f.write(template_content)
        
        self.logger.info(f"Created script: {script_path}")
        return script_path
    
    def execute_script(self, script_path: Path) -> None:
        """Execute a trading script."""
        if not script_path.exists():
            raise FileNotFoundError(f"Script not found: {script_path}")
        
        # Add the script directory to Python path
        script_dir = script_path.parent
        if str(script_dir) not in sys.path:
            sys.path.insert(0, str(script_dir))
        
        # Load and execute the script
        try:
            spec = importlib.util.spec_from_file_location(script_path.stem, script_path)
            module = importlib.util.module_from_spec(spec)
            
            # Set up the module with ZebuBot context
            self._setup_script_context(module)
            
            # Execute the script
            spec.loader.exec_module(module)
            
        except Exception as e:
            self.logger.error(f"Script execution failed: {e}")
            raise
    
    def _setup_script_context(self, module) -> None:
        """Set up the script execution context with ZebuBot utilities."""
        # Create a ZebuBot instance for the script
        try:
            config = self.config_manager.load_config("zebubot_config.yaml")
            zebubot = ZebuBot(config)
            module.zebubot = zebubot
            module.bot = zebubot  # Alias for convenience
        except Exception as e:
            self.logger.warning(f"Could not initialize ZebuBot context: {e}")
            module.zebubot = None
            module.bot = None
        
        # Add common imports to the module
        module.logger = logging.getLogger(module.__name__)
        module.Path = Path
        module.pd = __import__('pandas')
        module.np = __import__('numpy')
    
    def _get_template_content(self, template_name: str) -> str:
        """Get template content by name."""
        templates_dir = Path("templates")
        template_file = templates_dir / f"{template_name}.py"
        
        if not template_file.exists():
            raise FileNotFoundError(f"Template not found: {template_name}")
        
        with open(template_file, 'r') as f:
            return f.read()
    
    def _get_default_template(self, script_name: str) -> str:
        """Get default template content for a script."""
        if "rsi" in script_name.lower():
            return self._get_rsi_template()
        elif "macd" in script_name.lower():
            return self._get_macd_template()
        elif "bollinger" in script_name.lower():
            return self._get_bollinger_template()
        else:
            return self._get_basic_template()
    
    def _get_rsi_template(self) -> str:
        """Get RSI trading strategy template."""
        return '''"""
RSI Trading Strategy Script
Generated by ZebuBot
"""

import pandas as pd
import numpy as np
from pathlib import Path

# ZebuBot will inject 'zebubot' and 'bot' variables
# zebubot = ZebuBot instance
# bot = alias for zebubot

def calculate_rsi(prices, period=14):
    """Calculate RSI indicator."""
    delta = prices.diff()
    gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
    rs = gain / loss
    rsi = 100 - (100 / (1 + rs))
    return rsi

def main():
    """Main trading strategy function."""
    logger.info("Starting RSI Trading Strategy")
    
    if not zebubot:
        logger.error("ZebuBot not initialized. Please check your configuration.")
        return
    
    # Get market data
    try:
        # Example: Get BTC/USDT data from Binance
        symbol = "BTC/USDT"
        timeframe = "1h"
        limit = 100
        
        logger.info(f"Fetching {symbol} data from {timeframe} timeframe")
        ohlcv = zebubot.get_market_data(symbol, timeframe, limit)
        
        if ohlcv is None or len(ohlcv) == 0:
            logger.error("No market data received")
            return
        
        # Convert to DataFrame
        df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
        df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
        df.set_index('timestamp', inplace=True)
        
        # Calculate RSI
        df['rsi'] = calculate_rsi(df['close'])
        
        # Trading logic
        current_rsi = df['rsi'].iloc[-1]
        logger.info(f"Current RSI: {current_rsi:.2f}")
        
        # RSI strategy: Buy when RSI < 30, Sell when RSI > 70
        if current_rsi < 30:
            logger.info("RSI < 30: Potential BUY signal")
            # Add your buy logic here
            # zebubot.place_order(symbol, 'buy', amount, price)
            
        elif current_rsi > 70:
            logger.info("RSI > 70: Potential SELL signal")
            # Add your sell logic here
            # zebubot.place_order(symbol, 'sell', amount, price)
            
        else:
            logger.info("RSI in neutral zone: No action")
        
        # Display recent data
        logger.info("Recent RSI values:")
        logger.info(df[['close', 'rsi']].tail(10).to_string())
        
    except Exception as e:
        logger.error(f"Strategy execution failed: {e}")
        raise

if __name__ == "__main__":
    main()
'''
    
    def _get_macd_template(self) -> str:
        """Get MACD trading strategy template."""
        return '''"""
MACD Trading Strategy Script
Generated by ZebuBot
"""

import pandas as pd
import numpy as np
from pathlib import Path

def calculate_macd(prices, fast=12, slow=26, signal=9):
    """Calculate MACD indicator."""
    ema_fast = prices.ewm(span=fast).mean()
    ema_slow = prices.ewm(span=slow).mean()
    macd_line = ema_fast - ema_slow
    signal_line = macd_line.ewm(span=signal).mean()
    histogram = macd_line - signal_line
    return macd_line, signal_line, histogram

def main():
    """Main trading strategy function."""
    logger.info("Starting MACD Trading Strategy")
    
    if not zebubot:
        logger.error("ZebuBot not initialized. Please check your configuration.")
        return
    
    # Your MACD strategy implementation here
    logger.info("MACD strategy template - implement your logic here")

if __name__ == "__main__":
    main()
'''
    
    def _get_bollinger_template(self) -> str:
        """Get Bollinger Bands trading strategy template."""
        return '''"""
Bollinger Bands Trading Strategy Script
Generated by ZebuBot
"""

import pandas as pd
import numpy as np
from pathlib import Path

def calculate_bollinger_bands(prices, period=20, std_dev=2):
    """Calculate Bollinger Bands."""
    sma = prices.rolling(window=period).mean()
    std = prices.rolling(window=period).std()
    upper_band = sma + (std * std_dev)
    lower_band = sma - (std * std_dev)
    return upper_band, sma, lower_band

def main():
    """Main trading strategy function."""
    logger.info("Starting Bollinger Bands Trading Strategy")
    
    if not zebubot:
        logger.error("ZebuBot not initialized. Please check your configuration.")
        return
    
    # Your Bollinger Bands strategy implementation here
    logger.info("Bollinger Bands strategy template - implement your logic here")

if __name__ == "__main__":
    main()
'''
    
    def _get_basic_template(self) -> str:
        """Get basic trading script template."""
        return '''"""
Basic Trading Strategy Script
Generated by ZebuBot
"""

import pandas as pd
import numpy as np
from pathlib import Path

def main():
    """Main trading strategy function."""
    logger.info("Starting Basic Trading Strategy")
    
    if not zebubot:
        logger.error("ZebuBot not initialized. Please check your configuration.")
        return
    
    # Your trading strategy implementation here
    logger.info("Basic strategy template - implement your logic here")
    
    # Example: Get account balance
    # balance = zebubot.get_balance()
    # logger.info(f"Account balance: {balance}")
    
    # Example: Get market data
    # symbol = "BTC/USDT"
    # ohlcv = zebubot.get_market_data(symbol, "1h", 100)
    # logger.info(f"Market data for {symbol}: {len(ohlcv)} candles")

if __name__ == "__main__":
    main()
'''
