"""
Analyseur de frameworks pour les projets
"""
import re
from typing import Dict, List, Any
from pathlib import Path

from ..core.patterns import FRAMEWORK_PATTERNS
from ...monitoring.logger import logger


class FrameworkAnalyzer:
    """Analyseur pour détecter les frameworks utilisés dans un projet"""
    
    def __init__(self):
        self.patterns = FRAMEWORK_PATTERNS
    
    def detect(self, file_contents: Dict[str, str]) -> List[Dict[str, Any]]:
        """
        Détecte les frameworks présents dans le projet
        
        Args:
            file_contents: Dictionnaire {chemin_fichier: contenu}
            
        Returns:
            Liste des frameworks détectés avec leur confiance
        """
        detected_frameworks = []
        logger('info', f"Analyse des frameworks possibles dans {len(file_contents)} fichiers...")
        
        key_files = self._get_key_files(file_contents)
        logger('info', f"Fichiers clés trouvés: {key_files}")
        
        for framework_name, pattern_data in self.patterns.items():
            logger('info', f"Vérification de {framework_name}...")
            confidence = self._calculate_confidence(framework_name, pattern_data, file_contents)
            
            if confidence >= 50:
                framework_info = {
                    "name": framework_name,
                    "parent_stack_type": pattern_data.get("parent_stack_type", "unknown"),
                    "confidence": confidence
                }
                detected_frameworks.append(framework_info)
                logger('info', f"Framework {framework_name} détecté avec une confiance de {confidence}%")
            else:
                logger('info', f"Framework {framework_name} détecté avec une confiance de {confidence}%")

        # Trier par confiance décroissante
        detected_frameworks.sort(key=lambda x: x.get('confidence', 0), reverse=True)
        
        if detected_frameworks:
            framework_names = [f['name'] for f in detected_frameworks]
            logger('info', f"Frameworks détectés: {framework_names}")
        else:
            logger('warning', "Aucun framework détecté dans le projet.")
            detected_frameworks = self._check_fallback_detection(file_contents)
        
        return detected_frameworks
    
    def _calculate_confidence(self, framework_name: str, pattern_data: Dict, file_contents: Dict[str, str]) -> int:
        """Calcule le niveau de confiance pour un framework"""
        confidence = 0
        weights = pattern_data.get('confidence_weights', {
            'files': 50,
            'content_patterns': 40,
            'optional_files': 10
        })
        
        # Vérifier les fichiers requis
        if 'files' in pattern_data and pattern_data['files']:
            if self._check_required_files(pattern_data['files'], file_contents):
                confidence += weights.get('files', 50)
                logger('success', f"Fichiers requis présents pour {framework_name} (+{weights.get('files', 50)}%)")
        
        # Vérifier les patterns de contenu
        content_matches = self._check_content_patterns(pattern_data.get('content_patterns', {}), file_contents)
        if content_matches:
            confidence += weights.get('content_patterns', 40)
            logger('success', f"Patterns trouvés: {content_matches[:2]} (+{weights.get('content_patterns', 40)}%)")
        
        # Vérifier les fichiers optionnels
        if self._check_optional_files(pattern_data.get('optional_files', []), file_contents):
            confidence += weights.get('optional_files', 10)
            logger('success', f"Fichiers optionnels trouvés pour {framework_name} (+{weights.get('optional_files', 10)}%)")
        
        return min(confidence, 100)  # Limiter à 100%
    
    def _check_required_files(self, required_files: List[str], file_contents: Dict[str, str]) -> bool:
        """Vérifie la présence des fichiers requis"""
        for required_file in required_files:
            file_exists = any(
                file_path.endswith('/' + required_file) or file_path == required_file 
                for file_path in file_contents.keys()
            )
            if not file_exists:
                return False
        return True
    
    def _check_content_patterns(self, content_patterns: Dict[str, List[str]], file_contents: Dict[str, str]) -> List[str]:
        """Vérifie les patterns de contenu"""
        pattern_matches = []
        
        for file_glob, regex_patterns in content_patterns.items():
            matching_files = self._find_matching_files(file_glob, file_contents)
            
            for file_path in matching_files:
                content = file_contents.get(file_path, '')
                if content and not content.startswith('__'):
                    for regex_pattern in regex_patterns:
                        if re.search(regex_pattern, content, re.IGNORECASE | re.MULTILINE):
                            pattern_matches.append(f"{file_path} contient pattern: {regex_pattern}")
                            break
                    if pattern_matches:
                        break
            if pattern_matches:
                break
        
        return pattern_matches
    
    def _check_optional_files(self, optional_files: List[str], file_contents: Dict[str, str]) -> bool:
        """Vérifie la présence de fichiers optionnels"""
        for optional_file in optional_files:
            file_exists = any(
                file_path.endswith('/' + optional_file) or file_path == optional_file 
                for file_path in file_contents.keys()
            )
            if file_exists:
                logger('success', f"Fichier optionnel trouvé: {optional_file}")
                return True
        return False
    
    def _find_matching_files(self, file_glob: str, file_contents: Dict[str, str]) -> List[str]:
        """Trouve les fichiers correspondant au pattern glob"""
        if file_glob.startswith('*'):
            suffix = file_glob[1:]
            return [path for path in file_contents.keys() if path.endswith(suffix)]
        else:
            return [path for path in file_contents.keys() if path.endswith('/' + file_glob) or path == file_glob]
    
    def _get_key_files(self, file_contents: Dict[str, str]) -> List[str]:
        """Retourne la liste des fichiers clés trouvés"""
        key_files = ['manage.py', 'requirements.txt', 'pyproject.toml', 'package.json', 'composer.json']
        return [
            Path(file_path).name for file_path in file_contents.keys() 
            if Path(file_path).name in key_files
        ]
    
    def _check_fallback_detection(self, file_contents: Dict[str, str]) -> List[Dict[str, Any]]:
        """Détection de secours pour certains cas spéciaux"""
        fallback_frameworks = []
        
        # Détection Django de secours
        manage_py_files = [path for path in file_contents.keys() if path.endswith('manage.py')]
        if manage_py_files:
            logger('info', "manage.py trouvé mais pas les dépendances Django - est-ce un projet Django mal configuré?")
            fallback_frameworks.append({
                "name": "django",
                "parent_stack_type": "python",
                "confidence": 40,
                "note": "manage.py trouvé mais pas les dépendances Django standard"
            })
        
        return fallback_frameworks