"""
SILENT MONITOR - Surveillance silencieuse des services
Vérifie en continu que tous les composants sont actifs
Redémarre automatiquement les composants défaillants
"""

import os
import sys
import time
import subprocess
import psutil
from datetime import datetime
import json

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
VENV_PYTHON = os.path.join(SCRIPT_DIR, '.venv', 'Scripts', 'python.exe')
MONITOR_LOG = os.path.join(SCRIPT_DIR, 'silent_monitor.log')
STATUS_FILE = os.path.join(SCRIPT_DIR, 'monitor_status.json')

# Intervalle de vérification (60 secondes)
CHECK_INTERVAL = 60

def log_message(message, level="INFO"):
    """Enregistre un message dans le log silencieux"""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_entry = f"[{timestamp}] [{level}] {message}\n"
    
    try:
        with open(MONITOR_LOG, 'a', encoding='utf-8') as f:
            f.write(log_entry)
    except:
        pass

def update_status(status_data):
    """Met à jour le fichier de statut JSON"""
    try:
        status_data['last_check'] = datetime.now().isoformat()
        with open(STATUS_FILE, 'w', encoding='utf-8') as f:
            json.dump(status_data, f, indent=2)
    except:
        pass

def is_process_running(script_name):
    """Vérifie si un processus Python exécutant un script spécifique est actif"""
    try:
        for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
            try:
                if proc.info['name'] and 'python' in proc.info['name'].lower():
                    cmdline = proc.info['cmdline']
                    if cmdline and any(script_name in arg for arg in cmdline):
                        return proc.info['pid']
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                continue
    except:
        pass
    return None

def start_component(script_name, component_name):
    """Démarre un composant défaillant"""
    log_message(f"Redémarrage de {component_name}...", "WARNING")
    
    try:
        script_path = os.path.join(SCRIPT_DIR, script_name)
        
        # Démarrer le processus en arrière-plan
        CREATE_NO_WINDOW = 0x08000000
        DETACHED_PROCESS = 0x00000008
        
        subprocess.Popen(
            [VENV_PYTHON, script_path],
            cwd=SCRIPT_DIR,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            creationflags=CREATE_NO_WINDOW | DETACHED_PROCESS
        )
        
        # Attendre 3 secondes et vérifier
        time.sleep(3)
        pid = is_process_running(script_name)
        
        if pid:
            log_message(f"{component_name} redémarré avec succès (PID: {pid})", "SUCCESS")
            return True
        else:
            log_message(f"Échec redémarrage {component_name}", "ERROR")
            return False
    except Exception as e:
        log_message(f"Erreur redémarrage {component_name}: {e}", "ERROR")
        return False

def check_services():
    """Vérifie tous les services et les redémarre si nécessaire"""
    status = {
        'dashboard': False,
        'trading_bot': False,
        'watchdog': False,
        'auto_updater': False,
        'all_ok': True,
        'restart_count': 0
    }
    
    # 1. Dashboard API
    pid = is_process_running('dashboard_api_server.py')
    if pid:
        status['dashboard'] = True
        status['dashboard_pid'] = pid
    else:
        log_message("Dashboard API inactif détecté", "WARNING")
        if start_component('dashboard_api_server.py', 'Dashboard API'):
            status['dashboard'] = True
            status['restart_count'] += 1
        else:
            status['all_ok'] = False
    
    # 2. Trading Bot
    pid = is_process_running('trading_bot.py')
    if pid:
        status['trading_bot'] = True
        status['trading_bot_pid'] = pid
    else:
        log_message("Trading Bot inactif détecté", "WARNING")
        if start_component('trading_bot.py', 'Trading Bot'):
            status['trading_bot'] = True
            status['restart_count'] += 1
        else:
            status['all_ok'] = False
    
    # 3. Watchdog (CRITIQUE!)
    pid = is_process_running('bot_watchdog.py')
    if pid:
        status['watchdog'] = True
        status['watchdog_pid'] = pid
    else:
        log_message("⚠️ WATCHDOG INACTIF DÉTECTÉ - Redémarrage prioritaire!", "CRITICAL")
        if start_component('bot_watchdog.py', 'Watchdog'):
            status['watchdog'] = True
            status['restart_count'] += 1
        else:
            status['all_ok'] = False
    
    # 4. Auto Updater (non critique)
    pid = is_process_running('auto_updater_service.py')
    if pid:
        status['auto_updater'] = True
        status['auto_updater_pid'] = pid
    
    return status

def main():
    """Boucle principale de surveillance silencieuse"""
    log_message("=== Silent Monitor démarré ===", "INFO")
    log_message(f"Intervalle de vérification: {CHECK_INTERVAL}s", "INFO")
    
    consecutive_failures = 0
    total_restarts = 0
    
    try:
        while True:
            # Vérifier tous les services
            status = check_services()
            
            # Mettre à jour le fichier de statut
            status['consecutive_failures'] = consecutive_failures
            status['total_restarts'] = total_restarts
            update_status(status)
            
            # Gérer les échecs consécutifs
            if status['all_ok']:
                consecutive_failures = 0
                if status['restart_count'] > 0:
                    log_message(f"{status['restart_count']} service(s) redémarré(s) avec succès", "SUCCESS")
                    total_restarts += status['restart_count']
            else:
                consecutive_failures += 1
                log_message(f"Échec vérification (consécutifs: {consecutive_failures})", "ERROR")
                
                # Si trop d'échecs consécutifs, attendre plus longtemps
                if consecutive_failures >= 3:
                    log_message("Trop d'échecs consécutifs - attente prolongée", "WARNING")
                    time.sleep(CHECK_INTERVAL * 2)
                    consecutive_failures = 0
                    continue
            
            # Attendre avant la prochaine vérification
            time.sleep(CHECK_INTERVAL)
            
    except KeyboardInterrupt:
        log_message("=== Silent Monitor arrêté (Ctrl+C) ===", "INFO")
    except Exception as e:
        log_message(f"Erreur fatale: {e}", "ERROR")
        raise

if __name__ == '__main__':
    main()
