"""
DYNAMIC SL/TP CALCULATOR - Ajustement intelligent basé sur l'IA
================================================================

Calcule des niveaux de Stop-Loss et Take-Profit dynamiques adaptés à :
1. La volatilité de la crypto (volatility_scorer)
2. Le régime de marché (market_regime)
3. La prédiction IA (ai_opportunity_selector)
4. L'ATR (Average True Range)

Au lieu de SL/TP fixes, chaque trade a des niveaux optimisés pour son contexte.
"""

import logging
from typing import Dict, Tuple, Optional
import numpy as np
from config import STOP_LOSS_PERCENT, TAKE_PROFIT_PERCENT

logger = logging.getLogger("DynamicSLTP")

# === CONFIGURATION ===
MIN_STOP_LOSS = 1.5      # SL minimum (très stable)
MAX_STOP_LOSS = 4.0      # SL maximum (très volatile)
MIN_TAKE_PROFIT = 3.0    # TP minimum
MAX_TAKE_PROFIT = 8.0    # TP maximum
MIN_RISK_REWARD_RATIO = 1.8  # Ratio R/R minimum acceptable

# 🔴 FIX 04/02: TP minimum pour CREUX_REBOUND (pattern de rebond = potentiel plus élevé)
# En BEAR market, le TP était réduit à 1% ce qui coupait les gains prématurément
MIN_TAKE_PROFIT_CREUX_REBOUND = 4.0  # TP minimum pour rebonds (au lieu de 3%)


