"""
Exploration EXHAUSTIVE de toutes les configurations possibles
"""

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

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

print("\n" + "="*100)
print("🔬 EXPLORATION EXHAUSTIVE - RECHERCHE DE CONFIGURATIONS PROFITABLES")
print("="*100)

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

signal_gen = ShortTermSignalGenerator()
inverse_strategy = InverseStrategyV10()

# Paramètres à tester
test_configs = {
    'inversion': [False, True],  # Direct ou Inversé
    'sl_pct': [0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.01],
    'tp_ratio': [2, 3, 4, 5, 6, 8, 10, 15, 20],
    'leverage': [50, 100, 150, 200, 250]
}

results = []
total_tests = len(test_configs['inversion']) * len(test_configs['sl_pct']) * len(test_configs['tp_ratio']) * len(test_configs['leverage'])

print(f"\n📊 Tests à effectuer: {total_tests}")
print(f"⏱️  Estimation: ~{total_tests * 2}s\n")

current_test = 0

for use_inversion in test_configs['inversion']:
    for sl_pct in test_configs['sl_pct']:
        for tp_ratio in test_configs['tp_ratio']:
            for leverage in test_configs['leverage']:
                current_test += 1

                if current_test % 50 == 0:
                    print(f"  Progress: {current_test}/{total_tests} ({current_test/total_tests*100:.1f}%)")

                try:
                    # Backtest simulation
                    capital = 1000
                    trades = []
                    risk_per_trade = 0.1  # 10% du capital par trade

                    for i in range(100, len(df) - 50, 20):  # Check every 20 candles
                        if len([t for t in trades if 'exit_idx' not in t]) >= 3:  # Max 3 positions parallèles
                            continue

                        window_df = df.iloc[:i]

                        # Générer signal
                        if use_inversion:
                            signal = inverse_strategy.generate_inverse_signal(window_df, 'BTCUSDT')
                        else:
                            signals = signal_gen.generate_signals(window_df, 'BTCUSDT')
                            signal = max(signals, key=lambda x: x.score) if signals else None

                        if not signal:
                            continue

                        # Entry
                        entry_price = df.iloc[i]['close']
                        entry_idx = i

                        # Calculate SL/TP
                        if signal.side == 'LONG':
                            sl = entry_price * (1 - sl_pct)
                            tp = entry_price * (1 + sl_pct * tp_ratio)
                        else:  # SHORT
                            sl = entry_price * (1 + sl_pct)
                            tp = entry_price * (1 - sl_pct * tp_ratio)

                        # Track trade
                        trades.append({
                            'entry_price': entry_price,
                            'entry_idx': entry_idx,
                            'side': signal.side,
                            'sl': sl,
                            'tp': tp
                        })

                    # Process exits for all trades
                    for trade in trades:
                        if 'exit_idx' in trade:
                            continue

                        for j in range(trade['entry_idx'] + 1, len(df)):
                            candle = df.iloc[j]

                            exit_price = None
                            exit_reason = None

                            if trade['side'] == 'LONG':
                                if candle['low'] <= trade['sl']:
                                    exit_price = trade['sl']
                                    exit_reason = 'SL'
                                elif candle['high'] >= trade['tp']:
                                    exit_price = trade['tp']
                                    exit_reason = 'TP'
                            else:  # SHORT
                                if candle['high'] >= trade['sl']:
                                    exit_price = trade['sl']
                                    exit_reason = 'SL'
                                elif candle['low'] <= trade['tp']:
                                    exit_price = trade['tp']
                                    exit_reason = 'TP'

                            if exit_price:
                                # Calculate PnL
                                if trade['side'] == 'LONG':
                                    pnl_pct = (exit_price - trade['entry_price']) / trade['entry_price']
                                else:  # SHORT
                                    pnl_pct = (trade['entry_price'] - exit_price) / trade['entry_price']

                                pnl_usd = capital * risk_per_trade * leverage * pnl_pct
                                capital += pnl_usd

                                trade['exit_idx'] = j
                                trade['exit_price'] = exit_price
                                trade['exit_reason'] = exit_reason
                                trade['pnl_pct'] = pnl_pct * 100
                                trade['pnl_usd'] = pnl_usd
                                break

                    # Calculate stats
                    completed_trades = [t for t in trades if 'exit_idx' in t]

                    if len(completed_trades) < 5:  # Skip if too few trades
                        continue

                    final_capital = capital
                    total_return = ((final_capital - 1000) / 1000) * 100

                    wins = [t for t in completed_trades if t['pnl_usd'] > 0]
                    losses = [t for t in completed_trades if t['pnl_usd'] <= 0]

                    win_rate = len(wins) / len(completed_trades) if completed_trades else 0

                    avg_win = np.mean([t['pnl_pct'] for t in wins]) if wins else 0
                    avg_loss = np.mean([t['pnl_pct'] for t in losses]) if losses else 0

                    total_wins = sum(t['pnl_usd'] for t in wins) if wins else 0
                    total_losses = abs(sum(t['pnl_usd'] for t in losses)) if losses else 1
                    profit_factor = total_wins / total_losses if total_losses > 0 else 0

                    # Store result
                    results.append({
                        'inversion': use_inversion,
                        'sl_pct': sl_pct,
                        'tp_ratio': tp_ratio,
                        'leverage': leverage,
                        'return': total_return,
                        'win_rate': win_rate,
                        'profit_factor': profit_factor,
                        'trades': len(completed_trades),
                        'avg_win': avg_win,
                        'avg_loss': avg_loss,
                        'final_capital': final_capital
                    })

                except Exception as e:
                    pass

