#!/usr/bin/env python3
"""
MARKET DETECTOR - Détection intelligente du régime de marché
Combine indicateurs techniques + mini LLM (à venir)

Classification:
- BULL: Tendance haussière forte
- BEAR: Tendance baissière forte
- RANGE: Marché latéral/consolidation
"""

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

# Import des détecteurs spécifiques
from bull_strategy import BullDetector
from bear_strategy import BearDetector
from v10_range_strategy import V10RangeDetector


class MarketRegime(Enum):
    """Types de régimes de marché"""
    BULL = "BULL"
    BEAR = "BEAR"
    RANGE = "RANGE"
    UNCERTAIN = "UNCERTAIN"


@dataclass
class MarketAnalysis:
    """Analyse complète du marché"""
    regime: MarketRegime
    confidence: float  # 0-100
    bull_score: float  # 0-100
    bear_score: float  # 0-100
    range_score: float  # 0-100
    volatility: float  # ATR %
    reason: str


class MarketDetector:
    """
    Détecteur de régime de marché hybride

    Méthodes:
    1. Indicateurs techniques (bull/bear/range detectors)
    2. Mini LLM pour contexte macro (TODO: à intégrer)
    """

    def __init__(self, use_llm: bool = False):
        self.use_llm = use_llm  # Pour intégration future

        # Thresholds de classification
        self.thresholds = {
            'strong_bull': 70,  # Bull score > 70 = BULL confirmé
            'strong_bear': 70,  # Bear score > 70 = BEAR confirmé
            'range_confirmed': True,  # Range detector doit confirmer
            'min_confidence': 60,  # Confidence minimum pour classification
        }

    def detect(self, df: pd.DataFrame) -> MarketAnalysis:
        """
        Détecte le régime de marché actuel

        Args:
            df: DataFrame avec OHLCV

        Returns:
            MarketAnalysis avec régime détecté
        """
        if len(df) < 100:
            return MarketAnalysis(
                regime=MarketRegime.UNCERTAIN,
                confidence=0,
                bull_score=0,
                bear_score=0,
                range_score=0,
                volatility=0,
                reason="Données insuffisantes"
            )

        # 1. Calculer scores des 3 détecteurs
        bull_score = BullDetector.calculate_trend_strength(df)
        bear_score = BearDetector.calculate_trend_strength(df)
        is_range = V10RangeDetector.is_range_market(df)

        # 2. Calculer volatilité (ATR%)
        tr1 = df['high'] - df['low']
        tr2 = abs(df['high'] - df['close'].shift())
        tr3 = abs(df['low'] - df['close'].shift())
        tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
        atr = tr.rolling(14).mean().iloc[-1]
        price = df['close'].iloc[-1]
        volatility_pct = (atr / price) * 100

        # 3. Score RANGE (basé sur volatilité basse + détecteur)
        range_score = 0
        if is_range:
            range_score = 100 - (volatility_pct / 0.5 * 50)  # Inverse volatilité
            range_score = max(0, min(100, range_score))

        # 4. Normaliser scores (s'ils se chevauchent)
        total_score = bull_score + bear_score + range_score
        if total_score > 100:
            # Normaliser pour que total = 100
            factor = 100 / total_score
            bull_score *= factor
            bear_score *= factor
            range_score *= factor

        # 5. Classifier selon scores dominants
        regime, confidence, reason = self._classify_regime(
            bull_score, bear_score, range_score, volatility_pct, is_range
        )

        # 6. (TODO) Enrichir avec LLM si activé
        if self.use_llm:
            regime, confidence = self._enhance_with_llm(
                regime, confidence, df
            )

        return MarketAnalysis(
            regime=regime,
            confidence=confidence,
            bull_score=bull_score,
            bear_score=bear_score,
            range_score=range_score,
            volatility=volatility_pct,
            reason=reason
        )

    def _classify_regime(
        self,
        bull_score: float,
        bear_score: float,
        range_score: float,
        volatility: float,
        is_range: bool
    ) -> tuple[MarketRegime, float, str]:
        """
        Classifie le régime selon les scores
        """

        # Trouver score dominant
        scores = {
            'BULL': bull_score,
            'BEAR': bear_score,
            'RANGE': range_score
        }

        dominant = max(scores, key=scores.get)
        dominant_score = scores[dominant]

        # Vérifier si assez confiant
        if dominant_score < self.thresholds['min_confidence']:
            return MarketRegime.UNCERTAIN, dominant_score, f"Scores trop faibles (max: {dominant_score:.0f})"

        # Classifier
        if dominant == 'BULL' and bull_score >= self.thresholds['strong_bull']:
            confidence = bull_score
            reason = f"Tendance haussière forte (score: {bull_score:.0f}, vol: {volatility:.2f}%)"
            return MarketRegime.BULL, confidence, reason

        elif dominant == 'BEAR' and bear_score >= self.thresholds['strong_bear']:
            confidence = bear_score
            reason = f"Tendance baissière forte (score: {bear_score:.0f}, vol: {volatility:.2f}%)"
            return MarketRegime.BEAR, confidence, reason

        elif dominant == 'RANGE' and is_range:
            confidence = range_score
            reason = f"Marché latéral (volatilité: {volatility:.2f}%, touches S/R confirmées)"
            return MarketRegime.RANGE, confidence, reason

        # Si scores proches, incertain
        scores_sorted = sorted(scores.values(), reverse=True)
        if len(scores_sorted) >= 2 and scores_sorted[0] - scores_sorted[1] < 15:
            return MarketRegime.UNCERTAIN, dominant_score, f"Scores trop proches (BULL:{bull_score:.0f} BEAR:{bear_score:.0f} RANGE:{range_score:.0f})"

        # Fallback sur dominant
        regime_map = {
            'BULL': MarketRegime.BULL,
            'BEAR': MarketRegime.BEAR,
            'RANGE': MarketRegime.RANGE
        }

        return (
            regime_map[dominant],
            dominant_score,
            f"{dominant} dominant (score: {dominant_score:.0f})"
        )

    def _enhance_with_llm(
        self,
        regime: MarketRegime,
        confidence: float,
        df: pd.DataFrame
    ) -> tuple[MarketRegime, float]:
        """
        (TODO) Enrichir la détection avec un mini LLM

        Le LLM analyserait:
        - Contexte macro (news, sentiment)
        - Patterns complexes sur graphe
        - Corrélation avec autres assets

        Pour l'instant: placeholder
        """
        # TODO: Intégrer mini LLM local (distilgpt2, phi-3, etc.)
        # Exemple pseudo-code:
        #
        # prompt = f"Analyse le marché BTC: {regime.value}, confidence {confidence}%"
        # llm_response = llm.analyze(prompt, market_data=df)
        # adjusted_regime = llm_response['regime']
        # adjusted_confidence = llm_response['confidence']
        #
        # return adjusted_regime, adjusted_confidence

        return regime, confidence  # Pas d'ajustement pour l'instant


if __name__ == '__main__':
    print("🔍 Market Detector - Test")
    print("=" * 80)
    print()
    print("Détecte le régime de marché actuel:")
    print("  • BULL: Tendance haussière forte")
    print("  • BEAR: Tendance baissière forte")
    print("  • RANGE: Marché latéral/consolidation")
    print("  • UNCERTAIN: Pas de régime clair")
    print()
    print("Méthodes:")
    print("  ✅ Indicateurs techniques (Bull/Bear/Range detectors)")
    print("  ⏳ Mini LLM (TODO - intégration future)")
    print()
    print("Thresholds:")
    detector = MarketDetector()
    for k, v in detector.thresholds.items():
        print(f"  {k}: {v}")
