"""
EnhancedWorkflowMatcher pour la Phase 3 - Mode Complet.
Matching de workflows amélioré avec embeddings multi-modaux et matching au niveau élément.

Améliorations par rapport au WorkflowMatcher classique:
1. Utilise les embeddings multi-modaux fusionnés
2. Matching au niveau des éléments UI individuels
3. Scoring composite (écran global + éléments)
4. Cache des embeddings pour performance
5. Métriques détaillées
"""

import numpy as np
from typing import Dict, List, Optional, Tuple, Any
from dataclasses import dataclass
from pathlib import Path
import json
from datetime import datetime

from .ui_element_models import EnrichedScreenState, UIElement
from .multimodal_embedding_manager import MultiModalEmbeddingManager
from .logger import Logger


@dataclass
class ElementMatch:
    """Représente un match entre un élément UI et un élément de workflow."""
    ui_element: UIElement
    workflow_element_id: str
    similarity_score: float
    match_type: str  # "exact", "similar", "partial"
    confidence: float
    
    def to_dict(self) -> Dict[str, Any]:
        """Convertit en dictionnaire."""
        return {
            "ui_element_id": self.ui_element.element_id,
            "ui_element_label": self.ui_element.label,
            "workflow_element_id": self.workflow_element_id,
            "similarity_score": float(self.similarity_score),
            "match_type": self.match_type,
            "confidence": float(self.confidence)
        }


@dataclass
class MatchDifference:
    """Représente une différence détectée lors du matching."""
    difference_type: str  # "missing_element", "wrong_type", "wrong_position", "low_similarity"
    severity: str  # "critical", "major", "minor"
    description: str
    expected: Optional[Any] = None
    actual: Optional[Any] = None
    suggestion: Optional[str] = None
    
    def to_dict(self) -> Dict[str, Any]:
        """Convertit en dictionnaire."""
        return {
            "type": self.difference_type,
            "severity": self.severity,
            "description": self.description,
            "expected": self.expected,
            "actual": self.actual,
            "suggestion": self.suggestion
        }


@dataclass
class WorkflowMatch:
    """Représente un match complet entre un écran et un workflow."""
    workflow_id: str
    workflow_name: str
    screen_similarity: float
    element_matches: List[ElementMatch]
    composite_score: float
    confidence: float
    match_details: Dict[str, Any]
    differences: Optional[List[MatchDifference]] = None  # Nouveau champ pour le feedback
    
    def to_dict(self) -> Dict[str, Any]:
        """Convertit en dictionnaire."""
        result = {
            "workflow_id": self.workflow_id,
            "workflow_name": self.workflow_name,
            "screen_similarity": float(self.screen_similarity),
            "element_matches": [match.to_dict() for match in self.element_matches],
            "composite_score": float(self.composite_score),
            "confidence": float(self.confidence),
            "match_details": self.match_details
        }
        if self.differences:
            result["differences"] = [diff.to_dict() for diff in self.differences]
        return result
    
    def get_feedback_summary(self) -> str:
        """Génère un résumé lisible du feedback."""
        if not self.differences:
            return "✓ Match réussi - Aucun problème détecté"
        
        lines = [f"⚠ Match partiel - {len(self.differences)} différence(s) détectée(s):"]
        
        # Grouper par sévérité
        critical = [d for d in self.differences if d.severity == "critical"]
        major = [d for d in self.differences if d.severity == "major"]
        minor = [d for d in self.differences if d.severity == "minor"]
        
        if critical:
            lines.append(f"\n🔴 Critique ({len(critical)}):")
            for diff in critical:
                lines.append(f"  - {diff.description}")
                if diff.suggestion:
                    lines.append(f"    💡 {diff.suggestion}")
        
        if major:
            lines.append(f"\n🟠 Majeur ({len(major)}):")
            for diff in major:
                lines.append(f"  - {diff.description}")
                if diff.suggestion:
                    lines.append(f"    💡 {diff.suggestion}")
        
        if minor:
            lines.append(f"\n🟡 Mineur ({len(minor)}):")
            for diff in minor:
                lines.append(f"  - {diff.description}")
        
        return "\n".join(lines)


