#!/usr/bin/env python3
"""
OPTIMISATION MASSIVE CONTINUE
Teste des milliers de combinaisons et sauvegarde tout
"""

import pandas as pd
import numpy as np
import random
import json
import os
from datetime import datetime
from time import sleep, time
from adaptive_strategy import AdaptiveStrategy
from backtest_adaptive import AdaptiveBacktest
import logging
import sys

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

class MassiveOptimizer:
    def __init__(self, worker_id: int = 0):
        self.worker_id = worker_id
        self.results_dir = 'optimization_results_massive'
        os.makedirs(self.results_dir, exist_ok=True)

        # Charger données
        self.df = pd.read_csv('historical_data/BTCUSDT_5m_2000candles.csv')
        self.df['timestamp'] = pd.to_datetime(self.df['timestamp'])

        self.tests_done = 0
        self.profitable_found = 0
        self.non_profitable_deleted = 0
        self.start_time = time()

        print(f"[Worker {worker_id}] 🚀 Démarrage optimisation massive")
        print(f"[Worker {worker_id}] 📊 Données: {len(self.df)} bougies")
        print(f"[Worker {worker_id}] 💾 Résultats: {self.results_dir}/")
        print(f"[Worker {worker_id}] ⚡ Prêt à tester des MILLIERS de combinaisons!\n")

    def generate_random_params(self):
        """Génère des paramètres aléatoires"""
        return {
            'leverage': random.choice([100, 110, 120, 125, 130, 140, 150]),
            'sl_atr_mult': random.uniform(0.5, 2.0),
            'tp_atr_mult': random.uniform(2.0, 6.0),
            'min_confidence': random.randint(65, 85),
            'position_pct': random.choice([15, 20, 25]),  # % du capital
        }

    def test_config(self, params):
        """Teste une configuration"""
        try:
            # Créer stratégie
            strategy = AdaptiveStrategy(leverage=params['leverage'])
            strategy.params['ranging']['sl_atr_multiplier'] = params['sl_atr_mult']
            strategy.params['ranging']['tp_atr_multiplier'] = params['tp_atr_mult']
            strategy.params['ranging']['min_confidence'] = params['min_confidence']

            # Backtest avec capital $500
            backtest = AdaptiveBacktest(strategy, initial_capital=500.0)
            # Note: position_pct sera géré plus tard si besoin
            results = backtest.run(self.df, "BTCUSD_DEGEN")

            if not results or results['total_trades'] == 0:
                return None

            return {
                'worker_id': self.worker_id,
                'timestamp': datetime.now().isoformat(),
                'params': params,
                'results': {
                    'total_trades': results['total_trades'],
                    'win_rate': results['win_rate'],
                    'total_pnl_pct': results['total_pnl_pct'],
                    'final_capital': results['final_capital'],
                    'profit_factor': results['profit_factor'],
                    'avg_win': results['avg_win'],
                    'avg_loss': results['avg_loss'],
                }
            }
        except Exception as e:
            logger.error(f"Error testing config: {e}")
            return None

    def save_result(self, result):
        """Sauvegarde un résultat (seulement si profitable)"""
        if not result:
            return

        # Fichier horodaté
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"{self.results_dir}/worker{self.worker_id}_{timestamp}_{self.tests_done}.json"

        # Stats
        is_profitable = (result['results']['total_pnl_pct'] > 0 and
                        result['results']['profit_factor'] > 1.0)

        if is_profitable:
            # SAUVEGARDER seulement les profitables
            with open(filename, 'w') as f:
                json.dump(result, f, indent=2)

            self.profitable_found += 1
            pnl = result['results']['total_pnl_pct']
            pf = result['results']['profit_factor']
            lev = result['params']['leverage']
            profit_usd = result['results']['final_capital'] - 500.0

            # LOG DÉTAILLÉ
            print(f"[Worker {self.worker_id}] ✅ PROFITABLE #{self.profitable_found}")
            print(f"   💰 PnL: {pnl:+.2f}% (${profit_usd:+.2f}) | Capital: ${result['results']['final_capital']:.2f}")
            print(f"   📊 PF: {pf:.3f} | WR: {result['results']['win_rate']:.1f}% | Trades: {result['results']['total_trades']}")
            print(f"   ⚙️  Lev: {lev}x | SL: {result['params']['sl_atr_mult']:.2f}x | TP: {result['params']['tp_atr_mult']:.2f}x | Conf: {result['params']['min_confidence']}%")
            print(f"   🔢 Test #{self.tests_done} | File: {filename}")
            print()
        else:
            # NE PAS sauvegarder les non-profitables
            self.non_profitable_deleted += 1

    def run_continuous(self, max_tests: int = None):
        """Optimisation continue"""
        print(f"[Worker {self.worker_id}] 🔄 Démarrage boucle d'optimisation continue\n")

        while True:
            # Générer params
            params = self.generate_random_params()

            # S'assurer TP > SL * 1.5
            if params['tp_atr_mult'] < params['sl_atr_mult'] * 1.5:
                params['tp_atr_mult'] = params['sl_atr_mult'] * random.uniform(2.0, 3.5)

            # Tester
            result = self.test_config(params)

            # Sauvegarder
            self.save_result(result)

            self.tests_done += 1

            # Stats périodiques
            if self.tests_done % 50 == 0:
                elapsed = time() - self.start_time
                rate = self.tests_done / elapsed * 60  # tests/min
                success_rate = (self.profitable_found / self.tests_done * 100) if self.tests_done > 0 else 0
                print(f"[Worker {self.worker_id}] 📊 STATS:")
                print(f"   Tests: {self.tests_done} | Profitables: {self.profitable_found} ({success_rate:.1f}%)")
                print(f"   Non-profitables supprimés: {self.non_profitable_deleted}")
                print(f"   Rate: {rate:.1f} tests/min | Temps: {elapsed/60:.1f}min")
                print()

            # Limite optionnelle
            if max_tests and self.tests_done >= max_tests:
                print(f"[Worker {self.worker_id}] ✅ Max tests atteint: {max_tests}")
                break

            # Délai pour réduire CPU (mode économie)
            sleep(0.5)


if __name__ == '__main__':
    # Worker ID depuis args
    worker_id = int(sys.argv[1]) if len(sys.argv) > 1 else 0
    max_tests = int(sys.argv[2]) if len(sys.argv) > 2 else None

    optimizer = MassiveOptimizer(worker_id=worker_id)

    try:
        optimizer.run_continuous(max_tests=max_tests)
    except KeyboardInterrupt:
        print(f"\n[Worker {worker_id}] ⏹️  Arrêt demandé")
        print(f"[Worker {worker_id}] 📊 Total tests: {optimizer.tests_done}")
        print(f"[Worker {worker_id}] ✅ Profitables trouvés: {optimizer.profitable_found}")
