"""
Dialogue de correction pour permettre à l'utilisateur de corriger
les détections incorrectes et spécifier l'élément UI correct
"""

from PyQt5.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
    QListWidget, QListWidgetItem, QWidget, QTextEdit, QGroupBox
)
from PyQt5.QtCore import Qt, QRect, pyqtSignal
from PyQt5.QtGui import QFont, QPainter, QColor, QPen, QPixmap, QImage
from typing import Optional, Dict, Any, List, Tuple
import logging
import numpy as np


class CorrectionDialog(QDialog):
    """
    Dialogue permettant à l'utilisateur de corriger une détection incorrecte
    en sélectionnant l'élément UI correct parmi les détections alternatives
    ou en cliquant directement sur l'écran
    """
    
    # Signal émis quand une correction est effectuée
    correction_made = pyqtSignal(dict)  # Contient les détails de la correction
    
    def __init__(self, 
                 incorrect_detection: Dict[str, Any],
                 alternative_detections: List[Dict[str, Any]] = None,
                 screenshot: Optional[np.ndarray] = None,
                 parent=None):
        """
        Initialiser le dialogue de correction
        
        Args:
            incorrect_detection: Détection incorrecte à corriger
                {
                    "label": str,
                    "confidence": float,
                    "bbox": (x, y, w, h),
                    "action_type": str
                }
            alternative_detections: Liste de détections alternatives disponibles
            screenshot: Capture d'écran pour sélection visuelle (optionnel)
            parent: Widget parent (optionnel)
        """
        super().__init__(parent)
        self.incorrect_detection = incorrect_detection
        self.alternative_detections = alternative_detections or []
        self.screenshot = screenshot
        self.logger = logging.getLogger(__name__)
        
        self.corrected_element = None
        self.correction_method = None  # "alternative" ou "manual"
        
        self.init_ui()
        
        self.logger.info(f"CorrectionDialog créé pour élément: {incorrect_detection.get('label')}")
    
    def init_ui(self):
        """Initialiser l'interface du dialogue"""
        self.setWindowTitle("Correction de Détection")
        self.setModal(True)
        self.setMinimumWidth(600)
        self.setMinimumHeight(500)
        
        # Layout principal
        main_layout = QVBoxLayout()
        self.setLayout(main_layout)
        
        # Titre
        title_label = QLabel("✎ Correction de Détection Incorrecte")
        title_label.setFont(QFont("Arial", 14, QFont.Bold))
        title_label.setStyleSheet("color: #FF9800; padding: 10px;")
        main_layout.addWidget(title_label)
        
        # Informations sur la détection incorrecte
        incorrect_group = QGroupBox("Détection Incorrecte")
        incorrect_group.setFont(QFont("Arial", 11, QFont.Bold))
        incorrect_layout = QVBoxLayout()
        incorrect_group.setLayout(incorrect_layout)
        
        incorrect_info = self._format_detection_info(self.incorrect_detection)
        incorrect_label = QLabel(incorrect_info)
        incorrect_label.setFont(QFont("Arial", 10))
        incorrect_label.setStyleSheet("padding: 10px; background-color: #FFEBEE; border-radius: 5px;")
        incorrect_layout.addWidget(incorrect_label)
        
        main_layout.addWidget(incorrect_group)
        
        # Section des alternatives
        if self.alternative_detections:
            alternatives_group = QGroupBox("Sélectionner l'Élément Correct")
            alternatives_group.setFont(QFont("Arial", 11, QFont.Bold))
            alternatives_layout = QVBoxLayout()
            alternatives_group.setLayout(alternatives_layout)
            
            instruction_label = QLabel(
                "Sélectionnez l'élément correct parmi les détections alternatives ci-dessous:"
            )
            instruction_label.setFont(QFont("Arial", 10))
            instruction_label.setWordWrap(True)
            alternatives_layout.addWidget(instruction_label)
            
            # Liste des alternatives
            self.alternatives_list = QListWidget()
            self.alternatives_list.setFont(QFont("Arial", 10))
            self.alternatives_list.setStyleSheet("""
                QListWidget {
                    border: 2px solid #2196F3;
                    border-radius: 5px;
                    padding: 5px;
                }
                QListWidget::item {
                    padding: 10px;
                    border-bottom: 1px solid #E0E0E0;
                }
                QListWidget::item:selected {
                    background-color: #E3F2FD;
                    color: #1976D2;
                }
                QListWidget::item:hover {
                    background-color: #F5F5F5;
                }
            """)
            
            for idx, detection in enumerate(self.alternative_detections):
                item_text = self._format_detection_item(detection, idx + 1)
                item = QListWidgetItem(item_text)
                item.setData(Qt.UserRole, detection)
                self.alternatives_list.addItem(item)
            
            self.alternatives_list.itemDoubleClicked.connect(self.on_alternative_selected)
            alternatives_layout.addWidget(self.alternatives_list)
            
            main_layout.addWidget(alternatives_group)
        
        # Section de sélection manuelle
        manual_group = QGroupBox("Ou Spécifier Manuellement")
        manual_group.setFont(QFont("Arial", 11, QFont.Bold))
        manual_layout = QVBoxLayout()
        manual_group.setLayout(manual_layout)
        
        manual_instruction = QLabel(
            "Décrivez l'élément correct ou fournissez des informations supplémentaires:"
        )
        manual_instruction.setFont(QFont("Arial", 10))
        manual_instruction.setWordWrap(True)
        manual_layout.addWidget(manual_instruction)
        
        self.manual_input = QTextEdit()
        self.manual_input.setFont(QFont("Arial", 10))
        self.manual_input.setPlaceholderText(
            "Ex: Le bouton 'Valider' en bas à droite de la fenêtre, "
            "ou les coordonnées approximatives..."
        )
        self.manual_input.setMaximumHeight(80)
        self.manual_input.setStyleSheet("""
            QTextEdit {
                border: 2px solid #9E9E9E;
                border-radius: 5px;
                padding: 5px;
            }
            QTextEdit:focus {
                border-color: #2196F3;
            }
        """)
        manual_layout.addWidget(self.manual_input)
        
        main_layout.addWidget(manual_group)
        
        # Boutons d'action
        button_layout = QHBoxLayout()
        
        self.select_button = QPushButton("✓ Valider la Sélection")
        self.select_button.setFont(QFont("Arial", 11))
        self.select_button.setStyleSheet("""
            QPushButton {
                background-color: #4CAF50;
                color: white;
                border: none;
                padding: 10px 20px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
        """)
        self.select_button.clicked.connect(self.on_validate_correction)
        button_layout.addWidget(self.select_button)
        
        cancel_button = QPushButton("✗ Annuler")
        cancel_button.setFont(QFont("Arial", 11))
        cancel_button.setStyleSheet("""
            QPushButton {
                background-color: #f44336;
                color: white;
                border: none;
                padding: 10px 20px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #da190b;
            }
        """)
        cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(cancel_button)
        
        main_layout.addLayout(button_layout)
        
        # Note d'aide
        help_label = QLabel(
            "💡 Astuce: Double-cliquez sur une alternative pour la sélectionner rapidement"
        )
        help_label.setFont(QFont("Arial", 9))
        help_label.setStyleSheet("color: #666; padding: 5px;")
        main_layout.addWidget(help_label)
    
    def _format_detection_info(self, detection: Dict[str, Any]) -> str:
        """
        Formater les informations d'une détection pour affichage
        
        Args:
            detection: Dictionnaire de détection
            
        Returns:
            Chaîne formatée
        """
        label = detection.get("label", "inconnu")
        confidence = detection.get("confidence", 0.0)
        bbox = detection.get("bbox", (0, 0, 0, 0))
        action_type = detection.get("action_type", "action")
        
        info = f"<b>Élément:</b> {label}<br>"
        info += f"<b>Action:</b> {action_type}<br>"
        info += f"<b>Confiance:</b> {confidence * 100:.1f}%<br>"
        info += f"<b>Position:</b> ({bbox[0]}, {bbox[1]}) - Taille: {bbox[2]}×{bbox[3]}px"
        
        return info
    
    def _format_detection_item(self, detection: Dict[str, Any], index: int) -> str:
        """
        Formater un élément de détection pour la liste
        
        Args:
            detection: Dictionnaire de détection
            index: Numéro de l'alternative
            
        Returns:
            Chaîne formatée
        """
        label = detection.get("label", "inconnu")
        confidence = detection.get("confidence", 0.0)
        bbox = detection.get("bbox", (0, 0, 0, 0))
        
        return (f"{index}. {label} "
                f"(Confiance: {confidence * 100:.1f}%, "
                f"Position: {bbox[0]},{bbox[1]})")
    
    def on_alternative_selected(self, item: QListWidgetItem):
        """
        Gestionnaire de sélection d'une alternative (double-clic)
        
        Args:
            item: Élément de liste sélectionné
        """
        detection = item.data(Qt.UserRole)
        self.corrected_element = detection
        self.correction_method = "alternative"
        
        self.logger.info(f"Alternative sélectionnée: {detection.get('label')}")
        self.accept()
    
    def on_validate_correction(self):
        """Valider la correction (bouton Valider)"""
        # Vérifier si une alternative est sélectionnée
        if self.alternative_detections and self.alternatives_list.currentItem():
            item = self.alternatives_list.currentItem()
            detection = item.data(Qt.UserRole)
            self.corrected_element = detection
            self.correction_method = "alternative"
            
            self.logger.info(f"Correction validée (alternative): {detection.get('label')}")
            self.accept()
        
        # Sinon, vérifier si une description manuelle est fournie
        elif self.manual_input.toPlainText().strip():
            manual_description = self.manual_input.toPlainText().strip()
            self.corrected_element = {
                "label": "manual_correction",
                "description": manual_description,
                "confidence": 0.0,
                "bbox": self.incorrect_detection.get("bbox", (0, 0, 0, 0)),
                "action_type": self.incorrect_detection.get("action_type", "action")
            }
            self.correction_method = "manual"
            
            self.logger.info(f"Correction validée (manuelle): {manual_description[:50]}...")
            self.accept()
        
        else:
            # Aucune correction fournie
            from PyQt5.QtWidgets import QMessageBox
            QMessageBox.warning(
                self,
                "Correction Requise",
                "Veuillez sélectionner une alternative ou fournir une description manuelle."
            )
    
    def get_corrected_element(self) -> Optional[Dict[str, Any]]:
        """
        Obtenir l'élément corrigé après fermeture du dialogue
        
        Returns:
            Dictionnaire contenant les détails de la correction, ou None si annulé
            {
                "corrected_element": Dict[str, Any],
                "correction_method": str,
                "original_detection": Dict[str, Any]
            }
        """
        if self.corrected_element:
            return {
                "corrected_element": self.corrected_element,
                "correction_method": self.correction_method,
                "original_detection": self.incorrect_detection
            }
        return None
    
    @staticmethod
    def show_correction_dialog(incorrect_detection: Dict[str, Any],
                               alternative_detections: List[Dict[str, Any]] = None,
                               screenshot: Optional[np.ndarray] = None,
                               parent=None) -> Optional[Dict[str, Any]]:
        """
        Méthode statique pour afficher le dialogue et obtenir la correction
        
        Args:
            incorrect_detection: Détection incorrecte
            alternative_detections: Liste de détections alternatives
            screenshot: Capture d'écran (optionnel)
            parent: Widget parent (optionnel)
            
        Returns:
            Dictionnaire de correction ou None si annulé
        """
        dialog = CorrectionDialog(
            incorrect_detection,
            alternative_detections,
            screenshot,
            parent
        )
        
        result = dialog.exec_()
        
        if result == QDialog.Accepted:
            return dialog.get_corrected_element()
        
        return None


if __name__ == "__main__":
    """Test du dialogue de correction"""
    from PyQt5.QtWidgets import QApplication
    import sys
    
    app = QApplication(sys.argv)
    
    # Données de test
    incorrect = {
        "label": "annuler_button",
        "confidence": 0.75,
        "bbox": (300, 400, 100, 35),
        "action_type": "click"
    }
    
    alternatives = [
        {
            "label": "valider_button",
            "confidence": 0.92,
            "bbox": (450, 400, 100, 35),
            "action_type": "click"
        },
        {
            "label": "enregistrer_button",
            "confidence": 0.88,
            "bbox": (600, 400, 120, 35),
            "action_type": "click"
        },
        {
            "label": "fermer_button",
            "confidence": 0.65,
            "bbox": (750, 50, 30, 30),
            "action_type": "click"
        }
    ]
    
    correction = CorrectionDialog.show_correction_dialog(
        incorrect,
        alternatives
    )
    
    if correction:
        print("Correction effectuée:")
        print(f"  Méthode: {correction['correction_method']}")
        print(f"  Élément corrigé: {correction['corrected_element']['label']}")
        print(f"  Élément original: {correction['original_detection']['label']}")
    else:
        print("Correction annulée")
