"""
Test de la stratégie BI-MODALE sur PLUSIEURS périodes
Pour valider si trader en TREND améliore vraiment la performance
"""

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 Signal, ShortTermSignalGenerator
from strategies.inverse_strategy_optimized import MarketRegimeDetectorAdvanced
from datetime import datetime, timedelta

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

# Silence logs
for module in ['InverseStrategy', 'ShortTermSignalGenerator', 'ApolloDegenClient',
               'MarketRegimeDetectorAdvanced', 'InverseStrategyV10',
               'InverseBacktesterV10', 'BimodalStrategy', 'BimodalBacktester']:
    logging.getLogger(module).setLevel(logging.ERROR)


class BimodalStrategy(InverseStrategyV10):
    """Stratégie BI-MODALE: Inverse en RANGE, Normal en TREND"""

    def generate_inverse_signal(self, df, symbol):
        """Override pour supporter TREND + RANGE"""
        regime = self.regime_detector.detect_regime(df)
        signals = self.signal_generator.generate_signals(df, symbol)

        if not signals:
            return None

        # Scoring
        best_score = 0
        best_signal = None

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

            if perf['losses'] >= 2 and perf['wins'] == 0:
                continue

            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
            inverse_side = 'SHORT' if best_signal.side == 'LONG' else 'LONG'
            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,
                take_profit=best_signal.stop_loss,
                confluences=best_signal.confluences + ['RANGE_INV'],
                timeframe=best_signal.timeframe,
                timestamp=best_signal.timestamp
            )

        elif regime in ['UPTREND', 'DOWNTREND']:
            # TREND: GARDER NORMAL
            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,
                take_profit=best_signal.take_profit,
                confluences=best_signal.confluences + [f'{regime}_MOM'],
                timeframe=best_signal.timeframe,
                timestamp=best_signal.timestamp
            )

        return None


class BimodalBacktester(InverseBacktesterV10):
    """Backtester bi-modal"""
    def __init__(self, initial_capital: float = 1000):
        super().__init__(initial_capital)
        self.strategy = BimodalStrategy()


def test_period(df, period_name):
    """Test une période donnée"""

    results = {
        'period': period_name,
        'candles': len(df),
        'range_only': None,
        'bimodal': None
    }

    # Test RANGE ONLY
    try:
        bt_range = InverseBacktesterV10(initial_capital=1000)
        range_result = bt_range.backtest(df, 'BTCUSDT')
        if range_result:
            results['range_only'] = {
                'return': range_result['total_return'],
                'wr': range_result['win_rate'] * 100,
                'trades': len(range_result['trades']),
                'pf': range_result['profit_factor']
            }
    except Exception as e:
        logger.error(f"Error RANGE ONLY {period_name}: {e}")

    # Test BIMODAL
    try:
        bt_bimodal = BimodalBacktester(initial_capital=1000)
        bimodal_result = bt_bimodal.backtest(df, 'BTCUSDT')
        if bimodal_result:
            # Compter trades par régime
            range_trades = [t for t in bimodal_result['trades'] if 'INVERSE' in t['strategy']]
            trend_trades = [t for t in bimodal_result['trades'] if 'TREND' in t['strategy']]

            results['bimodal'] = {
                'return': bimodal_result['total_return'],
                'wr': bimodal_result['win_rate'] * 100,
                'trades': len(bimodal_result['trades']),
                'pf': bimodal_result['profit_factor'],
                'range_trades': len(range_trades),
                'trend_trades': len(trend_trades)
            }
    except Exception as e:
        logger.error(f"Error BIMODAL {period_name}: {e}")

    return results


