"""
InteractiveDialog - Dialogue interactif avec timeout automatique
Permet de demander confirmation à l'utilisateur de manière non-bloquante
"""

from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton
from PyQt5.QtCore import Qt, QTimer, pyqtSignal
from PyQt5.QtGui import QFont
from typing import Callable, Optional
import logging


class InteractiveDialog(QDialog):
    """
    Dialogue interactif avec timeout automatique.
    
    Caractéristiques:
    - Non-bloquant (l'application continue)
    - Timeout de 10 secondes par défaut
    - Callbacks pour accept/reject
    - Fermeture automatique après timeout
    - Compte à rebours visible
    
    Signals:
        accepted: Émis quand l'utilisateur accepte
        rejected: Émis quand l'utilisateur refuse
        timeout: Émis quand le timeout est atteint
    """
    
    accepted = pyqtSignal()
    rejected = pyqtSignal()
    timeout = pyqtSignal()
    
    def __init__(
        self,
        title: str,
        message: str,
        on_accept: Optional[Callable] = None,
        on_reject: Optional[Callable] = None,
        timeout_seconds: int = 10,
        parent=None
    ):
        """
        Initialise le dialogue interactif.
        
        Args:
            title: Titre du dialogue
            message: Message à afficher
            on_accept: Callback appelé si l'utilisateur accepte
            on_reject: Callback appelé si l'utilisateur refuse
            timeout_seconds: Durée du timeout en secondes (défaut: 10)
            parent: Widget parent (optionnel)
        """
        super().__init__(parent)
        
        self.logger = logging.getLogger(__name__)
        self.on_accept_callback = on_accept
        self.on_reject_callback = on_reject
        self.timeout_seconds = timeout_seconds
        self.remaining_seconds = timeout_seconds
        self.result_value = None
        
        # Configuration du dialogue
        self.setWindowTitle(title)
        self.setModal(False)  # Non-bloquant
        self.setWindowFlags(
            Qt.Dialog | 
            Qt.WindowStaysOnTopHint |
            Qt.WindowCloseButtonHint
        )
        
        # Initialiser l'interface
        self._init_ui(title, message)
        
        # Démarrer le timer de timeout
        self._start_timeout_timer()
        
        self.logger.info(f"InteractiveDialog créé: {title}")
    
    def _init_ui(self, title: str, message: str):
        """Initialise l'interface utilisateur."""
        # Layout principal
        layout = QVBoxLayout()
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(15)
        self.setLayout(layout)
        
        # Icône et titre
        title_layout = QHBoxLayout()
        title_icon = QLabel("💡")
        title_icon.setFont(QFont("Arial", 24))
        title_layout.addWidget(title_icon)
        
        title_label = QLabel(title)
        title_label.setFont(QFont("Arial", 14, QFont.Bold))
        title_label.setWordWrap(True)
        title_layout.addWidget(title_label, 1)
        
        layout.addLayout(title_layout)
        
        # Message
        message_label = QLabel(message)
        message_label.setFont(QFont("Arial", 11))
        message_label.setWordWrap(True)
        message_label.setStyleSheet("color: #333; padding: 10px 0;")
        layout.addWidget(message_label)
        
        # Compte à rebours
        self.countdown_label = QLabel(f"⏱️ Fermeture auto dans {self.remaining_seconds}s")
        self.countdown_label.setFont(QFont("Arial", 9))
        self.countdown_label.setStyleSheet("color: #999;")
        self.countdown_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.countdown_label)
        
        # Boutons
        button_layout = QHBoxLayout()
        button_layout.setSpacing(10)
        
        # Bouton Refuser
        self.reject_button = QPushButton("Non, continue")
        self.reject_button.setFont(QFont("Arial", 10))
        self.reject_button.setStyleSheet("""
            QPushButton {
                background-color: #f44336;
                color: white;
                border: none;
                padding: 10px 20px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #da190b;
            }
        """)
        self.reject_button.clicked.connect(self._on_reject)
        button_layout.addWidget(self.reject_button)
        
        # Bouton Accepter
        self.accept_button = QPushButton("Oui, essaie !")
        self.accept_button.setFont(QFont("Arial", 10))
        self.accept_button.setStyleSheet("""
            QPushButton {
                background-color: #4CAF50;
                color: white;
                border: none;
                padding: 10px 20px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
        """)
        self.accept_button.clicked.connect(self._on_accept)
        button_layout.addWidget(self.accept_button)
        
        layout.addLayout(button_layout)
        
        # Ajuster la taille
        self.setMinimumWidth(400)
        self.adjustSize()
    
    def _start_timeout_timer(self):
        """Démarre le timer de timeout."""
        self.timeout_timer = QTimer(self)
        self.timeout_timer.timeout.connect(self._on_timeout_tick)
        self.timeout_timer.start(1000)  # 1 seconde
    
    def _on_timeout_tick(self):
        """Gestionnaire du tick du timer."""
        self.remaining_seconds -= 1
        
        if self.remaining_seconds > 0:
            # Mettre à jour le compte à rebours
            self.countdown_label.setText(
                f"⏱️ Fermeture auto dans {self.remaining_seconds}s"
            )
        else:
            # Timeout atteint
            self._on_timeout()
    
    def _on_accept(self):
        """Gestionnaire du bouton Accepter."""
        self.timeout_timer.stop()
        self.result_value = "accept"
        
        # Émettre le signal
        self.accepted.emit()
        
        # Appeler le callback
        if self.on_accept_callback:
            try:
                self.on_accept_callback()
            except Exception as e:
                self.logger.error(f"Erreur dans on_accept callback: {e}")
        
        self.logger.info("Dialogue accepté")
        self.accept()
    
    def _on_reject(self):
        """Gestionnaire du bouton Refuser."""
        self.timeout_timer.stop()
        self.result_value = "reject"
        
        # Émettre le signal
        self.rejected.emit()
        
        # Appeler le callback
        if self.on_reject_callback:
            try:
                self.on_reject_callback()
            except Exception as e:
                self.logger.error(f"Erreur dans on_reject callback: {e}")
        
        self.logger.info("Dialogue refusé")
        self.reject()
    
    def _on_timeout(self):
        """Gestionnaire du timeout."""
        self.timeout_timer.stop()
        self.result_value = "timeout"
        
        # Émettre le signal
        self.timeout.emit()
        
        # Par défaut, timeout = reject
        if self.on_reject_callback:
            try:
                self.on_reject_callback()
            except Exception as e:
                self.logger.error(f"Erreur dans on_reject callback (timeout): {e}")
        
        self.logger.info("Dialogue timeout")
        self.reject()
    
    def closeEvent(self, event):
        """Gestionnaire de fermeture du dialogue."""
        # Arrêter le timer
        if hasattr(self, 'timeout_timer'):
            self.timeout_timer.stop()
        
        # Si pas de résultat, considérer comme reject
        if self.result_value is None:
            self.result_value = "reject"
            if self.on_reject_callback:
                try:
                    self.on_reject_callback()
                except Exception as e:
                    self.logger.error(f"Erreur dans on_reject callback (close): {e}")
        
        event.accept()
    
    @staticmethod
    def show_dialog(
        title: str,
        message: str,
        on_accept: Optional[Callable] = None,
        on_reject: Optional[Callable] = None,
        timeout_seconds: int = 10,
        parent=None
    ) -> 'InteractiveDialog':
        """
        Méthode statique pour afficher un dialogue.
        
        Args:
            title: Titre du dialogue
            message: Message à afficher
            on_accept: Callback appelé si l'utilisateur accepte
            on_reject: Callback appelé si l'utilisateur refuse
            timeout_seconds: Durée du timeout en secondes
            parent: Widget parent
            
        Returns:
            Instance du dialogue créé
            
        Examples:
            >>> def on_yes():
            ...     print("Utilisateur a accepté")
            >>> def on_no():
            ...     print("Utilisateur a refusé")
            >>> dialog = InteractiveDialog.show_dialog(
            ...     "Confirmation",
            ...     "Voulez-vous continuer ?",
            ...     on_yes,
            ...     on_no
            ... )
        """
        dialog = InteractiveDialog(
            title, message, on_accept, on_reject, timeout_seconds, parent
        )
        dialog.show()
        return dialog


