"""
LogsPanel - Widget Qt pour affichage des logs avec scroll et auto-scroll conditionnel
Affiche les messages de log avec timestamp, emoji et formatage.
"""

from PyQt5.QtWidgets import (
    QWidget, QVBoxLayout, QScrollArea, QLabel, QFrame
)
from PyQt5.QtCore import Qt, QTimer, pyqtSignal
from PyQt5.QtGui import QFont
from datetime import datetime
from typing import List, Optional
from dataclasses import dataclass


@dataclass
class LogMessage:
    """Message de log pour affichage."""
    timestamp: datetime
    emoji: str
    message: str
    level: str  # 'info', 'success', 'warning', 'error'
    technical_details: Optional[str] = None  # Pour logs techniques


class LogsPanel(QWidget):
    """
    Panneau d'affichage des logs avec scroll automatique conditionnel.
    
    Caractéristiques:
    - Affiche les 5 dernières actions visibles par défaut
    - Scrollable jusqu'à 30 messages maximum
    - Auto-scroll uniquement si déjà en bas
    - Format: HH:MM emoji Message
    - Supprime automatiquement les messages les plus anciens au-delà de 30
    
    Attributes:
        max_logs: Nombre maximum de logs à conserver (30)
        logs: Liste des messages de log
        log_labels: Liste des widgets QLabel pour chaque log
        scroll_area: Zone de scroll pour les logs
        content_widget: Widget contenant tous les logs
    """
    
    # Signal émis quand un log est ajouté
    log_added = pyqtSignal(str)
    
    def __init__(self, parent=None):
        """
        Initialise le panneau de logs.
        
        Args:
            parent: Widget parent (optionnel)
        """
        super().__init__(parent)
        
        self.max_logs = 30
        self.logs: List[LogMessage] = []
        self.log_labels: List[QLabel] = []
        
        self._init_ui()
    
    def _init_ui(self):
        """Initialise l'interface utilisateur du panneau."""
        # Layout principal
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)
        self.setLayout(main_layout)
        
        # Titre du panneau
        title_label = QLabel("📝 Journal d'activité")
        title_label.setFont(QFont("Arial", 11, QFont.Bold))
        title_label.setStyleSheet("""
            QLabel {
                padding: 8px;
                background-color: #f5f5f5;
                border-bottom: 2px solid #e0e0e0;
            }
        """)
        main_layout.addWidget(title_label)
        
        # Zone de scroll pour les logs
        self.scroll_area = QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.scroll_area.setStyleSheet("""
            QScrollArea {
                border: none;
                background-color: white;
            }
        """)
        
        # Widget contenant les logs
        self.content_widget = QWidget()
        self.content_layout = QVBoxLayout()
        self.content_layout.setContentsMargins(5, 5, 5, 5)
        self.content_layout.setSpacing(2)
        self.content_layout.addStretch()  # Push logs to top
        self.content_widget.setLayout(self.content_layout)
        
        self.scroll_area.setWidget(self.content_widget)
        main_layout.addWidget(self.scroll_area)
        
        # Message par défaut si aucun log
        self._show_empty_message()
    
    def _show_empty_message(self):
        """Affiche un message quand il n'y a pas de logs."""
        if len(self.logs) == 0:
            empty_label = QLabel("💤 En attente d'activité...")
            empty_label.setFont(QFont("Arial", 10))
            empty_label.setStyleSheet("""
                QLabel {
                    color: #999;
                    padding: 20px;
                    text-align: center;
                }
            """)
            empty_label.setAlignment(Qt.AlignCenter)
            self.content_layout.insertWidget(0, empty_label)
    
    def _remove_empty_message(self):
        """Supprime le message vide si présent."""
        if self.content_layout.count() > 1:
            item = self.content_layout.itemAt(0)
            if item and item.widget():
                widget = item.widget()
                if isinstance(widget, QLabel) and "En attente" in widget.text():
                    self.content_layout.removeWidget(widget)
                    widget.deleteLater()
    
    def _is_scrolled_to_bottom(self) -> bool:
        """
        Vérifie si le scroll est en bas.
        
        Returns:
            True si le scroll est en bas (ou proche), False sinon
        """
        scrollbar = self.scroll_area.verticalScrollBar()
        # Considérer "en bas" si on est à moins de 10 pixels du bas
        return scrollbar.value() >= scrollbar.maximum() - 10
    
    def _scroll_to_bottom(self):
        """Scroll vers le bas de la zone de logs."""
        scrollbar = self.scroll_area.verticalScrollBar()
        scrollbar.setValue(scrollbar.maximum())
    
    def add_log(self, message: str, emoji: str = "ℹ️", level: str = "info"):
        """
        Ajoute un log avec timestamp.
        
        Args:
            message: Message à afficher
            emoji: Emoji à afficher (défaut: ℹ️)
            level: Niveau du log ('info', 'success', 'warning', 'error')
            
        Examples:
            >>> panel = LogsPanel()
            >>> panel.add_log("J'observe vos actions", "👀", "info")
            >>> panel.add_log("Pattern détecté", "🎯", "success")
        """
        # Vérifier si on doit auto-scroll
        should_auto_scroll = self._is_scrolled_to_bottom()
        
        # Créer le message de log
        log_msg = LogMessage(
            timestamp=datetime.now(),
            emoji=emoji,
            message=message,
            level=level
        )
        
        # Ajouter à la liste
        self.logs.append(log_msg)
        
        # Supprimer le message vide si c'est le premier log
        if len(self.logs) == 1:
            self._remove_empty_message()
        
        # Supprimer les logs les plus anciens si on dépasse la limite
        while len(self.logs) > self.max_logs:
            removed_log = self.logs.pop(0)
            # Supprimer le widget correspondant
            if len(self.log_labels) > 0:
                old_label = self.log_labels.pop(0)
                self.content_layout.removeWidget(old_label)
                old_label.deleteLater()
        
        # Créer le widget pour ce log
        log_label = self._create_log_label(log_msg)
        self.log_labels.append(log_label)
        
        # Insérer avant le stretch (qui est toujours en dernier)
        insert_position = self.content_layout.count() - 1
        self.content_layout.insertWidget(insert_position, log_label)
        
        # Auto-scroll si on était déjà en bas
        if should_auto_scroll:
            # Utiliser un timer pour s'assurer que le layout est mis à jour
            QTimer.singleShot(10, self._scroll_to_bottom)
        
        # Émettre le signal
        self.log_added.emit(message)
    
    def _create_log_label(self, log_msg: LogMessage) -> QLabel:
        """
        Crée un widget QLabel pour un message de log.
        
        Args:
            log_msg: Message de log à afficher
            
        Returns:
            QLabel formaté pour le log
        """
        # Formater le timestamp (HH:MM)
        time_str = log_msg.timestamp.strftime("%H:%M")
        
        # Créer le texte complet
        text = f"{time_str} {log_msg.emoji} {log_msg.message}"
        
        # Créer le label
        label = QLabel(text)
        label.setFont(QFont("Arial", 9))
        label.setWordWrap(True)
        label.setTextInteractionFlags(Qt.TextSelectableByMouse)
        
        # Couleurs selon le niveau
        level_colors = {
            "info": "#333",
            "success": "#4CAF50",
            "warning": "#FF9800",
            "error": "#f44336"
        }
        
        level_bg_colors = {
            "info": "#f9f9f9",
            "success": "#E8F5E9",
            "warning": "#FFF3E0",
            "error": "#FFEBEE"
        }
        
        color = level_colors.get(log_msg.level, level_colors["info"])
        bg_color = level_bg_colors.get(log_msg.level, level_bg_colors["info"])
        
        label.setStyleSheet(f"""
            QLabel {{
                color: {color};
                background-color: {bg_color};
                padding: 6px 8px;
                border-radius: 4px;
                border-left: 3px solid {color};
            }}
        """)
        
        return label
    
    def clear(self):
        """Efface tous les logs."""
        # Supprimer tous les widgets
        for label in self.log_labels:
            self.content_layout.removeWidget(label)
            label.deleteLater()
        
        # Réinitialiser les listes
        self.logs.clear()
        self.log_labels.clear()
        
        # Afficher le message vide
        self._show_empty_message()
    
    def get_logs(self) -> List[LogMessage]:
        """
        Retourne l'historique des logs.
        
        Returns:
            Liste des messages de log
        """
        return self.logs.copy()
    
    def get_log_count(self) -> int:
        """
        Retourne le nombre de logs actuellement affichés.
        
        Returns:
            Nombre de logs
        """
        return len(self.logs)
    
    def get_last_log(self) -> Optional[LogMessage]:
        """
        Retourne le dernier log ajouté.
        
        Returns:
            Dernier message de log ou None si aucun log
        """
        if len(self.logs) > 0:
            return self.logs[-1]
        return None