if __name__ == '__main__':
    print("="*80)
    print("🔬 TEST MULTI-PÉRIODES - RANGE ONLY vs BI-MODAL")
    print("="*80)
    print()

    client = ApolloDegenClient()

    # Tester différentes tailles d'échantillons
    test_configs = [
        {'limit': 500, 'name': 'Sample 1 (500 candles ~8h)'},
        {'limit': 1000, 'name': 'Sample 2 (1000 candles ~17h)'},
        {'limit': 1500, 'name': 'Sample 3 (1500 candles ~25h)'},
        {'limit': 2000, 'name': 'Sample 4 (2000 candles ~33h)'},
        {'limit': 3000, 'name': 'Sample 5 (3000 candles ~2j)'},
        {'limit': 5000, 'name': 'Sample 6 (5000 candles ~3.5j)'},
    ]

    all_results = []

    print("📊 Test en cours sur différentes périodes...")
    print()

    for i, config in enumerate(test_configs, 1):
        print(f"[{i}/6] Testing {config['name']}...", end=' ', flush=True)

        try:
            df = client.get_klines('BTCUSDT', '1m', limit=config['limit'])
            result = test_period(df, config['name'])
            all_results.append(result)
            print("✅")
        except Exception as e:
            print(f"❌ Error: {e}")
            continue

    # Afficher résultats
    print()
    print("="*80)
    print("📊 RÉSULTATS COMPARATIFS")
    print("="*80)
    print()

    print(f"{'Period':<30} {'Strategy':<15} {'Return%':<10} {'WR%':<8} {'Trades':<10}")
    print("-"*80)

    range_only_wins = 0
    bimodal_wins = 0
    ties = 0

    for result in all_results:
        period = result['period']

        # RANGE ONLY
        if result['range_only']:
            r = result['range_only']
            print(f"{period:<30} {'RANGE ONLY':<15} {r['return']:<10.2f} {r['wr']:<8.0f} {r['trades']:<10}")

        # BIMODAL
        if result['bimodal']:
            b = result['bimodal']
            print(f"{'':30} {'BI-MODAL':<15} {b['return']:<10.2f} {b['wr']:<8.0f} {b['trades']:<10}")

            # Compter gagnant
            if result['range_only']:
                diff = b['return'] - r['return']
                if diff > 1:
                    winner = "BI-MODAL"
                    bimodal_wins += 1
                elif diff < -1:
                    winner = "RANGE ONLY"
                    range_only_wins += 1
                else:
                    winner = "TIE"
                    ties += 1

                print(f"{'':30} {'→ Winner:':<15} {winner:<10} (Δ: {diff:+.2f}%)")

            # Afficher breakdown régime
            if b.get('trend_trades', 0) > 0:
                print(f"{'':30} {'  Details:':<15} Range: {b['range_trades']}, Trend: {b['trend_trades']}")

        print()

    # Statistiques globales
    print("="*80)
    print("🏆 STATISTIQUES GLOBALES")
    print("="*80)
    print()

    total_tests = range_only_wins + bimodal_wins + ties

    print(f"Tests effectués:     {total_tests}")
    print(f"RANGE ONLY gagne:    {range_only_wins} fois ({range_only_wins/total_tests*100:.1f}%)")
    print(f"BI-MODAL gagne:      {bimodal_wins} fois ({bimodal_wins/total_tests*100:.1f}%)")
    print(f"Égalité:             {ties} fois ({ties/total_tests*100:.1f}%)")
    print()

    # Moyennes
    range_returns = [r['range_only']['return'] for r in all_results if r['range_only']]
    bimodal_returns = [r['bimodal']['return'] for r in all_results if r['bimodal']]

    if range_returns and bimodal_returns:
        avg_range = np.mean(range_returns)
        avg_bimodal = np.mean(bimodal_returns)

        print(f"Return moyen RANGE ONLY: {avg_range:.2f}%")
        print(f"Return moyen BI-MODAL:   {avg_bimodal:.2f}%")
        print(f"Différence moyenne:      {avg_bimodal - avg_range:+.2f}%")
        print()

    # Compter trades en TREND
    total_trend_trades = sum(r['bimodal'].get('trend_trades', 0) for r in all_results if r['bimodal'])
    total_range_trades = sum(r['bimodal'].get('range_trades', 0) for r in all_results if r['bimodal'])
    total_all_trades = total_trend_trades + total_range_trades

    if total_all_trades > 0:
        print(f"Distribution des trades BI-MODAL:")
        print(f"  RANGE trades: {total_range_trades} ({total_range_trades/total_all_trades*100:.1f}%)")
        print(f"  TREND trades: {total_trend_trades} ({total_trend_trades/total_all_trades*100:.1f}%)")
        print()

    # Conclusion
    print("="*80)
    print("💡 CONCLUSION")
    print("="*80)
    print()

    if bimodal_wins > range_only_wins + 1:
        print("✅ RECOMMANDATION: Activer le mode BI-MODAL")
        print("   La stratégie bi-modale performe mieux sur la majorité des périodes")
        print("   Les trades en TREND ajoutent de la valeur")
    elif range_only_wins > bimodal_wins + 1:
        print("✅ RECOMMANDATION: Garder RANGE ONLY")
        print("   Les trades en TREND dégradent la performance")
        print("   Rester focus sur les range markets")
    else:
        print("➡️  RECOMMANDATION: Les deux approches sont équivalentes")
        print("   Choix selon préférence:")
        print("   - RANGE ONLY: Plus sélectif, moins de trades")
        print("   - BI-MODAL: Plus de trades, diversification")

    print()
    print("="*80)