# Analyse des résultats
print("\n" + "="*100)
print("📊 ANALYSE DES RÉSULTATS")
print("="*100)

if not results:
    print("\n❌ Aucun résultat trouvé")
else:
    # Top 20 configurations
    sorted_results = sorted(results, key=lambda x: x['return'], reverse=True)[:20]

    print(f"\n🏆 TOP 20 CONFIGURATIONS PROFITABLES\n")
    print(f"{'Rank':<5} {'Inv':<4} {'SL%':<6} {'TP:1':<6} {'Lev':<6} {'Return%':<10} {'WR%':<7} {'PF':<7} {'Trades':<8} {'AvgW/L':<12}")
    print("-"*100)

    for i, r in enumerate(sorted_results, 1):
        inv_str = "YES" if r['inversion'] else "NO"
        ratio_str = f"{r['avg_win']/abs(r['avg_loss']) if r['avg_loss'] != 0 else 0:.2f}:1"

        print(
            f"{i:<5} {inv_str:<4} {r['sl_pct']*100:<6.2f} {r['tp_ratio']:<6} {r['leverage']:<6} "
            f"{r['return']:<10.2f} {r['win_rate']*100:<7.1f} {r['profit_factor']:<7.2f} "
            f"{r['trades']:<8} {ratio_str:<12}"
        )

    # Meilleure config
    best = sorted_results[0]

    print("\n" + "="*100)
    print("🥇 MEILLEURE CONFIGURATION")
    print("="*100)
    print(f"Stratégie:       {'INVERSÉE (V10)' if best['inversion'] else 'DIRECTE (signaux normaux)'}")
    print(f"Stop-Loss:       {best['sl_pct']*100:.2f}%")
    print(f"Take-Profit:     {best['sl_pct']*100*best['tp_ratio']:.2f}% (ratio {best['tp_ratio']}:1)")
    print(f"Leverage:        {best['leverage']}x")
    print(f"")
    print(f"Return:          {best['return']:+.2f}%")
    print(f"Win Rate:        {best['win_rate']*100:.1f}%")
    print(f"Profit Factor:   {best['profit_factor']:.2f}")
    print(f"Total Trades:    {best['trades']}")
    print(f"Avg Win:         {best['avg_win']:+.2f}%")
    print(f"Avg Loss:        {best['avg_loss']:+.2f}%")
    print(f"Reward:Risk:     {best['avg_win']/abs(best['avg_loss']) if best['avg_loss'] != 0 else 0:.2f}:1")
    print(f"Final Capital:   ${best['final_capital']:.2f}")

    # Statistiques par type
    print("\n" + "="*100)
    print("📈 STATISTIQUES PAR TYPE")
    print("="*100)

    profitable = [r for r in results if r['return'] > 0]
    with_inversion = [r for r in profitable if r['inversion']]
    without_inversion = [r for r in profitable if not r['inversion']]

    print(f"\nTotal configs testées:        {len(results)}")
    print(f"Configs profitables:          {len(profitable)} ({len(profitable)/len(results)*100:.1f}%)")
    print(f"  - AVEC inversion:           {len(with_inversion)}")
    print(f"  - SANS inversion (direct):  {len(without_inversion)}")

    if with_inversion:
        avg_return_inv = np.mean([r['return'] for r in with_inversion])
        print(f"\nAvg return AVEC inversion:    {avg_return_inv:+.2f}%")

    if without_inversion:
        avg_return_direct = np.mean([r['return'] for r in without_inversion])
        print(f"Avg return SANS inversion:    {avg_return_direct:+.2f}%")

    print("\n" + "="*100)

    # Recommandation
    if best['return'] > 10:
        print("✅ Configuration profitable trouvée ! Prête à être appliquée.")
    elif best['return'] > 0:
        print("⚠️  Configuration légèrement profitable. Besoin d'optimisation supplémentaire.")
    else:
        print("❌ Aucune configuration profitable trouvée sur cette période.")

    print("="*100)
