"""
Notifications de transition de mode et alertes système
pour informer l'utilisateur des changements d'état et problèmes détectés
"""

from PyQt5.QtWidgets import (
    QWidget, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QDialog
)
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QPropertyAnimation, QEasingCurve, QPoint
from PyQt5.QtGui import QFont, QPainter, QColor
from typing import Optional, Dict, Any, Callable
import logging


class TransitionNotification(QWidget):
    """
    Notification pour les transitions de mode et alertes système
    Supporte différents types: transition autopilot, baisse confiance,
    violation liste blanche, changement UI
    """
    
    # Types de notification
    TYPE_AUTOPILOT_PROPOSAL = "autopilot_proposal"
    TYPE_CONFIDENCE_DROP = "confidence_drop"
    TYPE_WHITELIST_VIOLATION = "whitelist_violation"
    TYPE_UI_CHANGE = "ui_change"
    TYPE_MODE_TRANSITION = "mode_transition"
    
    # Signaux
    action_taken = pyqtSignal(str)  # "accept", "reject", "dismiss"
    
    def __init__(self,
                 notification_type: str,
                 data: Dict[str, Any],
                 requires_action: bool = False,
                 timeout_ms: int = 10000,
                 parent=None):
        """
        Initialiser la notification de transition
        
        Args:
            notification_type: Type de notification (voir constantes TYPE_*)
            data: Données spécifiques au type de notification
            requires_action: Nécessite une action utilisateur (défaut: False)
            timeout_ms: Timeout en millisecondes (défaut: 10000)
            parent: Widget parent (optionnel)
        """
        super().__init__(parent)
        self.notification_type = notification_type
        self.data = data
        self.requires_action = requires_action
        self.timeout_ms = timeout_ms
        self.logger = logging.getLogger(__name__)
        
        self.is_closed = False
        
        self.init_ui()
        self.setup_animation()
        if not requires_action:
            self.setup_timer()
        
        self.logger.info(f"TransitionNotification créée: {notification_type}")
    
    def init_ui(self):
        """Initialiser l'interface de la notification"""
        # Fenêtre sans bordure, toujours au-dessus
        self.setWindowFlags(
            Qt.WindowStaysOnTopHint |
            Qt.FramelessWindowHint |
            Qt.Tool
        )
        self.setAttribute(Qt.WA_TranslucentBackground)
        
        # Taille variable selon le type
        if self.requires_action:
            self.setFixedSize(400, 180)
        else:
            self.setFixedSize(380, 140)
        
        # Positionner en haut à droite de l'écran
        from PyQt5.QtWidgets import QApplication
        screen = QApplication.primaryScreen().geometry()
        x = screen.width() - self.width() - 20
        y = 20
        self.move(x, y)
        
        # Widget conteneur avec fond
        self.container = QWidget(self)
        self.container.setGeometry(0, 0, self.width(), self.height())
        
        # Déterminer le style selon le type
        style_config = self._get_style_config()
        
        self.container.setStyleSheet(f"""
            QWidget {{
                background-color: {style_config['bg_color']};
                border-radius: 10px;
                border: 2px solid {style_config['border_color']};
            }}
        """)
        
        # Layout principal
        main_layout = QVBoxLayout()
        self.container.setLayout(main_layout)
        main_layout.setContentsMargins(15, 12, 15, 12)
        main_layout.setSpacing(10)
        
        # En-tête avec icône et titre
        header_layout = QHBoxLayout()
        
        icon_label = QLabel(style_config['icon'])
        icon_label.setFont(QFont("Arial", 18))
        header_layout.addWidget(icon_label)
        
        title_label = QLabel(style_config['title'])
        title_label.setFont(QFont("Arial", 12, QFont.Bold))
        title_label.setStyleSheet(f"color: {style_config['text_color']};")
        header_layout.addWidget(title_label)
        
        header_layout.addStretch()
        
        # Bouton de fermeture (si pas d'action requise)
        if not self.requires_action:
            close_button = QPushButton("×")
            close_button.setFont(QFont("Arial", 16, QFont.Bold))
            close_button.setFixedSize(25, 25)
            close_button.setStyleSheet(f"""
                QPushButton {{
                    background-color: transparent;
                    color: {style_config['text_color']};
                    border: none;
                }}
                QPushButton:hover {{
                    background-color: rgba(0, 0, 0, 30);
                    border-radius: 12px;
                }}
            """)
            close_button.clicked.connect(self.close_notification)
            header_layout.addWidget(close_button)
        
        main_layout.addLayout(header_layout)
        
        # Message principal
        message = self._get_message()
        message_label = QLabel(message)
        message_label.setFont(QFont("Arial", 10))
        message_label.setStyleSheet(f"color: {style_config['text_color']};")
        message_label.setWordWrap(True)
        main_layout.addWidget(message_label)
        
        # Détails additionnels
        details = self._get_details()
        if details:
            details_label = QLabel(details)
            details_label.setFont(QFont("Arial", 9))
            details_label.setStyleSheet(f"color: {style_config['details_color']};")
            details_label.setWordWrap(True)
            main_layout.addWidget(details_label)
        
        # Boutons d'action (si requis)
        if self.requires_action:
            button_layout = QHBoxLayout()
            button_layout.setSpacing(10)
            
            accept_button = QPushButton(style_config['accept_text'])
            accept_button.setFont(QFont("Arial", 10))
            accept_button.setStyleSheet("""
                QPushButton {
                    background-color: #4CAF50;
                    color: white;
                    border: none;
                    padding: 8px 15px;
                    border-radius: 5px;
                }
                QPushButton:hover {
                    background-color: #45a049;
                }
            """)
            accept_button.clicked.connect(lambda: self.on_action("accept"))
            button_layout.addWidget(accept_button)
            
            reject_button = QPushButton(style_config['reject_text'])
            reject_button.setFont(QFont("Arial", 10))
            reject_button.setStyleSheet("""
                QPushButton {
                    background-color: #f44336;
                    color: white;
                    border: none;
                    padding: 8px 15px;
                    border-radius: 5px;
                }
                QPushButton:hover {
                    background-color: #da190b;
                }
            """)
            reject_button.clicked.connect(lambda: self.on_action("reject"))
            button_layout.addWidget(reject_button)
            
            main_layout.addLayout(button_layout)
    
    def _get_style_config(self) -> Dict[str, str]:
        """Obtenir la configuration de style selon le type"""
        configs = {
            self.TYPE_AUTOPILOT_PROPOSAL: {
                'bg_color': '#E8F5E9',
                'border_color': '#4CAF50',
                'text_color': '#2E7D32',
                'details_color': '#558B2F',
                'icon': '🤖',
                'title': 'Passage en Autopilot Proposé',
                'accept_text': '✓ Activer Autopilot',
                'reject_text': '✗ Rester en Assisté'
            },
            self.TYPE_CONFIDENCE_DROP: {
                'bg_color': '#FFF3E0',
                'border_color': '#FF9800',
                'text_color': '#E65100',
                'details_color': '#F57C00',
                'icon': '⚠️',
                'title': 'Baisse de Confiance Détectée',
                'accept_text': '✓ Continuer',
                'reject_text': '✗ Arrêter'
            },
            self.TYPE_WHITELIST_VIOLATION: {
                'bg_color': '#FFEBEE',
                'border_color': '#f44336',
                'text_color': '#C62828',
                'details_color': '#D32F2F',
                'icon': '🚫',
                'title': 'Violation de Liste Blanche',
                'accept_text': '✓ Ajouter à la Liste',
                'reject_text': '✗ Bloquer'
            },
            self.TYPE_UI_CHANGE: {
                'bg_color': '#E3F2FD',
                'border_color': '#2196F3',
                'text_color': '#1565C0',
                'details_color': '#1976D2',
                'icon': '🔄',
                'title': 'Changement d\'Interface Détecté',
                'accept_text': '✓ Ré-observer',
                'reject_text': '✗ Ignorer'
            },
            self.TYPE_MODE_TRANSITION: {
                'bg_color': '#F3E5F5',
                'border_color': '#9C27B0',
                'text_color': '#6A1B9A',
                'details_color': '#7B1FA2',
                'icon': '🔀',
                'title': 'Transition de Mode',
                'accept_text': '✓ OK',
                'reject_text': '✗ Annuler'
            }
        }
        
        return configs.get(self.notification_type, configs[self.TYPE_MODE_TRANSITION])
    
    def _get_message(self) -> str:
        """Obtenir le message principal selon le type"""
        if self.notification_type == self.TYPE_AUTOPILOT_PROPOSAL:
            task_name = self.data.get('task_name', 'Tâche')
            observations = self.data.get('observation_count', 0)
            concordance = self.data.get('concordance_rate', 0.0)
            return (f"La tâche '{task_name}' a atteint les critères pour le mode Autopilot:\n"
                   f"• {observations} observations\n"
                   f"• {concordance * 100:.1f}% de concordance")
        
        elif self.notification_type == self.TYPE_CONFIDENCE_DROP:
            task_name = self.data.get('task_name', 'Tâche')
            confidence = self.data.get('confidence_score', 0.0)
            threshold = self.data.get('threshold', 0.90)
            return (f"La confiance pour '{task_name}' est tombée à {confidence * 100:.1f}% "
                   f"(seuil: {threshold * 100:.0f}%). Retour au mode Assisté recommandé.")
        
        elif self.notification_type == self.TYPE_WHITELIST_VIOLATION:
            window = self.data.get('window_title', 'Fenêtre inconnue')
            action = self.data.get('action_type', 'action')
            return (f"Tentative d'{action} dans une fenêtre non autorisée:\n"
                   f"'{window}'\n"
                   f"Cette action a été bloquée pour des raisons de sécurité.")
        
        elif self.notification_type == self.TYPE_UI_CHANGE:
            task_name = self.data.get('task_name', 'Tâche')
            similarity = self.data.get('similarity', 0.0)
            return (f"Changement d'interface détecté pour '{task_name}'.\n"
                   f"Similarité visuelle: {similarity * 100:.1f}% (seuil: 70%)\n"
                   f"Une ré-observation est recommandée.")
        
        elif self.notification_type == self.TYPE_MODE_TRANSITION:
            from_mode = self.data.get('from_mode', 'inconnu')
            to_mode = self.data.get('to_mode', 'inconnu')
            task_name = self.data.get('task_name', 'Tâche')
            mode_names = {
                'shadow': 'Shadow 👀',
                'assist': 'Assisté 🤝',
                'auto': 'Autopilot 🤖'
            }
            return (f"Transition de mode pour '{task_name}':\n"
                   f"{mode_names.get(from_mode, from_mode)} → "
                   f"{mode_names.get(to_mode, to_mode)}")
        
        return "Notification système"
    
    def _get_details(self) -> Optional[str]:
        """Obtenir les détails additionnels selon le type"""
        if self.notification_type == self.TYPE_CONFIDENCE_DROP:
            reason = self.data.get('reason', '')
            if reason:
                return f"Raison: {reason}"
        
        elif self.notification_type == self.TYPE_MODE_TRANSITION:
            reason = self.data.get('reason', '')
            if reason:
                reasons_fr = {
                    'low_confidence': 'Confiance insuffisante',
                    'high_concordance': 'Concordance élevée atteinte',
                    'user_request': 'Demande utilisateur',
                    'ui_change': 'Changement d\'interface',
                    'error': 'Erreur détectée'
                }
                return f"Raison: {reasons_fr.get(reason, reason)}"
        
        return None
    
    def setup_animation(self):
        """Configurer l'animation d'entrée"""
        from PyQt5.QtWidgets import QApplication
        screen = QApplication.primaryScreen().geometry()
        
        start_x = screen.width()
        end_x = screen.width() - self.width() - 20
        
        self.animation = QPropertyAnimation(self, b"pos")
        self.animation.setDuration(400)
        self.animation.setStartValue(QPoint(start_x, 20))
        self.animation.setEndValue(QPoint(end_x, 20))
        self.animation.setEasingCurve(QEasingCurve.OutCubic)
    
    def setup_timer(self):
        """Configurer le timer de fermeture automatique"""
        self.close_timer = QTimer(self)
        self.close_timer.timeout.connect(self.close_notification)
        self.close_timer.setSingleShot(True)
    
    def show_notification(self):
        """Afficher la notification avec animation"""
        self.show()
        self.animation.start()
        
        if not self.requires_action:
            self.close_timer.start(self.timeout_ms)
        
        self.logger.info(f"Notification affichée: {self.notification_type}")
    
    def close_notification(self):
        """Fermer la notification"""
        if self.is_closed:
            return
        
        self.is_closed = True
        if hasattr(self, 'close_timer'):
            self.close_timer.stop()
        
        self.action_taken.emit("dismiss")
        self.logger.info("Notification fermée")
        self.close()
    
    def on_action(self, action: str):
        """
        Gestionnaire d'action utilisateur
        
        Args:
            action: Type d'action ("accept" ou "reject")
        """
        self.is_closed = True
        self.action_taken.emit(action)
        self.logger.info(f"Action prise: {action}")
        self.close()
    
    @staticmethod
    def show_autopilot_proposal(task_name: str,
                                observation_count: int,
                                concordance_rate: float,
                                parent=None) -> 'TransitionNotification':
        """
        Afficher une proposition de passage en Autopilot
        
        Args:
            task_name: Nom de la tâche
            observation_count: Nombre d'observations
            concordance_rate: Taux de concordance
            parent: Widget parent
            
        Returns:
            Instance de TransitionNotification
        """
        data = {
            'task_name': task_name,
            'observation_count': observation_count,
            'concordance_rate': concordance_rate
        }
        
        notification = TransitionNotification(
            TransitionNotification.TYPE_AUTOPILOT_PROPOSAL,
            data,
            requires_action=True,
            parent=parent
        )
        notification.show_notification()
        return notification
    
    @staticmethod
    def show_confidence_drop(task_name: str,
                            confidence_score: float,
                            threshold: float = 0.90,
                            reason: str = "",
                            parent=None) -> 'TransitionNotification':
        """
        Afficher une alerte de baisse de confiance
        
        Args:
            task_name: Nom de la tâche
            confidence_score: Score de confiance actuel
            threshold: Seuil de confiance
            reason: Raison de la baisse (optionnel)
            parent: Widget parent
            
        Returns:
            Instance de TransitionNotification
        """
        data = {
            'task_name': task_name,
            'confidence_score': confidence_score,
            'threshold': threshold,
            'reason': reason
        }
        
        notification = TransitionNotification(
            TransitionNotification.TYPE_CONFIDENCE_DROP,
            data,
            requires_action=False,
            timeout_ms=8000,
            parent=parent
        )
        notification.show_notification()
        return notification
    
    @staticmethod
    def show_whitelist_violation(window_title: str,
                                 action_type: str,
                                 parent=None) -> 'TransitionNotification':
        """
        Afficher une alerte de violation de liste blanche
        
        Args:
            window_title: Titre de la fenêtre
            action_type: Type d'action tentée
            parent: Widget parent
            
        Returns:
            Instance de TransitionNotification
        """
        data = {
            'window_title': window_title,
            'action_type': action_type
        }
        
        notification = TransitionNotification(
            TransitionNotification.TYPE_WHITELIST_VIOLATION,
            data,
            requires_action=True,
            parent=parent
        )
        notification.show_notification()
        return notification
    
    @staticmethod
    def show_ui_change(task_name: str,
                      similarity: float,
                      parent=None) -> 'TransitionNotification':
        """
        Afficher une alerte de changement d'interface
        
        Args:
            task_name: Nom de la tâche
            similarity: Score de similarité visuelle
            parent: Widget parent
            
        Returns:
            Instance de TransitionNotification
        """
        data = {
            'task_name': task_name,
            'similarity': similarity
        }
        
        notification = TransitionNotification(
            TransitionNotification.TYPE_UI_CHANGE,
            data,
            requires_action=True,
            parent=parent
        )
        notification.show_notification()
        return notification
    
    @staticmethod
    def show_mode_transition(task_name: str,
                            from_mode: str,
                            to_mode: str,
                            reason: str = "",
                            parent=None) -> 'TransitionNotification':
        """
        Afficher une notification de transition de mode
        
        Args:
            task_name: Nom de la tâche
            from_mode: Mode d'origine
            to_mode: Mode de destination
            reason: Raison de la transition
            parent: Widget parent
            
        Returns:
            Instance de TransitionNotification
        """
        data = {
            'task_name': task_name,
            'from_mode': from_mode,
            'to_mode': to_mode,
            'reason': reason
        }
        
        notification = TransitionNotification(
            TransitionNotification.TYPE_MODE_TRANSITION,
            data,
            requires_action=False,
            timeout_ms=6000,
            parent=parent
        )
        notification.show_notification()
        return notification