class DynamicSLTPCalculator:
    """
    Calcule des SL/TP dynamiques adaptés au contexte de chaque trade
    """
    
    def __init__(self):
        """Initialise le calculateur"""
        self.base_sl = STOP_LOSS_PERCENT
        self.base_tp = TAKE_PROFIT_PERCENT
        logger.info(f"✅ Dynamic SL/TP Calculator initialisé (Base SL={self.base_sl}% TP={self.base_tp}%)")
    
    def calculate_sltp(self, 
                       symbol: str,
                       volatility_score: float = 50.0,
                       predicted_volatility_6h: float = 0.0,
                       market_regime: str = "NEUTRAL",
                       atr_percent: float = 0.0,
                       ai_confidence: float = 50.0,
                       pattern: str = "NEUTRAL") -> Tuple[float, float]:
        """
        Calcule SL/TP optimaux pour ce trade spécifique
        
        Args:
            symbol: Symbole de la crypto (ex: BTCUSDT)
            volatility_score: Score volatilité (0-100) de volatility_scorer
            predicted_volatility_6h: Volatilité prédite 6h (0-10%) par AI
            market_regime: Régime marché (BULL_STRONG, BULL_WEAK, NEUTRAL, CORRECTION, BEAR)
            atr_percent: ATR en % du prix actuel
            ai_confidence: Confiance IA (0-100%)
            pattern: Pattern de trade (CREUX_REBOUND, TREND_CONTINUATION, etc.)
        
        Returns:
            (stop_loss_pct, take_profit_pct): Pourcentages ajustés
        """
        
        # === 1. BASE: Configuration par défaut ===
        sl_pct = self.base_sl
        tp_pct = self.base_tp
        
        adjustments = []
        
        # === 2. AJUSTEMENT VOLATILITÉ (Facteur principal) ===
        # Plus volatile = SL plus large (éviter stop-out prématuré)
        if volatility_score > 0:
            vol_multiplier = 1.0
            
            if volatility_score >= 80:  # Crypto très volatile (SOL-like)
                vol_multiplier = 1.5
                adjustments.append(f"Vol HIGH ({volatility_score:.0f}): SL x1.5")
            elif volatility_score >= 60:  # Volatile
                vol_multiplier = 1.3
                adjustments.append(f"Vol GOOD ({volatility_score:.0f}): SL x1.3")
            elif volatility_score >= 40:  # Moyenne
                vol_multiplier = 1.1
                adjustments.append(f"Vol MED ({volatility_score:.0f}): SL x1.1")
            else:  # Faible volatilité
                vol_multiplier = 0.9
                adjustments.append(f"Vol LOW ({volatility_score:.0f}): SL x0.9")
            
            sl_pct *= vol_multiplier
            tp_pct *= vol_multiplier
        
        # === 3. AJUSTEMENT VOLATILITÉ PRÉDITE (IA) ===
        # Utilise la prédiction de volatilité future (plus précis que historique)
        if predicted_volatility_6h > 0:
            if predicted_volatility_6h >= 6.0:  # Très forte volatilité attendue
                sl_pct *= 1.4
                tp_pct *= 1.6  # Profiter de la volatilité
                adjustments.append(f"IA Vol 6h={predicted_volatility_6h:.1f}%: SL x1.4, TP x1.6")
            elif predicted_volatility_6h >= 4.0:  # Forte volatilité
                sl_pct *= 1.2
                tp_pct *= 1.3
                adjustments.append(f"IA Vol 6h={predicted_volatility_6h:.1f}%: SL x1.2, TP x1.3")
            elif predicted_volatility_6h <= 1.5:  # Faible volatilité
                sl_pct *= 0.8
                tp_pct *= 0.7  # TP plus serré (pas de gros mouvements attendus)
                adjustments.append(f"IA Vol 6h={predicted_volatility_6h:.1f}%: SL x0.8, TP x0.7")
        
        # === 4. AJUSTEMENT RÉGIME DE MARCHÉ ===
        regime_adjustments = {
            'BULL_STRONG': (1.0, 1.4),   # SL normal, TP large (laisser courir)
            'BULL_WEAK': (1.0, 1.2),     # Légèrement optimiste
            'NEUTRAL': (1.0, 1.0),       # Pas d'ajustement
            'CORRECTION': (0.8, 0.7),    # SL serré, TP serré (protection)
            'BEAR': (0.7, 0.5),          # Très défensif
        }
        
        if market_regime in regime_adjustments:
            sl_mult, tp_mult = regime_adjustments[market_regime]
            sl_pct *= sl_mult
            tp_pct *= tp_mult
            if sl_mult != 1.0 or tp_mult != 1.0:
                adjustments.append(f"Regime {market_regime}: SL x{sl_mult}, TP x{tp_mult}")
        
        # === 5. AJUSTEMENT ATR (Average True Range) ===
        # ATR représente la volatilité réelle récente
        if atr_percent > 0:
            if atr_percent >= 5.0:  # Très volatile récemment
                sl_pct *= 1.3
                adjustments.append(f"ATR={atr_percent:.1f}%: SL x1.3")
            elif atr_percent >= 3.0:  # Volatile
                sl_pct *= 1.15
                adjustments.append(f"ATR={atr_percent:.1f}%: SL x1.15")
            elif atr_percent <= 1.0:  # Stable
                sl_pct *= 0.85
                adjustments.append(f"ATR={atr_percent:.1f}%: SL x0.85")
        
        # === 6. AJUSTEMENT CONFIANCE IA ===
        # Plus la confiance est élevée, plus on peut être agressif sur TP
        if ai_confidence >= 80:  # Très confiant
            tp_pct *= 1.2
            adjustments.append(f"AI Conf={ai_confidence:.0f}%: TP x1.2")
        elif ai_confidence <= 40:  # Peu confiant
            tp_pct *= 0.8
            sl_pct *= 0.9  # SL plus serré aussi (trade incertain)
            adjustments.append(f"AI Conf={ai_confidence:.0f}%: SL x0.9, TP x0.8")
        
        # === 7. LIMITES ET RATIO R/R ===
        # 🔴 FIX 04/02: TP minimum plus élevé pour CREUX_REBOUND
        # Le pattern CREUX_REBOUND achète en creux et a un potentiel de rebond de 3-10%
        # Avec un TP à 1%, on coupe les gains prématurément (cas WLFI du 03/02)
        if pattern == 'CREUX_REBOUND':
            min_tp = MIN_TAKE_PROFIT_CREUX_REBOUND  # 4% au lieu de 3%
            adjustments.append(f"Pattern CREUX_REBOUND: TP min={min_tp}%")
        else:
            min_tp = MIN_TAKE_PROFIT
        
        # Appliquer les limites min/max
        sl_pct = max(MIN_STOP_LOSS, min(MAX_STOP_LOSS, sl_pct))
        tp_pct = max(min_tp, min(MAX_TAKE_PROFIT, tp_pct))
        
        # Garantir ratio R/R minimum
        risk_reward = tp_pct / sl_pct
        if risk_reward < MIN_RISK_REWARD_RATIO:
            tp_pct = sl_pct * MIN_RISK_REWARD_RATIO
            adjustments.append(f"R/R forcé à {MIN_RISK_REWARD_RATIO}:1")
        
        # === 8. LOGGING ===
        final_rr = tp_pct / sl_pct
        logger.info(f"📊 {symbol} - SL={sl_pct:.2f}% TP={tp_pct:.2f}% (R/R={final_rr:.2f}:1)")
        if adjustments:
            for adj in adjustments:
                logger.debug(f"   • {adj}")
        
        return round(sl_pct, 2), round(tp_pct, 2)
    
    def calculate_trailing_stop_distance(self,
                                         volatility_score: float = 50.0,
                                         predicted_volatility_6h: float = 0.0) -> float:
        """
        Calcule la distance du trailing stop adaptée à la volatilité
        
        Args:
            volatility_score: Score volatilité (0-100)
            predicted_volatility_6h: Volatilité prédite 6h
        
        Returns:
            trailing_stop_distance_pct: Distance en %
        """
        base_distance = 2.5  # De config.py
        
        # Plus volatile = trailing stop plus large (éviter sorties prématurées)
        if volatility_score >= 80 or predicted_volatility_6h >= 5.0:
            distance = base_distance * 1.5  # 3.75%
        elif volatility_score >= 60 or predicted_volatility_6h >= 3.0:
            distance = base_distance * 1.2  # 3.0%
        elif volatility_score <= 40 and predicted_volatility_6h <= 2.0:
            distance = base_distance * 0.8  # 2.0%
        else:
            distance = base_distance
        
        return round(distance, 2)


