#!/usr/bin/env python3
"""
HYBRID STRATEGY - Stratégie Adaptative Intelligente
Switch automatique entre 3 stratégies selon le régime de marché

Stratégies:
1. BULL: bull_strategy.py (zones haussières)
2. BEAR: bear_strategy.py (zones baissières)
3. RANGE: v10_range_strategy.py (marché latéral)

Le market_detector détermine le régime, puis la stratégie appropriée est utilisée.
"""

import pandas as pd
import numpy as np
from typing import Optional, Dict
from dataclasses import dataclass
import logging

from market_detector import MarketDetector, MarketRegime
from bull_strategy import BullStrategy, BullSignal
from bear_strategy import BearStrategy, BearSignal
from v10_range_strategy import V10RangeStrategy

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


@dataclass
class HybridSignal:
    """Signal unifié de la stratégie hybride"""
    symbol: str
    side: str  # 'LONG' ou 'SHORT'
    entry_price: float
    stop_loss: float
    take_profit: float
    leverage: int
    confidence: float  # 0-100
    reason: str
    strategy_used: str  # 'BULL', 'BEAR', 'RANGE'
    market_regime: str  # Régime détecté


class HybridStrategy:
    """
    Stratégie hybride adaptative

    Détecte automatiquement le régime de marché et utilise
    la stratégie optimale pour ce régime.
    """

    def __init__(self, leverage: int = 200, use_llm: bool = False):
        """
        Args:
            leverage: Leverage par défaut
            use_llm: Utiliser mini LLM pour détection (future)
        """
        self.leverage = leverage

        # Market detector
        self.detector = MarketDetector(use_llm=use_llm)

        # Sous-stratégies
        self.bull_strategy = BullStrategy(leverage=leverage)
        self.bear_strategy = BearStrategy(leverage=leverage)
        self.range_strategy = V10RangeStrategy(leverage=leverage)

        # Statistiques
        self.stats = {
            'total_signals': 0,
            'bull_signals': 0,
            'bear_signals': 0,
            'range_signals': 0,
            'regime_switches': 0,
        }
        self.last_regime = None

    def analyze(self, symbol: str, df: pd.DataFrame) -> Optional[HybridSignal]:
        """
        Analyse le marché et génère un signal adaptatif

        Args:
            symbol: Symbole du token
            df: DataFrame avec OHLCV

        Returns:
            HybridSignal ou None
        """
        if len(df) < 100:
            return None

        # 1. Détecter régime de marché
        market_analysis = self.detector.detect(df)
        regime = market_analysis.regime

        # Tracker changement de régime
        if self.last_regime and self.last_regime != regime:
            self.stats['regime_switches'] += 1
            logger.debug(f"🔄 Changement régime: {self.last_regime.value} → {regime.value}")

        self.last_regime = regime

        logger.debug(f"📊 Régime: {regime.value} | Confidence: {market_analysis.confidence:.0f}% | {market_analysis.reason}")

        # 2. Router vers stratégie appropriée
        signal = None

        if regime == MarketRegime.BULL:
            # Utiliser stratégie haussière
            bull_signal = self.bull_strategy.analyze(symbol, df)
            if bull_signal:
                signal = self._convert_bull_signal(bull_signal, symbol, market_analysis)
                self.stats['bull_signals'] += 1

        elif regime == MarketRegime.BEAR:
            # Utiliser stratégie baissière
            bear_signal = self.bear_strategy.analyze(symbol, df)
            if bear_signal:
                signal = self._convert_bear_signal(bear_signal, symbol, market_analysis)
                self.stats['bear_signals'] += 1

        elif regime == MarketRegime.RANGE:
            # Utiliser stratégie range V10
            range_signal = self.range_strategy.analyze(symbol, df)
            if range_signal:
                signal = self._convert_range_signal(range_signal, symbol, market_analysis)
                self.stats['range_signals'] += 1

        else:  # UNCERTAIN
            logger.debug(f"⚠️  Régime incertain, pas de signal")
            return None

        if signal:
            self.stats['total_signals'] += 1

        return signal

    def _convert_bull_signal(
        self,
        bull_signal: BullSignal,
        symbol: str,
        market_analysis
    ) -> HybridSignal:
        """Convertit BullSignal en HybridSignal"""
        return HybridSignal(
            symbol=symbol,
            side=bull_signal.side,
            entry_price=bull_signal.entry_price,
            stop_loss=bull_signal.stop_loss,
            take_profit=bull_signal.take_profit,
            leverage=bull_signal.leverage,
            confidence=bull_signal.confidence,
            reason=f"[BULL] {bull_signal.reason}",
            strategy_used='BULL',
            market_regime=market_analysis.regime.value
        )

    def _convert_bear_signal(
        self,
        bear_signal: BearSignal,
        symbol: str,
        market_analysis
    ) -> HybridSignal:
        """Convertit BearSignal en HybridSignal"""
        return HybridSignal(
            symbol=symbol,
            side=bear_signal.side,
            entry_price=bear_signal.entry_price,
            stop_loss=bear_signal.stop_loss,
            take_profit=bear_signal.take_profit,
            leverage=bear_signal.leverage,
            confidence=bear_signal.confidence,
            reason=f"[BEAR] {bear_signal.reason}",
            strategy_used='BEAR',
            market_regime=market_analysis.regime.value
        )

    def _convert_range_signal(
        self,
        range_signal,
        symbol: str,
        market_analysis
    ) -> HybridSignal:
        """Convertit signal V10 Range en HybridSignal"""
        return HybridSignal(
            symbol=symbol,
            side=range_signal['side'],
            entry_price=range_signal['entry_price'],
            stop_loss=range_signal['stop_loss'],
            take_profit=range_signal['take_profit'],
            leverage=range_signal.get('leverage', self.leverage),
            confidence=range_signal.get('confidence', 70),
            reason=f"[RANGE] {range_signal.get('reason', 'V10 Range signal')}",
            strategy_used='RANGE',
            market_regime=market_analysis.regime.value
        )

    def get_stats(self) -> Dict:
        """Retourne statistiques d'utilisation"""
        total = self.stats['total_signals']
        if total == 0:
            return self.stats

        stats_with_pct = self.stats.copy()
        stats_with_pct['bull_pct'] = (self.stats['bull_signals'] / total) * 100
        stats_with_pct['bear_pct'] = (self.stats['bear_signals'] / total) * 100
        stats_with_pct['range_pct'] = (self.stats['range_signals'] / total) * 100

        return stats_with_pct

    def get_optimizable_params(self) -> Dict:
        """
        Retourne tous les paramètres optimisables des 3 stratégies

        Format: {'strategy_name.param_name': (min, max)}
        """
        params = {}

        # Params Bull
        bull_params = self.bull_strategy.get_optimizable_params()
        for k, v in bull_params.items():
            params[f'bull.{k}'] = v

        # Params Bear
        bear_params = self.bear_strategy.get_optimizable_params()
        for k, v in bear_params.items():
            params[f'bear.{k}'] = v

        # Params Range (V10)
        # V10RangeStrategy n'a pas de get_optimizable_params(), on les définit ici
        params['range.rsi_oversold'] = (20, 40)
        params['range.rsi_overbought'] = (60, 80)
        params['range.range_atr_threshold'] = (0.20, 0.50)
        params['range.min_confidence'] = (60, 80)
        params['range.sl_atr_multiplier'] = (0.5, 2.5)
        params['range.trailing_pct'] = (0.03, 0.20)

        return params


if __name__ == '__main__':
    print("🎯 Hybrid Strategy - Test")
    print("=" * 80)
    print()
    print("Stratégie adaptative intelligente")
    print()
    print("Détecte automatiquement le régime de marché:")
    print("  • BULL → bull_strategy.py")
    print("  • BEAR → bear_strategy.py")
    print("  • RANGE → v10_range_strategy.py")
    print()
    print("Avantages:")
    print("  ✅ Adaptation automatique aux conditions")
    print("  ✅ Performance optimale pour chaque régime")
    print("  ✅ Une seule stratégie à gérer")
    print()

    strategy = HybridStrategy(leverage=200)
    print(f"Paramètres optimisables: {len(strategy.get_optimizable_params())}")
    print()
    print("Exemple params:")
    for k, v in list(strategy.get_optimizable_params().items())[:5]:
        print(f"  {k}: {v}")
    print("  ...")
