#!/usr/bin/env python3
"""
Bot de monitoring périodique pour analyser les signaux et trades avec Claude
"""

import sqlite3
import json
import logging
import time
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
import requests
import os
from hyperliquid_client import HyperliquidClient

# Configuration logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - [MonitoringBot] - %(message)s',
    handlers=[
        logging.FileHandler('logs/monitoring_bot.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

class TradingMonitor:
    def __init__(self, db_path: str = "crypto_trader.db"):
        self.db_path = db_path
        self.hl_client = HyperliquidClient()

    def get_recent_trades(self, hours: int = 24) -> List[Dict]:
        """Récupère les trades récents de la base de données"""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()

            # Timestamp pour les dernières X heures
            cutoff_time = datetime.now() - timedelta(hours=hours)
            cutoff_timestamp = cutoff_time.timestamp()

            query = """
            SELECT symbol, side, size, price, execution_time, pnl
            FROM executed_trades
            WHERE execution_time IS NOT NULL
            ORDER BY execution_time DESC
            LIMIT 100
            """

            cursor.execute(query)
            trades = []

            for row in cursor.fetchall():
                # execution_time peut être un datetime string
                try:
                    if isinstance(row[4], str):
                        dt = datetime.fromisoformat(row[4].replace('Z', '+00:00'))
                        timestamp = dt.timestamp()
                        datetime_str = dt.strftime('%Y-%m-%d %H:%M:%S')
                    else:
                        timestamp = row[4]
                        datetime_str = datetime.fromtimestamp(row[4]).strftime('%Y-%m-%d %H:%M:%S')

                    # Filtrer par période
                    if timestamp >= cutoff_timestamp:
                        trades.append({
                            'symbol': row[0],
                            'side': row[1],
                            'size': row[2],
                            'price': row[3],
                            'timestamp': timestamp,
                            'pnl': row[5],
                            'datetime': datetime_str
                        })
                except Exception as e:
                    logger.warning(f"Erreur parsing date trade: {e}")
                    continue

            conn.close()
            return trades

        except Exception as e:
            logger.error(f"Erreur lors de la récupération des trades: {e}")
            return []

    def get_recent_signals(self, hours: int = 24) -> List[Dict]:
        """Récupère les signaux récents"""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()

            cutoff_time = datetime.now() - timedelta(hours=hours)
            cutoff_timestamp = cutoff_time.timestamp()

            query = """
            SELECT symbol, signal_type, confidence, entry_price, executed_at, is_active, reasoning
            FROM executed_signals
            WHERE executed_at IS NOT NULL
            ORDER BY executed_at DESC
            LIMIT 100
            """

            cursor.execute(query)
            signals = []

            for row in cursor.fetchall():
                try:
                    if isinstance(row[4], str):
                        dt = datetime.fromisoformat(row[4].replace('Z', '+00:00'))
                        timestamp = dt.timestamp()
                        datetime_str = dt.strftime('%Y-%m-%d %H:%M:%S')
                    else:
                        timestamp = row[4]
                        datetime_str = datetime.fromtimestamp(row[4]).strftime('%Y-%m-%d %H:%M:%S')

                    # Filtrer par période
                    if timestamp >= cutoff_timestamp:
                        signals.append({
                            'symbol': row[0],
                            'signal_type': row[1],
                            'confidence': row[2] or 0.0,
                            'price': row[3],
                            'timestamp': timestamp,
                            'executed': bool(row[5]),  # is_active
                            'reason': row[6],
                            'datetime': datetime_str
                        })
                except Exception as e:
                    logger.warning(f"Erreur parsing date signal: {e}")
                    continue

            conn.close()
            return signals

        except Exception as e:
            logger.error(f"Erreur lors de la récupération des signaux: {e}")
            return []

    def get_candle_data(self, symbol: str, timeframe: str = "1h", count: int = 24) -> List[Dict]:
        """Récupère les données de chandeliers pour un symbole"""
        try:
            # Utilise le client Hyperliquid pour récupérer les données
            candles = self.hl_client.get_candles_data(symbol, interval=timeframe, lookback_hours=count)
            return candles
        except Exception as e:
            logger.error(f"Erreur lors de la récupération des chandeliers pour {symbol}: {e}")
            return []

    def get_system_performance(self) -> Dict:
        """Analyse les performances du système"""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()

            # Stats des dernières 24h
            cutoff_time = datetime.now() - timedelta(hours=24)
            cutoff_timestamp = cutoff_time.timestamp()

            # Nombre de trades
            cursor.execute("SELECT COUNT(*) FROM executed_trades WHERE execution_time IS NOT NULL")
            trades_count = cursor.fetchone()[0]

            # PnL total
            cursor.execute("SELECT SUM(pnl) FROM executed_trades WHERE pnl IS NOT NULL")
            total_pnl = cursor.fetchone()[0] or 0

            # Nombre de signaux générés vs exécutés
            cursor.execute("SELECT COUNT(*) FROM executed_signals WHERE executed_at IS NOT NULL")
            signals_count = cursor.fetchone()[0]

            cursor.execute("SELECT COUNT(*) FROM executed_signals WHERE executed_at IS NOT NULL AND is_active = 1")
            executed_signals_count = cursor.fetchone()[0]

            # Positions actives (status != 'closed')
            cursor.execute("SELECT COUNT(*) FROM positions WHERE status != 'closed' OR status IS NULL")
            active_positions = cursor.fetchone()[0]

            conn.close()

            return {
                'trades_24h': trades_count,
                'total_pnl_24h': total_pnl,
                'signals_generated_24h': signals_count,
                'signals_executed_24h': executed_signals_count,
                'execution_rate': (executed_signals_count / signals_count * 100) if signals_count > 0 else 0,
                'active_positions': active_positions,
                'timestamp': datetime.now().isoformat()
            }

        except Exception as e:
            logger.error(f"Erreur lors du calcul des performances: {e}")
            return {}

    def prepare_analysis_data(self, hours: int = 24) -> Dict:
        """Prépare toutes les données pour l'analyse Claude"""
        logger.info(f"Préparation des données des dernières {hours}h pour analyse...")

        # Récupération des données
        trades = self.get_recent_trades(hours)
        signals = self.get_recent_signals(hours)
        performance = self.get_system_performance()

        # Récupération des chandeliers pour les symboles actifs
        active_symbols = list(set([trade['symbol'] for trade in trades] + [signal['symbol'] for signal in signals]))
        candle_data = {}

        for symbol in active_symbols:
            candles = self.get_candle_data(symbol, "1h", 48)  # 48h de données
            if candles:
                candle_data[symbol] = candles

        analysis_data = {
            'timestamp': datetime.now().isoformat(),
            'period_hours': hours,
            'trades': trades,
            'signals': signals,
            'candle_data': candle_data,
            'performance': performance,
            'summary': {
                'total_trades': len(trades),
                'total_signals': len(signals),
                'active_symbols': active_symbols,
                'symbols_count': len(active_symbols)
            }
        }

        return analysis_data

    def save_analysis_data(self, data: Dict, filename: str = None) -> str:
        """Sauvegarde les données d'analyse dans un fichier JSON"""
        if filename is None:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"logs/analysis_data_{timestamp}.json"

        try:
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=2, ensure_ascii=False)

            logger.info(f"Données d'analyse sauvegardées: {filename}")
            return filename

        except Exception as e:
            logger.error(f"Erreur lors de la sauvegarde: {e}")
            return None

    def call_claude_analysis(self, data: Dict) -> Optional[str]:
        """Appelle l'API Claude pour analyser les données"""
        try:
            from claude_analyzer import ClaudeAnalyzer

            analyzer = ClaudeAnalyzer()
            analysis = analyzer.analyze_trading_data(data)

            if analysis:
                logger.info("Analyse Claude terminée avec succès")
                return analysis
            else:
                logger.warning("Échec de l'analyse Claude")
                return None

        except ImportError:
            logger.error("Module claude_analyzer non trouvé")
            return None
        except Exception as e:
            logger.error(f"Erreur lors de l'analyse Claude: {e}")
            return None

    def run_monitoring_cycle(self, hours: int = 24):
        """Exécute un cycle complet de monitoring"""
        logger.info("=== DÉBUT CYCLE MONITORING ===")

        try:
            # Préparation des données
            data = self.prepare_analysis_data(hours)

            # Sauvegarde
            filename = self.save_analysis_data(data)

            # Analyse (placeholder pour Claude)
            analysis = self.call_claude_analysis(data)

            if analysis:
                logger.info("Analyse générée:")
                print(analysis)

            logger.info(f"Cycle terminé - {len(data['trades'])} trades, {len(data['signals'])} signaux analysés")

        except Exception as e:
            logger.error(f"Erreur dans le cycle de monitoring: {e}")

        logger.info("=== FIN CYCLE MONITORING ===")

def main():
    """Point d'entrée principal"""
    import argparse

    parser = argparse.ArgumentParser(description='Bot de monitoring trading')
    parser.add_argument('--hours', type=int, default=24, help='Nombre d\'heures à analyser (défaut: 24)')
    parser.add_argument('--daemon', action='store_true', help='Mode démon (exécution continue)')
    parser.add_argument('--interval', type=int, default=3600, help='Intervalle en secondes pour le mode démon (défaut: 3600s = 1h)')

    args = parser.parse_args()

    monitor = TradingMonitor()

    if args.daemon:
        logger.info(f"Démarrage en mode démon - analyse toutes les {args.interval}s")
        try:
            while True:
                monitor.run_monitoring_cycle(args.hours)
                logger.info(f"Attente {args.interval}s avant le prochain cycle...")
                time.sleep(args.interval)
        except KeyboardInterrupt:
            logger.info("Arrêt du monitoring démon")
    else:
        # Exécution unique
        monitor.run_monitoring_cycle(args.hours)

if __name__ == "__main__":
    main()