"""
Système de signaux Qt pour communication Orchestrator → GUI
Permet une communication thread-safe entre les composants
"""

from PyQt5.QtCore import QObject, pyqtSignal
from typing import Callable, Dict, Any


class GUISignals(QObject):
    """
    Signaux Qt pour communication entre l'Orchestrator et la GUI.
    
    Ces signaux permettent une communication thread-safe et asynchrone
    entre le backend (Orchestrator) et l'interface utilisateur.
    
    Signals:
        log_message: Émet un message de log (emoji: str, message: str, level: str)
        update_stats: Met à jour les statistiques (stats: dict)
        show_dialog: Affiche un dialogue interactif (title: str, message: str, on_accept: callable, on_reject: callable)
        mode_changed: Notifie un changement de mode (mode: str)
        status_changed: Notifie un changement de statut (is_running: bool)
    """
    
    # Signal pour ajouter un message de log
    # Paramètres: (emoji: str, message: str, level: str)
    log_message = pyqtSignal(str, str, str)
    
    # Signal pour mettre à jour les statistiques
    # Paramètre: (stats: dict) contenant actions_count, patterns_count, etc.
    update_stats = pyqtSignal(dict)
    
    # Signal pour afficher un dialogue interactif
    # Paramètres: (title: str, message: str, on_accept: object, on_reject: object)
    show_dialog = pyqtSignal(str, str, object, object)
    
    # Signal pour notifier un changement de mode
    # Paramètre: (mode: str) - 'shadow', 'assist', 'copilot', 'auto'
    mode_changed = pyqtSignal(str)
    
    # Signal pour notifier un changement de statut
    # Paramètre: (is_running: bool)
    status_changed = pyqtSignal(bool)
    
    def __init__(self):
        """Initialise le système de signaux."""
        super().__init__()
    
    def emit_log(self, emoji: str, message: str, level: str = "info"):
        """
        Émet un signal de log.
        
        Args:
            emoji: Emoji à afficher
            message: Message de log
            level: Niveau du log ('info', 'success', 'warning', 'error')
            
        Examples:
            >>> signals = GUISignals()
            >>> signals.emit_log("👀", "J'observe vos actions", "info")
        """
        self.log_message.emit(emoji, message, level)
    
    def emit_stats_update(self, stats: Dict[str, Any]):
        """
        Émet un signal de mise à jour des statistiques.
        
        Args:
            stats: Dictionnaire contenant les statistiques
                   {
                       'actions_count': int,
                       'patterns_count': int,
                       'workflows_count': int,
                       'finetuning_status': str,
                       'finetuning_progress': int
                   }
                   
        Examples:
            >>> signals = GUISignals()
            >>> signals.emit_stats_update({
            ...     'actions_count': 12,
            ...     'patterns_count': 2,
            ...     'workflows_count': 1
            ... })
        """
        self.update_stats.emit(stats)
    
    def emit_dialog(self, title: str, message: str, 
                   on_accept: Callable, on_reject: Callable):
        """
        Émet un signal pour afficher un dialogue interactif.
        
        Args:
            title: Titre du dialogue
            message: Message du dialogue
            on_accept: Callback appelé si l'utilisateur accepte
            on_reject: Callback appelé si l'utilisateur refuse
            
        Examples:
            >>> signals = GUISignals()
            >>> def accept():
            ...     print("Accepté")
            >>> def reject():
            ...     print("Refusé")
            >>> signals.emit_dialog(
            ...     "Confirmation",
            ...     "Voulez-vous continuer ?",
            ...     accept,
            ...     reject
            ... )
        """
        self.show_dialog.emit(title, message, on_accept, on_reject)
    
    def emit_mode_change(self, mode: str):
        """
        Émet un signal de changement de mode.
        
        Args:
            mode: Nouveau mode ('shadow', 'assist', 'copilot', 'auto')
            
        Examples:
            >>> signals = GUISignals()
            >>> signals.emit_mode_change("assist")
        """
        self.mode_changed.emit(mode)
    
    def emit_status_change(self, is_running: bool):
        """
        Émet un signal de changement de statut.
        
        Args:
            is_running: True si le système est en cours d'exécution
            
        Examples:
            >>> signals = GUISignals()
            >>> signals.emit_status_change(True)
        """
        self.status_changed.emit(is_running)


if __name__ == "__main__":
    """Tests du système de signaux"""
    from PyQt5.QtWidgets import QApplication
    import sys
    
    app = QApplication(sys.argv)
    
    print("Test du système de signaux Qt")
    print("=" * 50)
    
    # Créer une instance de signaux
    signals = GUISignals()
    
    # Compteurs pour vérifier les émissions
    log_count = 0
    stats_count = 0
    dialog_count = 0
    mode_count = 0
    status_count = 0
    
    # Connecter des slots de test
    def on_log(emoji, message, level):
        global log_count
        log_count += 1
        print(f"\n✓ Log reçu: {emoji} {message} [{level}]")
    
    def on_stats(stats):
        global stats_count
        stats_count += 1
        print(f"\n✓ Stats reçues: {stats}")
    
    def on_dialog(title, message, on_accept, on_reject):
        global dialog_count
        dialog_count += 1
        print(f"\n✓ Dialogue reçu: {title} - {message}")
    
    def on_mode(mode):
        global mode_count
        mode_count += 1
        print(f"\n✓ Mode changé: {mode}")
    
    def on_status(is_running):
        global status_count
        status_count += 1
        print(f"\n✓ Statut changé: {'En cours' if is_running else 'Arrêté'}")
    
    # Connecter les signaux
    signals.log_message.connect(on_log)
    signals.update_stats.connect(on_stats)
    signals.show_dialog.connect(on_dialog)
    signals.mode_changed.connect(on_mode)
    signals.status_changed.connect(on_status)
    
    print("\n1. Test émission de log:")
    signals.emit_log("👀", "Test message", "info")
    
    print("\n2. Test émission de stats:")
    signals.emit_stats_update({
        'actions_count': 12,
        'patterns_count': 2,
        'workflows_count': 1
    })
    
    print("\n3. Test émission de dialogue:")
    signals.emit_dialog(
        "Test",
        "Message de test",
        lambda: print("Accepté"),
        lambda: print("Refusé")
    )
    
    print("\n4. Test émission de changement de mode:")
    signals.emit_mode_change("assist")
    
    print("\n5. Test émission de changement de statut:")
    signals.emit_status_change(True)
    
    # Traiter les événements Qt
    app.processEvents()
    
    # Vérifier les compteurs
    print("\n" + "=" * 50)
    print("Résultats:")
    print(f"  Logs émis: {log_count}")
    print(f"  Stats émises: {stats_count}")
    print(f"  Dialogues émis: {dialog_count}")
    print(f"  Modes émis: {mode_count}")
    print(f"  Statuts émis: {status_count}")
    
    if all([log_count == 1, stats_count == 1, dialog_count == 1, 
            mode_count == 1, status_count == 1]):
        print("\n✅ Tous les tests passent!")
    else:
        print("\n❌ Certains tests ont échoué")