if __name__ == "__main__":
    """Test des notifications de transition"""
    from PyQt5.QtWidgets import QApplication
    import sys
    
    app = QApplication(sys.argv)
    
    def test_autopilot_proposal():
        """Test proposition autopilot"""
        notification = TransitionNotification.show_autopilot_proposal(
            task_name="Ouvrir Facture",
            observation_count=25,
            concordance_rate=0.97
        )
        notification.action_taken.connect(
            lambda action: print(f"Autopilot proposal: {action}")
        )
    
    def test_confidence_drop():
        """Test baisse de confiance"""
        notification = TransitionNotification.show_confidence_drop(
            task_name="Saisie Données",
            confidence_score=0.85,
            threshold=0.90,
            reason="Changements UI détectés"
        )
        notification.action_taken.connect(
            lambda action: print(f"Confidence drop: {action}")
        )
    
    def test_whitelist_violation():
        """Test violation liste blanche"""
        notification = TransitionNotification.show_whitelist_violation(
            window_title="Application Non Autorisée",
            action_type="click"
        )
        notification.action_taken.connect(
            lambda action: print(f"Whitelist violation: {action}")
        )
    
    def test_ui_change():
        """Test changement UI"""
        notification = TransitionNotification.show_ui_change(
            task_name="Navigation Menu",
            similarity=0.65
        )
        notification.action_taken.connect(
            lambda action: print(f"UI change: {action}")
        )
    
    def test_mode_transition():
        """Test transition de mode"""
        notification = TransitionNotification.show_mode_transition(
            task_name="Export Données",
            from_mode="auto",
            to_mode="assist",
            reason="low_confidence"
        )
        notification.action_taken.connect(
            lambda action: print(f"Mode transition: {action}")
        )
    
    # Tester séquentiellement
    test_autopilot_proposal()
    QTimer.singleShot(2000, test_confidence_drop)
    QTimer.singleShot(4000, test_whitelist_violation)
    QTimer.singleShot(6000, test_ui_change)
    QTimer.singleShot(8000, test_mode_transition)
    
    sys.exit(app.exec_())