if __name__ == "__main__":
    """Test du LogsPanel"""
    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow
    
    app = QApplication(sys.argv)
    
    # Créer une fenêtre de test
    window = QMainWindow()
    window.setWindowTitle("Test LogsPanel")
    window.setGeometry(100, 100, 400, 500)
    
    # Créer le panneau de logs
    logs_panel = LogsPanel()
    window.setCentralWidget(logs_panel)
    
    # Ajouter quelques logs de test
    logs_panel.add_log("J'observe vos actions dans Calculator", "👀", "info")
    logs_panel.add_log("Tiens ! Vous avez fait 3 fois la même chose", "🎯", "success")
    logs_panel.add_log("J'apprends: Calculer 9/9 (5 observations)", "📚", "info")
    logs_panel.add_log("Mode Suggestions activé", "✅", "success")
    logs_panel.add_log("Prêt à suggérer: Calculer 9/9", "💡", "info")
    
    # Ajouter un log d'erreur
    logs_panel.add_log("Impossible de se connecter - Calculator", "⚠️", "error")
    
    # Ajouter un log d'avertissement
    logs_panel.add_log("Application non autorisée", "⚠️", "warning")
    
    # Test: Ajouter beaucoup de logs pour tester la limite de 30
    print(f"Nombre de logs avant test: {logs_panel.get_log_count()}")
    
    for i in range(25):
        logs_panel.add_log(f"Test log #{i+8}", "📝", "info")
    
    print(f"Nombre de logs après ajout de 25: {logs_panel.get_log_count()}")
    print(f"Limite max: {logs_panel.max_logs}")
    
    # Vérifier que le dernier log est bien le dernier ajouté
    last_log = logs_panel.get_last_log()
    if last_log:
        print(f"Dernier log: {last_log.message}")
    
    window.show()
    sys.exit(app.exec_())