if __name__ == "__main__":
    """Test de l'InteractiveDialog"""
    import sys
    from PyQt5.QtWidgets import QApplication
    
    app = QApplication(sys.argv)
    
    print("=" * 60)
    print("Test de l'InteractiveDialog")
    print("=" * 60)
    
    # Callbacks de test
    def on_accept():
        print("\n✅ Utilisateur a ACCEPTÉ")
    
    def on_reject():
        print("\n❌ Utilisateur a REFUSÉ")
    
    # Test 1: Dialogue avec timeout de 10 secondes
    print("\nTest 1: Dialogue avec timeout de 10 secondes")
    print("Attendez 10 secondes ou cliquez sur un bouton")
    
    dialog = InteractiveDialog.show_dialog(
        "J'ai une idée !",
        "J'ai remarqué que vous faites souvent:\n"
        "\"Calculer 9/9 dans la calculatrice\"\n\n"
        "Est-ce que je peux essayer de vous suggérer\n"
        "cette action la prochaine fois ?",
        on_accept,
        on_reject,
        timeout_seconds=10
    )
    
    # Connecter les signaux pour les tests
    dialog.accepted.connect(lambda: print("Signal 'accepted' émis"))
    dialog.rejected.connect(lambda: print("Signal 'rejected' émis"))
    dialog.timeout.connect(lambda: print("Signal 'timeout' émis"))
    
    # Test 2: Créer un deuxième dialogue après 3 secondes
    def create_second_dialog():
        print("\nTest 2: Deuxième dialogue avec timeout de 5 secondes")
        dialog2 = InteractiveDialog.show_dialog(
            "Changement de mode",
            "Voulez-vous passer en mode Suggestions ?",
            lambda: print("\n✅ Mode Suggestions activé"),
            lambda: print("\n❌ Reste en mode Shadow"),
            timeout_seconds=5
        )
    
    QTimer.singleShot(3000, create_second_dialog)
    
    sys.exit(app.exec_())
