"""
Notifications post-action pour afficher le succès/échec des actions
avec possibilité de retour correctif
"""

from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QPushButton
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 PostActionNotification(QWidget):
    """
    Notification post-action affichant le résultat d'une action automatisée
    avec indicateur de succès (✔️) ou d'échec (❌) et possibilité de correction
    """
    
    # Signaux
    correction_requested = pyqtSignal(dict)  # Émis quand l'utilisateur demande une correction
    feedback_provided = pyqtSignal(str)  # Émis quand un retour est fourni ("success", "failed", "corrected")
    
    def __init__(self, 
                 action_result: Dict[str, Any],
                 allow_correction: bool = True,
                 timeout_ms: int = 5000,
                 parent=None):
        """
        Initialiser la notification post-action
        
        Args:
            action_result: Résultat de l'action
                {
                    "action_type": str,
                    "target_element": str,
                    "result": str ("success" ou "failed"),
                    "confidence": float,
                    "error_message": str (optionnel, si échec)
                }
            allow_correction: Permettre le retour correctif (défaut: True)
            timeout_ms: Timeout en millisecondes avant fermeture auto (défaut: 5000)
            parent: Widget parent (optionnel)
        """
        super().__init__(parent)
        self.action_result = action_result
        self.allow_correction = allow_correction
        self.timeout_ms = timeout_ms
        self.logger = logging.getLogger(__name__)
        
        self.correction_callback = None
        self.is_closed = False
        
        self.init_ui()
        self.setup_animation()
        self.setup_timer()
        
        self.logger.info(
            f"PostActionNotification créée: {action_result.get('action_type')} - "
            f"{action_result.get('result')}"
        )
    
    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 fixe
        self.setFixedSize(350, 120)
        
        # 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 résultat
        result = self.action_result.get("result", "failed")
        if result == "success":
            bg_color = "#4CAF50"
            icon = "✔️"
            title = "Action Réussie"
        else:
            bg_color = "#f44336"
            icon = "❌"
            title = "Action Échouée"
        
        self.container.setStyleSheet(f"""
            QWidget {{
                background-color: {bg_color};
                border-radius: 10px;
            }}
        """)
        
        # Layout principal
        main_layout = QVBoxLayout()
        self.container.setLayout(main_layout)
        main_layout.setContentsMargins(15, 10, 15, 10)
        main_layout.setSpacing(8)
        
        # En-tête avec icône et titre
        header_layout = QHBoxLayout()
        
        icon_label = QLabel(icon)
        icon_label.setFont(QFont("Arial", 20))
        header_layout.addWidget(icon_label)
        
        title_label = QLabel(title)
        title_label.setFont(QFont("Arial", 12, QFont.Bold))
        title_label.setStyleSheet("color: white;")
        header_layout.addWidget(title_label)
        
        header_layout.addStretch()
        
        # Bouton de fermeture
        close_button = QPushButton("×")
        close_button.setFont(QFont("Arial", 16, QFont.Bold))
        close_button.setFixedSize(25, 25)
        close_button.setStyleSheet("""
            QPushButton {
                background-color: transparent;
                color: white;
                border: none;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 50);
                border-radius: 12px;
            }
        """)
        close_button.clicked.connect(self.close_notification)
        header_layout.addWidget(close_button)
        
        main_layout.addLayout(header_layout)
        
        # Détails de l'action
        action_type = self.action_result.get("action_type", "action")
        target = self.action_result.get("target_element", "élément")
        
        details_text = f"{action_type.upper()} sur '{target}'"
        details_label = QLabel(details_text)
        details_label.setFont(QFont("Arial", 10))
        details_label.setStyleSheet("color: white;")
        details_label.setWordWrap(True)
        main_layout.addWidget(details_label)
        
        # Message d'erreur si échec
        if result == "failed":
            error_msg = self.action_result.get("error_message", "Erreur inconnue")
            error_label = QLabel(f"Erreur: {error_msg}")
            error_label.setFont(QFont("Arial", 9))
            error_label.setStyleSheet("color: rgba(255, 255, 255, 200);")
            error_label.setWordWrap(True)
            main_layout.addWidget(error_label)
        
        # Bouton de correction (si autorisé et échec)
        if self.allow_correction and result == "failed":
            correction_button = QPushButton("✎ Corriger")
            correction_button.setFont(QFont("Arial", 9))
            correction_button.setStyleSheet("""
                QPushButton {
                    background-color: rgba(255, 255, 255, 200);
                    color: #f44336;
                    border: none;
                    padding: 5px 10px;
                    border-radius: 5px;
                }
                QPushButton:hover {
                    background-color: white;
                }
            """)
            correction_button.clicked.connect(self.on_correction_requested)
            main_layout.addWidget(correction_button)
        
        # Barre de progression du timeout
        self.progress_bar = QWidget(self.container)
        self.progress_bar.setGeometry(0, self.height() - 3, self.width(), 3)
        self.progress_bar.setStyleSheet(f"""
            QWidget {{
                background-color: rgba(255, 255, 255, 150);
            }}
        """)
    
    def setup_animation(self):
        """Configurer l'animation d'entrée"""
        # Animation de glissement depuis la droite
        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(300)
        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)
        
        # Timer pour l'animation de la barre de progression
        self.progress_timer = QTimer(self)
        self.progress_timer.timeout.connect(self.update_progress)
        self.progress_value = 0
        self.progress_step = 100 / (self.timeout_ms / 50)  # Mise à jour toutes les 50ms
    
    def show_notification(self):
        """Afficher la notification avec animation"""
        self.show()
        self.animation.start()
        
        # Démarrer les timers
        self.close_timer.start(self.timeout_ms)
        self.progress_timer.start(50)
        
        self.logger.info("Notification affichée")
    
    def update_progress(self):
        """Mettre à jour la barre de progression"""
        self.progress_value += self.progress_step
        if self.progress_value >= 100:
            self.progress_value = 100
            self.progress_timer.stop()
        
        # Réduire la largeur de la barre
        remaining_width = int(self.width() * (1 - self.progress_value / 100))
        self.progress_bar.setGeometry(0, self.height() - 3, remaining_width, 3)
    
    def close_notification(self):
        """Fermer la notification"""
        if self.is_closed:
            return
        
        self.is_closed = True
        self.close_timer.stop()
        self.progress_timer.stop()
        
        # Émettre le signal de retour
        result = self.action_result.get("result", "failed")
        self.feedback_provided.emit(result)
        
        self.logger.info("Notification fermée")
        self.close()
    
    def on_correction_requested(self):
        """Gestionnaire de demande de correction"""
        self.close_timer.stop()
        self.progress_timer.stop()
        
        self.correction_requested.emit(self.action_result)
        self.feedback_provided.emit("corrected")
        
        self.logger.info("Correction demandée")
        self.close()
    
    def allow_corrective_feedback(self, callback: Optional[Callable] = None):
        """
        Permettre le retour correctif avec callback optionnel
        
        Args:
            callback: Fonction à appeler quand une correction est demandée
        """
        self.correction_callback = callback
        if callback:
            self.correction_requested.connect(lambda data: callback(data))
    
    def mousePressEvent(self, event):
        """Permettre de fermer en cliquant sur la notification"""
        if event.button() == Qt.LeftButton:
            self.close_notification()
    
    @staticmethod
    def show_success(action_type: str, 
                     target_element: str,
                     confidence: float = 1.0,
                     timeout_ms: int = 5000,
                     parent=None) -> 'PostActionNotification':
        """
        Afficher une notification de succès
        
        Args:
            action_type: Type d'action
            target_element: Élément cible
            confidence: Score de confiance
            timeout_ms: Timeout en millisecondes
            parent: Widget parent
            
        Returns:
            Instance de PostActionNotification
        """
        action_result = {
            "action_type": action_type,
            "target_element": target_element,
            "result": "success",
            "confidence": confidence
        }
        
        notification = PostActionNotification(
            action_result,
            allow_correction=False,
            timeout_ms=timeout_ms,
            parent=parent
        )
        notification.show_notification()
        return notification
    
    @staticmethod
    def show_failure(action_type: str,
                     target_element: str,
                     error_message: str = "Erreur inconnue",
                     confidence: float = 0.0,
                     allow_correction: bool = True,
                     timeout_ms: int = 5000,
                     parent=None) -> 'PostActionNotification':
        """
        Afficher une notification d'échec
        
        Args:
            action_type: Type d'action
            target_element: Élément cible
            error_message: Message d'erreur
            confidence: Score de confiance
            allow_correction: Permettre la correction
            timeout_ms: Timeout en millisecondes
            parent: Widget parent
            
        Returns:
            Instance de PostActionNotification
        """
        action_result = {
            "action_type": action_type,
            "target_element": target_element,
            "result": "failed",
            "confidence": confidence,
            "error_message": error_message
        }
        
        notification = PostActionNotification(
            action_result,
            allow_correction=allow_correction,
            timeout_ms=timeout_ms,
            parent=parent
        )
        notification.show_notification()
        return notification


if __name__ == "__main__":
    """Test des notifications post-action"""
    from PyQt5.QtWidgets import QApplication
    import sys
    
    app = QApplication(sys.argv)
    
    def test_success():
        """Test notification de succès"""
        notification = PostActionNotification.show_success(
            action_type="click",
            target_element="valider_button",
            confidence=0.95
        )
        notification.feedback_provided.connect(
            lambda result: print(f"Retour: {result}")
        )
    
    def test_failure():
        """Test notification d'échec"""
        def on_correction(data):
            print(f"Correction demandée pour: {data}")
        
        notification = PostActionNotification.show_failure(
            action_type="click",
            target_element="annuler_button",
            error_message="Élément non trouvé à l'écran",
            confidence=0.65,
            allow_correction=True
        )
        notification.allow_corrective_feedback(on_correction)
        notification.feedback_provided.connect(
            lambda result: print(f"Retour: {result}")
        )
    
    # Tester les deux types
    test_success()
    
    # Tester l'échec après 2 secondes
    QTimer.singleShot(2000, test_failure)
    
    sys.exit(app.exec_())
