# backtest.py
"""
Script principal para ejecutar backtests
"""
import os
from dotenv import load_dotenv
from pathlib import Path
from datetime import datetime, timedelta

from src.utils.logger import log
from src.data.storage import StorageManager
from src.core.engine import Engine
from src.core.metrics import print_backtest_report, calculate_all_metrics
from src.strategies import MovingAverageCrossover, BuyAndHold, RSIStrategy

def setup_environment():
    """Carga variables de entorno"""
    env_path = Path(__file__).parent / 'config' / 'secrets.env'
    load_dotenv(dotenv_path=env_path)
    log.success("✓ Variables de entorno cargadas")

def run_backtest_demo():
    """
    Demo de backtesting con estrategia simple
    """
    log.info("="*70)
    log.info("🧪 BACKTESTING - DEMO")
    log.info("="*70)
    
    # Setup
    setup_environment()
    
    # Configuración del backtest
    symbol = 'BTC/USDT'
    timeframe = '1h'
    
    log.info(f"\n📊 Configuración:")
    log.info(f"   Símbolo: {symbol}")
    log.info(f"   Timeframe: {timeframe}")
    
    # Conectar a base de datos
    storage = StorageManager(
        db_host=os.getenv('DB_HOST'),
        db_port=int(os.getenv('DB_PORT', 5432)),
        db_name=os.getenv('DB_NAME'),
        db_user=os.getenv('DB_USER'),
        db_password=os.getenv('DB_PASSWORD'),
    )
    
    # Cargar datos
    log.info("\n📥 Cargando TODOS los datos desde PostgreSQL...")
    
    data = storage.load_ohlcv(
        symbol=symbol,
        timeframe=timeframe,
        start_date=None,
        end_date=None,
        use_cache=False
    )
    
    if data.empty:
        log.error(f"❌ No hay datos disponibles para {symbol} {timeframe}")
        log.info("💡 Ejecuta primero: python download_data.py")
        return
    
    log.success(f"✓ Datos cargados: {len(data)} velas")
    log.info(f"   Desde: {data.index.min()}")
    log.info(f"   Hasta: {data.index.max()}")
    log.info(f"   Total días: {(data.index.max() - data.index.min()).days}")
    
    # Crear estrategia
    strategy = MovingAverageCrossover(
        fast_period=10,
        slow_period=30,
        ma_type='sma'
    )
    
    # Crear motor de backtesting
    engine = Engine(
        strategy=strategy,
        initial_capital=10000,
        commission=0.001,  # 0.1%
        slippage=0.0005,   # 0.05%
        position_size=0.95  # Usar 95% del capital
    )
    
    # Ejecutar backtest
    log.info("\n🚀 Ejecutando backtest...")
    results = engine.run(data)
    
    # Mostrar resultados
    print_backtest_report(results)
    
    # Calcular métricas adicionales
    additional_metrics = calculate_all_metrics(results)
    
    if additional_metrics:
        print("\n📈 MÉTRICAS ADICIONALES:")
        print(f"   Sortino Ratio:      {additional_metrics['sortino_ratio']:>12.2f}")
        print(f"   Calmar Ratio:       {additional_metrics['calmar_ratio']:>12.2f}")
        print(f"   Expectancy:         ${additional_metrics['expectancy']:>12,.2f}")
        print(f"   Risk/Reward:        {additional_metrics['risk_reward_ratio']:>12.2f}")
        print(f"   Recovery Factor:    {additional_metrics['recovery_factor']:>12.2f}")
    
    # Mostrar algunos trades de ejemplo
    if results['trades']:
        print(f"\n📋 TRADES (primeros 5):")
        for i, trade in enumerate(results['trades'][:5], 1):
            print(f"\n   Trade #{i}:")
            print(f"      Entrada:  {trade.entry_time} @ ${trade.entry_price:.2f}")
            print(f"      Salida:   {trade.exit_time} @ ${trade.exit_price:.2f}")
            print(f"      PnL:      ${trade.pnl:>10.2f} ({trade.pnl_percentage:>6.2f}%)")
            print(f"      Duración: {trade.duration:.1f}h")
    
    # Cleanup
    storage.close()
    
    log.info("\n" + "="*70)
    log.success("✅ DEMO COMPLETADO")
    log.info("="*70)
    
    return results

def compare_strategies_demo():
    """
    Compara múltiples estrategias sobre los mismos datos
    """
    log.info("="*70)
    log.info("🔍 COMPARACIÓN DE ESTRATEGIAS")
    log.info("="*70)
    
    setup_environment()
    
    # Configuración
    symbol = 'BTC/USDT'
    timeframe = '1h'
    
    # Conectar a base de datos y cargar datos
    storage = StorageManager(
        db_host=os.getenv('DB_HOST'),
        db_port=int(os.getenv('DB_PORT', 5432)),
        db_name=os.getenv('DB_NAME'),
        db_user=os.getenv('DB_USER'),
        db_password=os.getenv('DB_PASSWORD'),
    )
    
    data = storage.load_ohlcv(
        symbol=symbol,
        timeframe=timeframe,
        start_date=None,
        end_date=None,
        use_cache=False
    )
    
    if data.empty:
        log.error(f"❌ No hay datos disponibles")
        return
    
    log.success(f"✓ Datos cargados: {len(data)} velas")
    
    # Definir estrategias a comparar
    strategies = [
        ('Buy & Hold', BuyAndHold()),
        ('MA Cross (10/30 SMA)', MovingAverageCrossover(10, 30, 'sma')),
        ('MA Cross (20/50 EMA)', MovingAverageCrossover(20, 50, 'ema')),
        ('RSI (30/70)', RSIStrategy(14, 30, 70)),
    ]
    
    # Ejecutar backtest para cada estrategia
    all_results = {}
    
    for name, strategy in strategies:
        log.info(f"\n🧪 Testeando: {name}")
        
        engine = Engine(
            strategy=strategy,
            initial_capital=10000,
            commission=0.001,
            position_size=0.95
        )
        
        results = engine.run(data)
        all_results[name] = results
        
        log.info(f"   Retorno: {results['total_return_pct']:.2f}%")
        log.info(f"   Trades: {results['total_trades']}")
        log.info(f"   Win Rate: {results['win_rate_pct']:.2f}%")
    
    # Comparar resultados
    from src.core.metrics import compare_strategies
    compare_strategies(all_results)
    
    storage.close()
    
    log.success("✅ COMPARACIÓN COMPLETADA")
    
    return all_results

if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1 and sys.argv[1] == 'compare':
        # Modo comparación
        compare_strategies_demo()
    else:
        # Modo demo simple
        run_backtest_demo()
    
    print("\n💡 TIP: Para comparar estrategias usa: python backtest.py compare")