"""
Tableau de bord résumé pour RPA Vision V2
Affiche les statistiques de tâches, niveaux de confiance et historique d'exécution
"""

from PyQt5.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem,
    QPushButton, QLabel, QLineEdit, QComboBox, QHeaderView, QFileDialog,
    QMessageBox, QWidget, QGroupBox
)
from PyQt5.QtCore import Qt, QTimer, pyqtSignal
from PyQt5.QtGui import QFont, QColor, QBrush
from typing import Dict, Any, List, Optional
import logging
import json
import csv
from datetime import datetime


class SummaryDashboard(QDialog):
    """
    Tableau de bord affichant les métriques de tâches en temps réel
    avec filtrage, recherche et export
    """
    
    # Signal émis quand une tâche est sélectionnée
    task_selected = pyqtSignal(str)  # task_id
    
    def __init__(self, learning_manager=None, parent=None):
        """
        Initialiser le tableau de bord
        
        Args:
            learning_manager: Instance du gestionnaire d'apprentissage
            parent: Widget parent (optionnel)
        """
        super().__init__(parent)
        self.learning_manager = learning_manager
        self.logger = logging.getLogger(__name__)
        
        # Données des tâches
        self.tasks_data: Dict[str, Dict[str, Any]] = {}
        
        # Timer pour mise à jour automatique
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.refresh_data)
        
        self.init_ui()
        
        # Charger les données initiales
        if self.learning_manager:
            self.refresh_data()
        
        # Démarrer les mises à jour automatiques (toutes les 2 secondes)
        self.update_timer.start(2000)
        
        self.logger.info("SummaryDashboard initialisé")
    
    def init_ui(self):
        """Initialiser l'interface utilisateur"""
        self.setWindowTitle("Tableau de Bord - RPA Vision V2")
        self.setMinimumWidth(1000)
        self.setMinimumHeight(600)
        
        # Layout principal
        main_layout = QVBoxLayout()
        self.setLayout(main_layout)
        
        # Titre
        title_label = QLabel("📊 Tableau de Bord des Tâches")
        title_label.setFont(QFont("Arial", 16, QFont.Bold))
        title_label.setStyleSheet("color: #2196F3; padding: 10px;")
        main_layout.addWidget(title_label)
        
        # Barre d'outils (recherche et filtres)
        toolbar_layout = QHBoxLayout()
        
        # Recherche
        search_label = QLabel("🔍 Recherche:")
        search_label.setFont(QFont("Arial", 10))
        toolbar_layout.addWidget(search_label)
        
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("Rechercher par nom de tâche...")
        self.search_input.setFont(QFont("Arial", 10))
        self.search_input.textChanged.connect(self.apply_filters)
        toolbar_layout.addWidget(self.search_input)
        
        # Filtre par mode
        mode_label = QLabel("Mode:")
        mode_label.setFont(QFont("Arial", 10))
        toolbar_layout.addWidget(mode_label)
        
        self.mode_filter = QComboBox()
        self.mode_filter.setFont(QFont("Arial", 10))
        self.mode_filter.addItems(["Tous", "Shadow", "Assisté", "Autopilot"])
        self.mode_filter.currentTextChanged.connect(self.apply_filters)
        toolbar_layout.addWidget(self.mode_filter)
        
        # Bouton rafraîchir
        refresh_button = QPushButton("🔄 Rafraîchir")
        refresh_button.setFont(QFont("Arial", 10))
        refresh_button.clicked.connect(self.refresh_data)
        toolbar_layout.addWidget(refresh_button)
        
        main_layout.addLayout(toolbar_layout)
        
        # Statistiques globales
        stats_group = QGroupBox("Statistiques Globales")
        stats_group.setFont(QFont("Arial", 11, QFont.Bold))
        stats_layout = QHBoxLayout()
        stats_group.setLayout(stats_layout)
        
        self.total_tasks_label = QLabel("Total: 0")
        self.total_tasks_label.setFont(QFont("Arial", 10))
        stats_layout.addWidget(self.total_tasks_label)
        
        self.shadow_tasks_label = QLabel("👀 Shadow: 0")
        self.shadow_tasks_label.setFont(QFont("Arial", 10))
        stats_layout.addWidget(self.shadow_tasks_label)
        
        self.assist_tasks_label = QLabel("🤝 Assisté: 0")
        self.assist_tasks_label.setFont(QFont("Arial", 10))
        stats_layout.addWidget(self.assist_tasks_label)
        
        self.auto_tasks_label = QLabel("🤖 Autopilot: 0")
        self.auto_tasks_label.setFont(QFont("Arial", 10))
        stats_layout.addWidget(self.auto_tasks_label)
        
        stats_layout.addStretch()
        
        main_layout.addWidget(stats_group)
        
        # Tableau des tâches
        self.tasks_table = QTableWidget()
        self.tasks_table.setFont(QFont("Arial", 9))
        self.tasks_table.setColumnCount(8)
        self.tasks_table.setHorizontalHeaderLabels([
            "Tâche",
            "Mode",
            "Confiance",
            "Observations",
            "Concordance",
            "Corrections",
            "Taux Correction",
            "Dernière Exécution"
        ])
        
        # Configuration du tableau
        header = self.tasks_table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.Stretch)  # Tâche
        header.setSectionResizeMode(1, QHeaderView.ResizeToContents)  # Mode
        header.setSectionResizeMode(2, QHeaderView.ResizeToContents)  # Confiance
        header.setSectionResizeMode(3, QHeaderView.ResizeToContents)  # Observations
        header.setSectionResizeMode(4, QHeaderView.ResizeToContents)  # Concordance
        header.setSectionResizeMode(5, QHeaderView.ResizeToContents)  # Corrections
        header.setSectionResizeMode(6, QHeaderView.ResizeToContents)  # Taux Correction
        header.setSectionResizeMode(7, QHeaderView.Stretch)  # Dernière Exécution
        
        self.tasks_table.setAlternatingRowColors(True)
        self.tasks_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.tasks_table.setSelectionMode(QTableWidget.SingleSelection)
        self.tasks_table.itemDoubleClicked.connect(self.on_task_double_clicked)
        
        self.tasks_table.setStyleSheet("""
            QTableWidget {
                border: 2px solid #E0E0E0;
                border-radius: 5px;
                gridline-color: #E0E0E0;
            }
            QTableWidget::item {
                padding: 5px;
            }
            QTableWidget::item:selected {
                background-color: #E3F2FD;
                color: #1976D2;
            }
            QHeaderView::section {
                background-color: #2196F3;
                color: white;
                padding: 8px;
                border: none;
                font-weight: bold;
            }
        """)
        
        main_layout.addWidget(self.tasks_table)
        
        # Boutons d'action
        button_layout = QHBoxLayout()
        
        export_csv_button = QPushButton("📄 Exporter CSV")
        export_csv_button.setFont(QFont("Arial", 10))
        export_csv_button.setStyleSheet("""
            QPushButton {
                background-color: #4CAF50;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
        """)
        export_csv_button.clicked.connect(self.export_to_csv)
        button_layout.addWidget(export_csv_button)
        
        export_json_button = QPushButton("📋 Exporter JSON")
        export_json_button.setFont(QFont("Arial", 10))
        export_json_button.setStyleSheet("""
            QPushButton {
                background-color: #2196F3;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #1976D2;
            }
        """)
        export_json_button.clicked.connect(self.export_to_json)
        button_layout.addWidget(export_json_button)
        
        button_layout.addStretch()
        
        close_button = QPushButton("✗ Fermer")
        close_button.setFont(QFont("Arial", 10))
        close_button.setStyleSheet("""
            QPushButton {
                background-color: #f44336;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #da190b;
            }
        """)
        close_button.clicked.connect(self.close)
        button_layout.addWidget(close_button)
        
        main_layout.addLayout(button_layout)
        
        # Note d'aide
        help_label = QLabel(
            "💡 Astuce: Double-cliquez sur une tâche pour voir les détails"
        )
        help_label.setFont(QFont("Arial", 9))
        help_label.setStyleSheet("color: #666; padding: 5px;")
        main_layout.addWidget(help_label)
    
    def refresh_data(self):
        """Rafraîchir les données depuis le gestionnaire d'apprentissage"""
        if not self.learning_manager:
            return
        
        try:
            # Obtenir toutes les tâches
            tasks = self.learning_manager.get_all_tasks()
            
            # Mettre à jour les données
            self.tasks_data = {task["task_id"]: task for task in tasks}
            
            # Mettre à jour les statistiques globales
            self.update_global_stats()
            
            # Mettre à jour le tableau
            self.update_table()
            
            self.logger.debug(f"Données rafraîchies: {len(self.tasks_data)} tâches")
        
        except Exception as e:
            self.logger.error(f"Erreur lors du rafraîchissement: {e}")
    
    def update_global_stats(self):
        """Mettre à jour les statistiques globales"""
        if not self.learning_manager:
            return
        
        try:
            stats = self.learning_manager.get_task_stats()
            
            self.total_tasks_label.setText(f"Total: {stats.get('total_tasks', 0)}")
            self.shadow_tasks_label.setText(f"👀 Shadow: {stats.get('shadow_tasks', 0)}")
            self.assist_tasks_label.setText(f"🤝 Assisté: {stats.get('assist_tasks', 0)}")
            self.auto_tasks_label.setText(f"🤖 Autopilot: {stats.get('auto_tasks', 0)}")
        
        except Exception as e:
            self.logger.error(f"Erreur lors de la mise à jour des stats: {e}")
    
    def update_metrics(self, task_id: str, metrics: Dict[str, Any]):
        """
        Mettre à jour les métriques d'une tâche spécifique
        
        Args:
            task_id: ID de la tâche
            metrics: Dictionnaire de métriques
        """
        if task_id in self.tasks_data:
            self.tasks_data[task_id].update(metrics)
        else:
            self.tasks_data[task_id] = metrics
        
        # Mettre à jour le tableau
        self.update_table()
        
        self.logger.debug(f"Métriques mises à jour pour tâche: {task_id}")
    
    def update_table(self):
        """Mettre à jour le tableau avec les données filtrées"""
        # Appliquer les filtres
        filtered_tasks = self.get_filtered_tasks()
        
        # Mettre à jour le nombre de lignes
        self.tasks_table.setRowCount(len(filtered_tasks))
        
        # Remplir le tableau
        for row, task in enumerate(filtered_tasks):
            self._populate_row(row, task)
        
        self.logger.debug(f"Tableau mis à jour: {len(filtered_tasks)} tâches affichées")
    
    def _populate_row(self, row: int, task: Dict[str, Any]):
        """
        Remplir une ligne du tableau avec les données d'une tâche
        
        Args:
            row: Numéro de ligne
            task: Dictionnaire de données de tâche
        """
        # Tâche
        task_item = QTableWidgetItem(task.get("task_name", ""))
        task_item.setData(Qt.UserRole, task.get("task_id"))
        self.tasks_table.setItem(row, 0, task_item)
        
        # Mode
        mode = task.get("mode", "shadow")
        mode_icons = {"shadow": "👀", "assist": "🤝", "auto": "🤖"}
        mode_names = {"shadow": "Shadow", "assist": "Assisté", "auto": "Autopilot"}
        mode_text = f"{mode_icons.get(mode, '')} {mode_names.get(mode, mode)}"
        mode_item = QTableWidgetItem(mode_text)
        mode_item.setTextAlignment(Qt.AlignCenter)
        
        # Couleur selon le mode
        mode_colors = {
            "shadow": QColor(33, 150, 243),  # Bleu
            "assist": QColor(255, 152, 0),   # Orange
            "auto": QColor(76, 175, 80)      # Vert
        }
        if mode in mode_colors:
            mode_item.setForeground(QBrush(mode_colors[mode]))
        
        self.tasks_table.setItem(row, 1, mode_item)
        
        # Confiance
        confidence = task.get("confidence_score", 0.0)
        confidence_item = QTableWidgetItem(f"{confidence * 100:.1f}%")
        confidence_item.setTextAlignment(Qt.AlignCenter)
        
        # Couleur selon la confiance
        if confidence >= 0.95:
            confidence_item.setForeground(QBrush(QColor(76, 175, 80)))  # Vert
        elif confidence >= 0.85:
            confidence_item.setForeground(QBrush(QColor(255, 152, 0)))  # Orange
        else:
            confidence_item.setForeground(QBrush(QColor(244, 67, 54)))  # Rouge
        
        self.tasks_table.setItem(row, 2, confidence_item)
        
        # Observations
        obs_count = task.get("observation_count", 0)
        obs_item = QTableWidgetItem(str(obs_count))
        obs_item.setTextAlignment(Qt.AlignCenter)
        self.tasks_table.setItem(row, 3, obs_item)
        
        # Concordance
        concordance = task.get("concordance_rate", 0.0)
        concordance_item = QTableWidgetItem(f"{concordance * 100:.1f}%")
        concordance_item.setTextAlignment(Qt.AlignCenter)
        
        # Couleur selon la concordance
        if concordance >= 0.95:
            concordance_item.setForeground(QBrush(QColor(76, 175, 80)))  # Vert
        elif concordance >= 0.85:
            concordance_item.setForeground(QBrush(QColor(255, 152, 0)))  # Orange
        else:
            concordance_item.setForeground(QBrush(QColor(244, 67, 54)))  # Rouge
        
        self.tasks_table.setItem(row, 4, concordance_item)
        
        # Corrections
        corrections = task.get("correction_count", 0)
        corrections_item = QTableWidgetItem(str(corrections))
        corrections_item.setTextAlignment(Qt.AlignCenter)
        self.tasks_table.setItem(row, 5, corrections_item)
        
        # Taux de correction
        correction_rate = task.get("correction_rate", 0.0)
        correction_rate_item = QTableWidgetItem(f"{correction_rate * 100:.1f}%")
        correction_rate_item.setTextAlignment(Qt.AlignCenter)
        
        # Couleur selon le taux de correction (inverse: moins c'est mieux)
        if correction_rate <= 0.03:
            correction_rate_item.setForeground(QBrush(QColor(76, 175, 80)))  # Vert
        elif correction_rate <= 0.05:
            correction_rate_item.setForeground(QBrush(QColor(255, 152, 0)))  # Orange
        else:
            correction_rate_item.setForeground(QBrush(QColor(244, 67, 54)))  # Rouge
        
        self.tasks_table.setItem(row, 6, correction_rate_item)
        
        # Dernière exécution
        last_exec = task.get("last_execution", "")
        if last_exec:
            try:
                dt = datetime.fromisoformat(last_exec)
                last_exec_text = dt.strftime("%Y-%m-%d %H:%M:%S")
            except:
                last_exec_text = last_exec
        else:
            last_exec_text = "Jamais"
        
        last_exec_item = QTableWidgetItem(last_exec_text)
        self.tasks_table.setItem(row, 7, last_exec_item)
    
    def get_filtered_tasks(self) -> List[Dict[str, Any]]:
        """
        Obtenir la liste des tâches filtrées selon les critères
        
        Returns:
            Liste de tâches filtrées
        """
        filtered = list(self.tasks_data.values())
        
        # Filtre de recherche
        search_text = self.search_input.text().lower()
        if search_text:
            filtered = [
                task for task in filtered
                if search_text in task.get("task_name", "").lower() or
                   search_text in task.get("task_id", "").lower()
            ]
        
        # Filtre de mode
        mode_filter = self.mode_filter.currentText()
        if mode_filter != "Tous":
            mode_map = {
                "Shadow": "shadow",
                "Assisté": "assist",
                "Autopilot": "auto"
            }
            target_mode = mode_map.get(mode_filter)
            if target_mode:
                filtered = [
                    task for task in filtered
                    if task.get("mode") == target_mode
                ]
        
        # Trier par dernière exécution (plus récent en premier)
        filtered.sort(
            key=lambda t: t.get("last_execution", ""),
            reverse=True
        )
        
        return filtered
    
    def apply_filters(self):
        """Appliquer les filtres et mettre à jour le tableau"""
        self.update_table()
    
    def on_task_double_clicked(self, item):
        """
        Gestionnaire de double-clic sur une tâche
        
        Args:
            item: Élément de tableau cliqué
        """
        row = item.row()
        task_id_item = self.tasks_table.item(row, 0)
        
        if task_id_item:
            task_id = task_id_item.data(Qt.UserRole)
            
            if task_id and task_id in self.tasks_data:
                self.show_task_details(task_id)
                self.task_selected.emit(task_id)
    
    def show_task_details(self, task_id: str):
        """
        Afficher les détails d'une tâche dans une boîte de dialogue
        
        Args:
            task_id: ID de la tâche
        """
        if task_id not in self.tasks_data:
            return
        
        task = self.tasks_data[task_id]
        
        details = f"""
<h3>Détails de la Tâche</h3>
<p><b>ID:</b> {task.get('task_id', '')}</p>
<p><b>Nom:</b> {task.get('task_name', '')}</p>
<p><b>Mode:</b> {task.get('mode', '')}</p>
<p><b>Observations:</b> {task.get('observation_count', 0)}</p>
<p><b>Confiance:</b> {task.get('confidence_score', 0) * 100:.1f}%</p>
<p><b>Concordance:</b> {task.get('concordance_rate', 0) * 100:.1f}%</p>
<p><b>Corrections:</b> {task.get('correction_count', 0)}</p>
<p><b>Taux de correction:</b> {task.get('correction_rate', 0) * 100:.1f}%</p>
<p><b>Dernière exécution:</b> {task.get('last_execution', 'Jamais')}</p>
        """
        
        msg_box = QMessageBox(self)
        msg_box.setWindowTitle("Détails de la Tâche")
        msg_box.setTextFormat(Qt.RichText)
        msg_box.setText(details)
        msg_box.setIcon(QMessageBox.Information)
        msg_box.exec_()
    
    def export_to_csv(self):
        """Exporter les données vers un fichier CSV"""
        if not self.tasks_data:
            QMessageBox.warning(
                self,
                "Aucune Donnée",
                "Aucune donnée à exporter."
            )
            return
        
        # Dialogue de sauvegarde
        file_path, _ = QFileDialog.getSaveFileName(
            self,
            "Exporter vers CSV",
            f"rpa_tasks_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
            "CSV Files (*.csv)"
        )
        
        if not file_path:
            return
        
        try:
            with open(file_path, 'w', newline='', encoding='utf-8') as f:
                writer = csv.writer(f)
                
                # En-têtes
                writer.writerow([
                    "ID Tâche",
                    "Nom Tâche",
                    "Mode",
                    "Confiance (%)",
                    "Observations",
                    "Concordance (%)",
                    "Corrections",
                    "Taux Correction (%)",
                    "Dernière Exécution"
                ])
                
                # Données
                for task in self.get_filtered_tasks():
                    writer.writerow([
                        task.get("task_id", ""),
                        task.get("task_name", ""),
                        task.get("mode", ""),
                        f"{task.get('confidence_score', 0) * 100:.1f}",
                        task.get("observation_count", 0),
                        f"{task.get('concordance_rate', 0) * 100:.1f}",
                        task.get("correction_count", 0),
                        f"{task.get('correction_rate', 0) * 100:.1f}",
                        task.get("last_execution", "")
                    ])
            
            QMessageBox.information(
                self,
                "Export Réussi",
                f"Données exportées vers:\n{file_path}"
            )
            
            self.logger.info(f"Données exportées vers CSV: {file_path}")
        
        except Exception as e:
            QMessageBox.critical(
                self,
                "Erreur d'Export",
                f"Erreur lors de l'export CSV:\n{str(e)}"
            )
            self.logger.error(f"Erreur d'export CSV: {e}")
    
    def export_to_json(self):
        """Exporter les données vers un fichier JSON"""
        if not self.tasks_data:
            QMessageBox.warning(
                self,
                "Aucune Donnée",
                "Aucune donnée à exporter."
            )
            return
        
        # Dialogue de sauvegarde
        file_path, _ = QFileDialog.getSaveFileName(
            self,
            "Exporter vers JSON",
            f"rpa_tasks_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
            "JSON Files (*.json)"
        )
        
        if not file_path:
            return
        
        try:
            export_data = {
                "export_date": datetime.now().isoformat(),
                "total_tasks": len(self.tasks_data),
                "tasks": self.get_filtered_tasks()
            }
            
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(export_data, f, indent=2, ensure_ascii=False)
            
            QMessageBox.information(
                self,
                "Export Réussi",
                f"Données exportées vers:\n{file_path}"
            )
            
            self.logger.info(f"Données exportées vers JSON: {file_path}")
        
        except Exception as e:
            QMessageBox.critical(
                self,
                "Erreur d'Export",
                f"Erreur lors de l'export JSON:\n{str(e)}"
            )
            self.logger.error(f"Erreur d'export JSON: {e}")
    
    def closeEvent(self, event):
        """Gestionnaire de fermeture"""
        # Arrêter le timer de mise à jour
        self.update_timer.stop()
        event.accept()
    
    @staticmethod
    def show_dashboard(learning_manager=None, parent=None) -> 'SummaryDashboard':
        """
        Méthode statique pour afficher le tableau de bord
        
        Args:
            learning_manager: Instance du gestionnaire d'apprentissage
            parent: Widget parent (optionnel)
            
        Returns:
            Instance du tableau de bord
        """
        dashboard = SummaryDashboard(learning_manager, parent)
        dashboard.show()
        return dashboard