# === SINGLETON ===
_dynamic_sltp_calculator = None

def get_dynamic_sltp_calculator() -> DynamicSLTPCalculator:
    """Retourne l'instance singleton du calculateur"""
    global _dynamic_sltp_calculator
    if _dynamic_sltp_calculator is None:
        _dynamic_sltp_calculator = DynamicSLTPCalculator()
    return _dynamic_sltp_calculator


# === FONCTION HELPER POUR INTÉGRATION FACILE ===
def calculate_optimal_sltp(symbol: str, 
                           crypto_data: Dict,
                           market_regime: str = "NEUTRAL",
                           pattern: str = "NEUTRAL") -> Tuple[float, float]:
    """
    Fonction helper pour calculer SL/TP optimaux facilement
    
    Usage dans trading_bot.py:
        from dynamic_sltp import calculate_optimal_sltp
        sl, tp = calculate_optimal_sltp(symbol, crypto_data, market_regime, pattern)
        self.open_position(symbol, "BUY", amount, sl, tp)
    
    Args:
        symbol: Symbole crypto
        crypto_data: Données crypto (de ai_predictor ou trading_bot)
        market_regime: Régime marché actuel
        pattern: Pattern de trade (CREUX_REBOUND, etc.)
    
    Returns:
        (stop_loss_pct, take_profit_pct)
    """
    calculator = get_dynamic_sltp_calculator()
    
    # Extraire les données disponibles
    volatility_score = crypto_data.get('volatility_score', 50.0)
    ai_confidence = crypto_data.get('confidence', 50.0)
    atr_percent = crypto_data.get('atr_percent', 0.0)
    
    # Extraire le pattern des données si non fourni
    if pattern == "NEUTRAL" and 'pattern' in crypto_data:
        pattern = crypto_data.get('pattern', 'NEUTRAL')
    
    # Prédiction IA si disponible
    predicted_vol = 0.0
    if 'ai_opportunity' in crypto_data:
        predicted_vol = crypto_data['ai_opportunity'].get('predicted_volatility_6h', 0.0)
    elif 'predicted_volatility_6h' in crypto_data:
        predicted_vol = crypto_data['predicted_volatility_6h']
    
    return calculator.calculate_sltp(
        symbol=symbol,
        volatility_score=volatility_score,
        predicted_volatility_6h=predicted_vol,
        market_regime=market_regime,
        atr_percent=atr_percent,
        ai_confidence=ai_confidence,
        pattern=pattern
    )


if __name__ == "__main__":
    # Test du calculateur
    logging.basicConfig(level=logging.INFO)
    
    print("=" * 80)
    print("TEST DYNAMIC SL/TP CALCULATOR")
    print("=" * 80)
    print()
    
    calculator = get_dynamic_sltp_calculator()
    
    # Test 1: Crypto stable en marché neutre
    print("1️⃣  Crypto STABLE (BTC) - Marché NEUTRE")
    sl, tp = calculator.calculate_sltp(
        symbol="BTCUSDT",
        volatility_score=45,
        predicted_volatility_6h=2.0,
        market_regime="NEUTRAL",
        atr_percent=1.8,
        ai_confidence=70
    )
    print(f"   → SL={sl}% TP={tp}% (R/R={tp/sl:.2f}:1)")
    print()
    
    # Test 2: Crypto volatile en bull market
    print("2️⃣  Crypto VOLATILE (SOL) - Bull Market")
    sl, tp = calculator.calculate_sltp(
        symbol="SOLUSDT",
        volatility_score=85,
        predicted_volatility_6h=6.5,
        market_regime="BULL_STRONG",
        atr_percent=5.2,
        ai_confidence=80
    )
    print(f"   → SL={sl}% TP={tp}% (R/R={tp/sl:.2f}:1)")
    print()
    
    # Test 3: Crypto moyenne en correction
    print("3️⃣  Crypto MOYENNE - CORRECTION")
    sl, tp = calculator.calculate_sltp(
        symbol="ADAUSDT",
        volatility_score=55,
        predicted_volatility_6h=3.0,
        market_regime="CORRECTION",
        atr_percent=2.5,
        ai_confidence=50
    )
    print(f"   → SL={sl}% TP={tp}% (R/R={tp/sl:.2f}:1)")
    print()
    
    # Test 4: Crypto faible volatilité en bear market
    print("4️⃣  Crypto LOW VOL - Bear Market")
    sl, tp = calculator.calculate_sltp(
        symbol="XLMUSDT",
        volatility_score=35,
        predicted_volatility_6h=1.2,
        market_regime="BEAR",
        atr_percent=1.0,
        ai_confidence=40
    )
    print(f"   → SL={sl}% TP={tp}% (R/R={tp/sl:.2f}:1)")
    print()
    
    print("=" * 80)
    print("✅ Tests terminés")