class EnhancedWorkflowMatcher:
    """
    Matcher de workflows amélioré avec embeddings multi-modaux.
    
    Stratégie de matching:
    1. Matching global de l'écran (embedding multi-modal)
    2. Matching individuel des éléments UI
    3. Scoring composite pondéré
    4. Filtrage par seuils de confiance
    """
    
    def __init__(
        self,
        multimodal_manager: MultiModalEmbeddingManager,
        logger: Optional[Logger] = None,
        config: Optional[Dict[str, Any]] = None
    ):
        """
        Initialise l'EnhancedWorkflowMatcher.
        
        Args:
            multimodal_manager: Gestionnaire d'embeddings multi-modaux
            logger: Logger
            config: Configuration
        """
        self.multimodal_manager = multimodal_manager
        self.logger = logger
        self.config = config or {}
        
        # Configuration du matching
        self.screen_weight = self.config.get("screen_weight", 0.6)
        self.elements_weight = self.config.get("elements_weight", 0.4)
        self.min_similarity_threshold = self.config.get("min_similarity_threshold", 0.3)
        self.min_confidence_threshold = self.config.get("min_confidence_threshold", 0.5)
        self.max_candidates = self.config.get("max_candidates", 10)
        
        # Cache des workflows et embeddings
        self._workflow_cache = {}
        self._embedding_cache = {}
        
        if self.logger:
            self.logger.log_action({
                "action": "enhanced_workflow_matcher_initialized",
                "screen_weight": self.screen_weight,
                "elements_weight": self.elements_weight,
                "min_similarity_threshold": self.min_similarity_threshold
            })
    
    def find_matching_workflows(
        self,
        screen_state: EnrichedScreenState,
        screenshot: Optional[np.ndarray] = None,
        workflows: Optional[List] = None,
        top_k: int = 5
    ) -> List[WorkflowMatch]:
        """
        Trouve les workflows qui matchent le mieux avec l'écran actuel.
        
        Args:
            screen_state: État d'écran enrichi
            screenshot: Screenshot numpy array
            workflows: Liste de workflows à comparer (charge tous si None)
            top_k: Nombre de meilleurs matches à retourner
            
        Returns:
            Liste des meilleurs WorkflowMatch triés par score
        """
        try:
            # Générer l'embedding multi-modal de l'écran actuel
            current_embedding = self._get_screen_embedding(screen_state, screenshot)
            
            if current_embedding is None:
                if self.logger:
                    self.logger.log_action({
                        "action": "matching_failed_no_embedding",
                        "screen_state_id": screen_state.screen_state_id
                    })
                return []
            
            # Charger les workflows si non fournis
            if workflows is None:
                workflows = self._load_all_workflows()
            
            # Calculer les matches pour chaque workflow
            matches = []
            for workflow in workflows:
                match = self._compute_workflow_match(
                    screen_state, current_embedding, workflow
                )
                if match and match.composite_score >= self.min_similarity_threshold:
                    matches.append(match)
            
            # Trier par score composite décroissant
            matches.sort(key=lambda m: m.composite_score, reverse=True)
            
            # Limiter au top_k
            matches = matches[:top_k]
            
            if self.logger:
                self.logger.log_action({
                    "action": "workflow_matching_completed",
                    "screen_state_id": screen_state.screen_state_id,
                    "workflows_evaluated": len(workflows),
                    "matches_found": len(matches),
                    "top_score": matches[0].composite_score if matches else 0.0
                })
            
            return matches
        
        except Exception as e:
            if self.logger:
                self.logger.log_action({
                    "action": "workflow_matching_error",
                    "screen_state_id": screen_state.screen_state_id,
                    "error": str(e)
                })
            return []
    
    def _get_screen_embedding(
        self,
        screen_state: EnrichedScreenState,
        screenshot: Optional[np.ndarray]
    ) -> Optional[np.ndarray]:
        """Obtient l'embedding multi-modal de l'écran."""
        try:
            # Vérifier le cache
            cache_key = screen_state.screen_state_id
            if cache_key in self._embedding_cache:
                return self._embedding_cache[cache_key]
            
            # Générer l'embedding si pas en cache
            if screen_state.state_embedding and screen_state.state_embedding.provider == "multimodal_fusion_v1":
                # Charger l'embedding existant
                embedding = self.multimodal_manager.load_fused_embedding(
                    screen_state.state_embedding.vector_id
                )
            else:
                # Générer un nouvel embedding multi-modal
                state_embedding = self.multimodal_manager.generate_multimodal_embedding(
                    screen_state, screenshot, save=False
                )
                embedding = self.multimodal_manager.load_fused_embedding(
                    state_embedding.vector_id
                )
            
            # Mettre en cache
            if embedding is not None:
                self._embedding_cache[cache_key] = embedding
            
            return embedding
        
        except Exception as e:
            if self.logger:
                self.logger.log_action({
                    "action": "screen_embedding_error",
                    "screen_state_id": screen_state.screen_state_id,
                    "error": str(e)
                })
            return None
    
    def _compute_workflow_match(
        self,
        screen_state: EnrichedScreenState,
        current_embedding: np.ndarray,
        workflow: Any
    ) -> Optional[WorkflowMatch]:
        """
        Calcule le match entre un écran et un workflow.
        
        Args:
            screen_state: État d'écran actuel
            current_embedding: Embedding de l'écran actuel
            workflow: Workflow à comparer
            
        Returns:
            WorkflowMatch ou None si pas de match valide
        """
        try:
            # 1. Matching global de l'écran
            screen_similarity = self._compute_screen_similarity(
                current_embedding, workflow
            )
            
            # 2. Matching des éléments UI
            element_matches = self._compute_element_matches(
                screen_state.ui_elements, workflow
            )
            
            # 3. Calcul du score composite
            elements_score = self._compute_elements_score(element_matches)
            composite_score = (
                self.screen_weight * screen_similarity +
                self.elements_weight * elements_score
            )
            
            # 4. Calcul de la confiance
            confidence = self._compute_match_confidence(
                screen_similarity, elements_score, element_matches
            )
            
            # 5. Détails du match
            match_details = {
                "screen_similarity": float(screen_similarity),
                "elements_score": float(elements_score),
                "elements_count": len(element_matches),
                "exact_matches": len([m for m in element_matches if m.match_type == "exact"]),
                "similar_matches": len([m for m in element_matches if m.match_type == "similar"]),
                "partial_matches": len([m for m in element_matches if m.match_type == "partial"]),
                "timestamp": datetime.now().isoformat()
            }
            
            # 6. Générer le feedback détaillé si le match n'est pas parfait
            differences = None
            if composite_score < 0.9 or confidence < 0.8:
                differences = self._generate_match_feedback(
                    screen_state, workflow, screen_similarity, 
                    element_matches, composite_score
                )
            
            return WorkflowMatch(
                workflow_id=getattr(workflow, 'workflow_id', 'unknown'),
                workflow_name=getattr(workflow, 'name', 'unknown'),
                screen_similarity=screen_similarity,
                element_matches=element_matches,
                composite_score=composite_score,
                confidence=confidence,
                match_details=match_details,
                differences=differences
            )
        
        except Exception as e:
            if self.logger:
                self.logger.log_action({
                    "action": "workflow_match_computation_error",
                    "workflow_id": getattr(workflow, 'workflow_id', 'unknown'),
                    "error": str(e)
                })
            return None
    
    def _compute_screen_similarity(
        self,
        current_embedding: np.ndarray,
        workflow: Any
    ) -> float:
        """
        Calcule la similarité globale de l'écran avec le workflow.
        
        Compare l'embedding de l'écran actuel avec les embeddings des steps du workflow.
        Retourne la similarité maximale trouvée.
        
        Args:
            current_embedding: Embedding de l'écran actuel
            workflow: Workflow à comparer
            
        Returns:
            Score de similarité entre 0.0 et 1.0
        """
        try:
            if not hasattr(workflow, 'steps') or not workflow.steps:
                return 0.0
            
            similarities = []
            
            for step in workflow.steps:
                if step.embedding is not None:
                    # Calculer la similarité cosinus
                    similarity = self.multimodal_manager.compute_similarity(
                        current_embedding,
                        step.embedding,
                        metric="cosine"
                    )
                    similarities.append(similarity)
            
            if similarities:
                # Retourner la similarité maximale (meilleur match)
                max_similarity = float(np.max(similarities))
                
                if self.logger:
                    self.logger.log_action({
                        "action": "screen_similarity_computed",
                        "workflow_id": getattr(workflow, 'workflow_id', 'unknown'),
                        "max_similarity": max_similarity,
                        "avg_similarity": float(np.mean(similarities)),
                        "steps_compared": len(similarities)
                    })
                
                return max_similarity
            else:
                # Aucun embedding disponible dans le workflow
                if self.logger:
                    self.logger.log_action({
                        "action": "screen_similarity_no_embeddings",
                        "workflow_id": getattr(workflow, 'workflow_id', 'unknown')
                    })
                return 0.0
        
        except Exception as e:
            if self.logger:
                self.logger.log_action({
                    "action": "screen_similarity_error",
                    "workflow_id": getattr(workflow, 'workflow_id', 'unknown'),
                    "error": str(e)
                })
            return 0.0
    
    def _compute_element_matches(
        self,
        ui_elements: List[UIElement],
        workflow: Any
    ) -> List[ElementMatch]:
        """
        Calcule les matches entre éléments UI et éléments de workflow.
        
        Compare les éléments UI détectés avec les target_description des steps du workflow.
        Utilise la similarité textuelle et la position pour trouver les meilleurs matches.
        
        Args:
            ui_elements: Liste des éléments UI détectés
            workflow: Workflow à comparer
            
        Returns:
            Liste des ElementMatch trouvés
        """
        if not ui_elements or not hasattr(workflow, 'steps') or not workflow.steps:
            return []
        
        matches = []
        
        try:
            # Pour chaque step du workflow, chercher le meilleur élément UI correspondant
            for step in workflow.steps:
                if not step.target_description:
                    continue
                
                best_match = None
                best_score = 0.0
                
                # Comparer avec chaque élément UI
                for ui_element in ui_elements:
                    # Calculer la similarité textuelle
                    text_similarity = self._compute_text_similarity(
                        ui_element.label.lower(),
                        step.target_description.lower()
                    )
                    
                    # Calculer la similarité de position (si disponible)
                    position_similarity = 0.0
                    if step.position and ui_element.bbox:
                        position_similarity = self._compute_position_similarity(
                            ui_element.bbox,
                            step.position
                        )
                    
                    # Score combiné (70% texte, 30% position)
                    combined_score = 0.7 * text_similarity + 0.3 * position_similarity
                    
                    if combined_score > best_score:
                        best_score = combined_score
                        
                        # Déterminer le type de match
                        if combined_score >= 0.85:
                            match_type = "exact"
                        elif combined_score >= 0.6:
                            match_type = "similar"
                        else:
                            match_type = "partial"
                        
                        best_match = ElementMatch(
                            ui_element=ui_element,
                            workflow_element_id=f"{workflow.workflow_id}_step_{step.step_id}",
                            similarity_score=combined_score,
                            match_type=match_type,
                            confidence=combined_score * ui_element.confidence
                        )
                
                # Ajouter le meilleur match si au-dessus du seuil
                if best_match and best_match.similarity_score >= 0.3:
                    matches.append(best_match)
            
            if self.logger:
                self.logger.log_action({
                    "action": "element_matches_computed",
                    "workflow_id": getattr(workflow, 'workflow_id', 'unknown'),
                    "ui_elements_count": len(ui_elements),
                    "workflow_steps_count": len(workflow.steps),
                    "matches_found": len(matches),
                    "exact_matches": len([m for m in matches if m.match_type == "exact"]),
                    "similar_matches": len([m for m in matches if m.match_type == "similar"]),
                    "partial_matches": len([m for m in matches if m.match_type == "partial"])
                })
            
            return matches
        
        except Exception as e:
            if self.logger:
                self.logger.log_action({
                    "action": "element_matches_error",
                    "workflow_id": getattr(workflow, 'workflow_id', 'unknown'),
                    "error": str(e)
                })
            return []
    
    def _compute_position_similarity(
        self,
        bbox: Tuple[int, int, int, int],
        target_position: Tuple[int, int]
    ) -> float:
        """
        Calcule la similarité de position entre un bbox et une position cible.
        
        Args:
            bbox: (x, y, width, height) de l'élément UI
            target_position: (x, y) de la position cible
            
        Returns:
            Score de similarité entre 0.0 et 1.0
        """
        try:
            # Calculer le centre du bbox
            center_x = bbox[0] + bbox[2] / 2
            center_y = bbox[1] + bbox[3] / 2
            
            # Calculer la distance euclidienne
            distance = np.sqrt(
                (center_x - target_position[0]) ** 2 +
                (center_y - target_position[1]) ** 2
            )
            
            # Normaliser la distance (supposons un écran de 1920x1080)
            max_distance = np.sqrt(1920**2 + 1080**2)
            normalized_distance = distance / max_distance
            
            # Convertir en similarité (1.0 = même position, 0.0 = très éloigné)
            similarity = 1.0 - normalized_distance
            
            return max(0.0, min(1.0, similarity))
        
        except Exception as e:
            return 0.0
    
    def _compute_text_similarity(self, text1: str, text2: str) -> float:
        """
        Calcule la similarité entre deux textes.
        
        Utilise la similarité de Jaccard (intersection / union des mots).
        
        Args:
            text1: Premier texte
            text2: Deuxième texte
            
        Returns:
            Score de similarité entre 0.0 et 1.0
        """
        if not text1 or not text2:
            return 0.0
        
        # Tokenisation simple
        words1 = set(text1.lower().split())
        words2 = set(text2.lower().split())
        
        # Intersection et union
        intersection = words1.intersection(words2)
        union = words1.union(words2)
        
        if not union:
            return 0.0
        
        # Jaccard similarity
        return len(intersection) / len(union)
    
    def _compute_elements_score(self, element_matches: List[ElementMatch]) -> float:
        """
        Calcule le score global des matches d'éléments.
        """
        if not element_matches:
            return 0.0
        
        # Moyenne pondérée par la confiance
        total_score = 0.0
        total_weight = 0.0
        
        for match in element_matches:
            weight = match.confidence
            total_score += match.similarity_score * weight
            total_weight += weight
        
        if total_weight > 0:
            return total_score / total_weight
        else:
            return 0.0
    
    def _compute_match_confidence(
        self,
        screen_similarity: float,
        elements_score: float,
        element_matches: List[ElementMatch]
    ) -> float:
        """
        Calcule la confiance globale du match.
        """
        # Facteurs de confiance
        base_confidence = (screen_similarity + elements_score) / 2
        
        # Bonus pour nombre d'éléments matchés
        elements_bonus = min(len(element_matches) * 0.1, 0.3)
        
        # Bonus pour matches exacts
        exact_matches = len([m for m in element_matches if m.match_type == "exact"])
        exact_bonus = min(exact_matches * 0.05, 0.2)
        
        confidence = base_confidence + elements_bonus + exact_bonus
        return min(confidence, 1.0)
    
    def _load_all_workflows(self) -> List:
        """
        Charge tous les workflows disponibles.
        Pour l'instant, retourne une liste vide.
        TODO: Intégrer avec le système de workflows existant.
        """
        # Placeholder - à intégrer avec le WorkflowDetector existant
        return []
    
    def _generate_match_feedback(
        self,
        screen_state: EnrichedScreenState,
        workflow: Any,
        screen_similarity: float,
        element_matches: List[ElementMatch],
        composite_score: float
    ) -> List[MatchDifference]:
        """
        Génère un feedback détaillé sur les différences détectées.
        
        Args:
            screen_state: État d'écran actuel
            workflow: Workflow comparé
            screen_similarity: Score de similarité d'écran
            element_matches: Matches d'éléments trouvés
            composite_score: Score composite final
            
        Returns:
            Liste des différences détectées
        """
        differences = []
        
        try:
            # 1. Vérifier la similarité d'écran
            if screen_similarity < 0.7:
                severity = "critical" if screen_similarity < 0.5 else "major"
                differences.append(MatchDifference(
                    difference_type="low_similarity",
                    severity=severity,
                    description=f"Similarité d'écran faible: {screen_similarity:.2f}",
                    expected="≥ 0.70",
                    actual=f"{screen_similarity:.2f}",
                    suggestion="L'écran actuel semble très différent du workflow attendu. Vérifiez que vous êtes sur la bonne application/fenêtre."
                ))
            
            # 2. Vérifier les éléments manquants
            if hasattr(workflow, 'steps') and workflow.steps:
                expected_elements = len(workflow.steps)
                matched_elements = len([m for m in element_matches if m.match_type in ["exact", "similar"]])
                
                if matched_elements < expected_elements:
                    missing_count = expected_elements - matched_elements
                    severity = "critical" if missing_count > expected_elements / 2 else "major"
                    differences.append(MatchDifference(
                        difference_type="missing_element",
                        severity=severity,
                        description=f"{missing_count} élément(s) requis manquant(s)",
                        expected=f"{expected_elements} éléments",
                        actual=f"{matched_elements} éléments trouvés",
                        suggestion=f"Vérifiez que tous les éléments UI sont visibles à l'écran. Éléments manquants: {missing_count}"
                    ))
            
            # 3. Vérifier les matches partiels
            partial_matches = [m for m in element_matches if m.match_type == "partial"]
            if partial_matches:
                for match in partial_matches:
                    differences.append(MatchDifference(
                        difference_type="low_similarity",
                        severity="minor",
                        description=f"Élément '{match.ui_element.label}' partiellement correspondant",
                        expected="Match exact ou similaire",
                        actual=f"Score: {match.similarity_score:.2f}",
                        suggestion="L'élément existe mais ne correspond pas parfaitement (texte différent ou position décalée)"
                    ))
            
            # 4. Vérifier les types d'éléments incorrects
            for match in element_matches:
                # Vérifier si le type d'élément est cohérent avec l'action attendue
                # (Cette logique pourrait être améliorée avec plus d'informations du workflow)
                if match.confidence < 0.5:
                    differences.append(MatchDifference(
                        difference_type="wrong_type",
                        severity="major",
                        description=f"Type d'élément incertain pour '{match.ui_element.label}'",
                        expected="Confiance ≥ 0.50",
                        actual=f"Confiance: {match.confidence:.2f}",
                        suggestion="L'élément détecté pourrait ne pas être du bon type pour l'action attendue"
                    ))
            
            # 5. Vérifier le score composite global
            if composite_score < 0.5:
                differences.append(MatchDifference(
                    difference_type="low_similarity",
                    severity="critical",
                    description=f"Score composite très faible: {composite_score:.2f}",
                    expected="≥ 0.50",
                    actual=f"{composite_score:.2f}",
                    suggestion="Le workflow ne correspond pas à l'écran actuel. Considérez un workflow différent ou vérifiez l'état de l'application."
                ))
            elif composite_score < 0.7:
                differences.append(MatchDifference(
                    difference_type="low_similarity",
                    severity="major",
                    description=f"Score composite modéré: {composite_score:.2f}",
                    expected="≥ 0.70",
                    actual=f"{composite_score:.2f}",
                    suggestion="Le match est acceptable mais pas optimal. Certains éléments peuvent être différents."
                ))
            
            if self.logger and differences:
                self.logger.log_action({
                    "action": "match_feedback_generated",
                    "workflow_id": getattr(workflow, 'workflow_id', 'unknown'),
                    "differences_count": len(differences),
                    "critical": len([d for d in differences if d.severity == "critical"]),
                    "major": len([d for d in differences if d.severity == "major"]),
                    "minor": len([d for d in differences if d.severity == "minor"])
                })
            
            return differences
        
        except Exception as e:
            if self.logger:
                self.logger.log_action({
                    "action": "feedback_generation_error",
                    "workflow_id": getattr(workflow, 'workflow_id', 'unknown'),
                    "error": str(e)
                })
            return []
    
    def get_match_explanation(
        self,
        match: WorkflowMatch
    ) -> Dict[str, Any]:
        """
        Génère une explication détaillée d'un match.
        
        Args:
            match: WorkflowMatch à expliquer
            
        Returns:
            Dictionnaire avec l'explication détaillée
        """
        explanation = {
            "workflow_info": {
                "id": match.workflow_id,
                "name": match.workflow_name
            },
            "scores": {
                "composite_score": match.composite_score,
                "screen_similarity": match.screen_similarity,
                "confidence": match.confidence
            },
            "element_analysis": {
                "total_matches": len(match.element_matches),
                "exact_matches": len([m for m in match.element_matches if m.match_type == "exact"]),
                "similar_matches": len([m for m in match.element_matches if m.match_type == "similar"]),
                "partial_matches": len([m for m in match.element_matches if m.match_type == "partial"])
            },
            "top_element_matches": [
                {
                    "ui_element": m.ui_element.label,
                    "similarity": m.similarity_score,
                    "type": m.match_type
                }
                for m in sorted(match.element_matches, key=lambda x: x.similarity_score, reverse=True)[:5]
            ],
            "match_details": match.match_details
        }
        
        return explanation


if __name__ == "__main__":
    # Tests basiques
    from .logger import Logger
    from .multimodal_embedding_manager import MultiModalEmbeddingManager
    import shutil
    
    print("EnhancedWorkflowMatcher - Tests basiques")
    print("=" * 50)
    
    # Test EnhancedWorkflowMatcher
    print("\n1. Test EnhancedWorkflowMatcher:")
    logger = Logger(log_dir="test_logs")
    multimodal_manager = MultiModalEmbeddingManager(logger=logger, data_dir="test_data")
    
    matcher = EnhancedWorkflowMatcher(
        multimodal_manager=multimodal_manager,
        logger=logger,
        config={
            "screen_weight": 0.6,
            "elements_weight": 0.4,
            "min_similarity_threshold": 0.3
        }
    )
    
    print(f"   Matcher créé")
    print(f"   Screen weight: {matcher.screen_weight}")
    print(f"   Elements weight: {matcher.elements_weight}")
    print(f"   Min threshold: {matcher.min_similarity_threshold}")
    
    print("\n✓ Tous les tests basiques réussis!")
    
    # Nettoyage
    if Path("test_data").exists():
        shutil.rmtree("test_data")
    if Path("test_logs").exists():
        shutil.rmtree("test_logs")