if __name__ == "__main__":
    """Test du tableau de bord"""
    from PyQt5.QtWidgets import QApplication
    import sys
    
    app = QApplication(sys.argv)
    
    # Créer un tableau de bord avec des données de test
    dashboard = SummaryDashboard()
    
    # Ajouter des données de test
    test_tasks = [
        {
            "task_id": "task_001",
            "task_name": "Ouvrir Facture",
            "mode": "auto",
            "confidence_score": 0.97,
            "observation_count": 45,
            "concordance_rate": 0.98,
            "correction_count": 1,
            "correction_rate": 0.022,
            "last_execution": datetime.now().isoformat()
        },
        {
            "task_id": "task_002",
            "task_name": "Valider Commande",
            "mode": "assist",
            "confidence_score": 0.89,
            "observation_count": 12,
            "concordance_rate": 0.92,
            "correction_count": 2,
            "correction_rate": 0.167,
            "last_execution": datetime.now().isoformat()
        },
        {
            "task_id": "task_003",
            "task_name": "Saisie Données Client",
            "mode": "shadow",
            "confidence_score": 0.65,
            "observation_count": 3,
            "concordance_rate": 0.67,
            "correction_count": 0,
            "correction_rate": 0.0,
            "last_execution": datetime.now().isoformat()
        }
    ]
    
    for task in test_tasks:
        dashboard.update_metrics(task["task_id"], task)
    
    dashboard.show()
    
    sys.exit(app.exec_())
