"""
Test de la stratégie BI-MODALE:
- En RANGE: Inverser les signaux (mean reversion)
- En TREND: Garder les signaux normaux (momentum)

Comparaison avec stratégie RANGE-only actuelle
"""

import logging
import pandas as pd
import numpy as np
from apollo_client import ApolloDegenClient
from strategies.inverse_strategy_v10 import InverseStrategyV10, InverseBacktesterV10
from signals.short_term_signals import ShortTermSignalGenerator
from strategies.inverse_strategy_optimized import MarketRegimeDetectorAdvanced
import config

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

# Désactiver logs verbeux
for module in ['InverseStrategy', 'ShortTermSignalGenerator', 'ApolloDegenClient',
               'MarketRegimeDetectorAdvanced', 'InverseStrategyV10', 'InverseBacktesterV10']:
    logging.getLogger(module).setLevel(logging.WARNING)


class BimodalStrategy(InverseStrategyV10):
    """
    Stratégie BI-MODALE:
    - RANGE: Inverse les signaux (comme V10)
    - TREND: Garde les signaux normaux (momentum/breakout)
    """

    def __init__(self):
        super().__init__()
        self.logger.info("🔄 BimodalStrategy initialisée (RANGE + TREND)")

    def generate_signal(self, df, symbol):
        """Génère signal selon régime: inversé en RANGE, normal en TREND"""

        regime = self.regime_detector.detect_regime(df)
        signals = self.signal_generator.generate_signals(df, symbol)

        if not signals:
            return None

        # Filtrage et scoring
        best_score = 0
        best_signal = None

        for sig in signals:
            base_strategy = sig.strategy
            perf = self.strategy_performance[base_strategy]

            # Skip mauvaises stratégies
            if perf['losses'] >= 2 and perf['wins'] == 0:
                continue

            # Boost score
            total_trades = perf['wins'] + perf['losses']
            if total_trades > 0:
                win_rate = perf['wins'] / total_trades
                adjusted_score = sig.score * (1.1 if win_rate >= 0.8 else 1.0)
            else:
                adjusted_score = sig.score

            if adjusted_score > best_score:
                best_score = adjusted_score
                best_signal = sig

        if not best_signal:
            best_signal = max(signals, key=lambda x: x.score)

        # BI-MODAL LOGIC
        if regime == 'RANGE':
            # RANGE: INVERSER (mean reversion)
            inverse_side = 'SHORT' if best_signal.side == 'LONG' else 'LONG'

            from signals.short_term_signals import Signal
            return Signal(
                symbol=symbol,
                side=inverse_side,
                score=best_signal.score,
                strategy=f'BIMODAL_INVERSE_{best_signal.strategy}',
                entry_price=best_signal.entry_price,
                stop_loss=best_signal.take_profit,  # Inversé
                take_profit=best_signal.stop_loss,  # Inversé
                confluences=best_signal.confluences + [f'RANGE_INVERSE'],
                timeframe=best_signal.timeframe,
                timestamp=best_signal.timestamp
            )

        elif regime in ['UPTREND', 'DOWNTREND']:
            # TREND: GARDER SIGNAL NORMAL (momentum)
            from signals.short_term_signals import Signal
            return Signal(
                symbol=symbol,
                side=best_signal.side,  # PAS inversé
                score=best_signal.score,
                strategy=f'BIMODAL_TREND_{best_signal.strategy}',
                entry_price=best_signal.entry_price,
                stop_loss=best_signal.stop_loss,  # Normal
                take_profit=best_signal.take_profit,  # Normal
                confluences=best_signal.confluences + [f'{regime}_MOMENTUM'],
                timeframe=best_signal.timeframe,
                timestamp=best_signal.timestamp
            )

        return None


class BimodalBacktester(InverseBacktesterV10):
    """Backtester pour stratégie bimodale"""

    def __init__(self, initial_capital: float = 1000):
        super().__init__(initial_capital)
        self.strategy = BimodalStrategy()  # Override avec stratégie bimodale


if __name__ == '__main__':
    logger.info("="*80)
    logger.info("🔬 TEST COMPARATIF - STRATÉGIE BI-MODALE")
    logger.info("="*80)
    logger.info("")
    logger.info("Comparaison de 3 approches:")
    logger.info("  1. RANGE ONLY    - Inverse en range, skip en trend")
    logger.info("  2. TREND ONLY    - Skip en range, normal en trend")
    logger.info("  3. BI-MODAL      - Inverse en range, normal en trend")
    logger.info("="*80)
    logger.info("")

    # Charger données
    client = ApolloDegenClient()
    df = client.get_klines('BTCUSDT', '1m', limit=1500)

    logger.info(f"Données: {len(df)} chandeliers BTC 1m\n")

    results = {}

    # Test 1: RANGE ONLY (stratégie actuelle V10)
    logger.info("1️⃣  Test RANGE ONLY (V10 actuelle)...")
    try:
        bt_range = InverseBacktesterV10(initial_capital=1000)
        results['RANGE_ONLY'] = bt_range.backtest(df, 'BTCUSDT')
    except Exception as e:
        logger.error(f"Erreur RANGE_ONLY: {e}")
        results['RANGE_ONLY'] = None

    # Test 2: BI-MODAL (RANGE inversé + TREND normal)
    logger.info("\n2️⃣  Test BI-MODAL (Range inversé + Trend normal)...")
    try:
        bt_bimodal = BimodalBacktester(initial_capital=1000)
        results['BIMODAL'] = bt_bimodal.backtest(df, 'BTCUSDT')
    except Exception as e:
        logger.error(f"Erreur BI-MODAL: {e}")
        results['BIMODAL'] = None

    # Résultats comparatifs
    logger.info("\n" + "="*80)
    logger.info("📊 RÉSULTATS COMPARATIFS")
    logger.info("="*80)
    logger.info("")

    logger.info(f"{'Stratégie':<20} {'Return%':<12} {'WR%':<10} {'Trades':<10} {'PF':<10}")
    logger.info("-"*80)

    for name, result in results.items():
        if result:
            logger.info(
                f"{name:<20} "
                f"{result['total_return']:<12.2f} "
                f"{result['win_rate']*100:<10.0f} "
                f"{len(result['trades']):<10} "
                f"{result['profit_factor']:<10.2f}"
            )
        else:
            logger.info(f"{name:<20} {'ERROR':<12}")

    # Analyse détaillée
    if results['RANGE_ONLY'] and results['BIMODAL']:
        logger.info("\n" + "="*80)
        logger.info("🔍 ANALYSE DÉTAILLÉE")
        logger.info("="*80)
        logger.info("")

        range_only = results['RANGE_ONLY']
        bimodal = results['BIMODAL']

        # Différence de trades
        diff_trades = len(bimodal['trades']) - len(range_only['trades'])
        diff_return = bimodal['total_return'] - range_only['total_return']

        logger.info(f"📈 Trades supplémentaires (BI-MODAL): {diff_trades:+d}")
        logger.info(f"📈 Return supplémentaire (BI-MODAL): {diff_return:+.2f} points")
        logger.info("")

        # Analyser les trades TREND dans bimodal
        trend_trades = [t for t in bimodal['trades'] if 'TREND' in t['strategy']]
        range_trades = [t for t in bimodal['trades'] if 'INVERSE' in t['strategy']]

        if trend_trades:
            trend_wins = sum(1 for t in trend_trades if t['pnl_usd'] > 0)
            trend_wr = trend_wins / len(trend_trades) * 100
            trend_pnl = sum(t['pnl_usd'] for t in trend_trades)

            logger.info(f"🔼 TRADES EN TREND:")
            logger.info(f"   Nombre:      {len(trend_trades)}")
            logger.info(f"   Win Rate:    {trend_wr:.1f}%")
            logger.info(f"   PnL Total:   ${trend_pnl:+.2f}")
            logger.info("")

        if range_trades:
            range_wins = sum(1 for t in range_trades if t['pnl_usd'] > 0)
            range_wr = range_wins / len(range_trades) * 100
            range_pnl = sum(t['pnl_usd'] for t in range_trades)

            logger.info(f"↔️  TRADES EN RANGE:")
            logger.info(f"   Nombre:      {len(range_trades)}")
            logger.info(f"   Win Rate:    {range_wr:.1f}%")
            logger.info(f"   PnL Total:   ${range_pnl:+.2f}")
            logger.info("")

        # Conclusion
        logger.info("="*80)
        if diff_return > 0:
            logger.info("✅ CONCLUSION: BI-MODAL EST MEILLEUR!")
            logger.info(f"   Amélioration: +{diff_return:.2f} points ({diff_trades:+d} trades)")
            logger.info("   Recommandation: Activer mode BI-MODAL")
        elif diff_return < -5:
            logger.info("⚠️  CONCLUSION: RANGE ONLY EST MEILLEUR")
            logger.info(f"   Les trades TREND ont dégradé la performance de {diff_return:.2f} points")
            logger.info("   Recommandation: Rester en RANGE ONLY")
        else:
            logger.info("➡️  CONCLUSION: PERFORMANCES ÉQUIVALENTES")
            logger.info("   Différence non significative")
            logger.info("   Choix selon préférence (fréquence vs sélectivité)")
        logger.info("="*80)

    logger.info("\n")
