"""
Module d'analyse des technologies web modernes pour Web Sentinel.
Détecte les frameworks SPA, PWA, et leurs configurations de sécurité.
Version simplifiée avec localisation complète.
"""

from __future__ import annotations

import json
import logging
import re
from typing import Iterable, List
from urllib.parse import urljoin

import requests

from ..localization.helpers import create_translated_finding
from ..model import Finding, ScanRequest

LOGGER = logging.getLogger("web_sentinel.checks.modern_web")

# Signatures de frameworks JavaScript modernes
FRAMEWORK_SIGNATURES = {
    'react': [
        r'react\.development\.js',
        r'react\.production\.min\.js',
        r'data-react',
        r'__REACT_DEVTOOLS_GLOBAL_HOOK__',
    ],
    'vue': [
        r'vue\.js',
        r'vue\.min\.js',
        r'data-v-',
        r'__VUE__',
    ],
    'angular': [
        r'angular\.js',
        r'angular\.min\.js',
        r'ng-',
        r'data-ng-',
    ],
}

# Fichiers de configuration à vérifier
CONFIG_FILES = [
    'manifest.json',        # PWA manifest
    'sw.js',               # Service Worker
    'service-worker.js',   # Service Worker alternatif
]


def evaluate_modern_web_technologies(request: ScanRequest) -> Iterable[Finding]:
    """
    Analyse les technologies web modernes et leurs configurations de sécurité.
    """
    findings: List[Finding] = []
    base_url = f"https://{request.domain}"
    
    # Analyse de la page principale
    try:
        response = requests.get(
            base_url,
            headers={"User-Agent": request.user_agent},
            timeout=request.timeout,
            allow_redirects=True
        )
        
        findings.extend(_detect_frameworks(response))
        findings.extend(_check_spa_security(response))
        
    except requests.RequestException as exc:
        findings.append(
            create_translated_finding(
                check="modern-web",
                i18n_key="modern.analysis_failed",
                severity="medium",
                i18n_params={"error": str(exc), "url": base_url},
                evidence=f"URL: {base_url}"
            )
        )
        return findings
    
    # Analyse des fichiers de configuration
    findings.extend(_analyze_config_files(request))
    
    return findings


def _detect_frameworks(response: requests.Response) -> List[Finding]:
    """
    Détecte les frameworks JavaScript utilisés.
    """
    findings: List[Finding] = []
    content = response.text.lower()
    detected_frameworks = []
    
    for framework, signatures in FRAMEWORK_SIGNATURES.items():
        for signature in signatures:
            if re.search(signature, content, re.IGNORECASE):
                detected_frameworks.append(framework)
                break
    
    if detected_frameworks:
        frameworks_str = ', '.join(detected_frameworks)
        findings.append(
            create_translated_finding(
                check="modern-web",
                i18n_key="modern.frameworks_detected",
                severity="info",
                i18n_params={"frameworks": frameworks_str},
                evidence=f"Frameworks: {frameworks_str}"
            )
        )
        
        # Vérifications spécifiques aux frameworks
        if 'react' in detected_frameworks and 'react.development.js' in content:
            findings.append(
                create_translated_finding(
                    check="modern-web",
                    i18n_key="modern.react_dev_build",
                    severity="medium",
                    evidence="react.development.js found in page"
                )
            )
    
    return findings


def _check_spa_security(response: requests.Response) -> List[Finding]:
    """
    Vérifications de sécurité spécifiques aux Single Page Applications.
    """
    findings: List[Finding] = []
    content = response.text
    
    # Vérification des tokens/clés exposés dans le code client
    sensitive_patterns = {
        'api key': r'["\']?api[_-]?key["\']?\s*[:=]\s*["\'][^"\']{16,}["\']',
        'secret': r'["\']?secret["\']?\s*[:=]\s*["\'][^"\']{16,}["\']',
        'token': r'["\']?token["\']?\s*[:=]\s*["\'][^"\']{20,}["\']',
    }
    
    for pattern_name, pattern in sensitive_patterns.items():
        matches = re.findall(pattern, content, re.IGNORECASE)
        if matches:
            findings.append(
                create_translated_finding(
                    check="modern-web",
                    i18n_key="modern.credentials_exposed",
                    severity="high",
                    i18n_params={"pattern_name": pattern_name, "count": len(matches)},
                    evidence=f"Found {len(matches)} potential matches"
                )
            )
    
    return findings


def _analyze_config_files(request: ScanRequest) -> List[Finding]:
    """
    Analyse les fichiers de configuration modernes.
    """
    findings: List[Finding] = []
    base_url = f"https://{request.domain}"
    
    # Vérification du manifest PWA
    manifest_url = urljoin(base_url, 'manifest.json')
    try:
        response = requests.get(
            manifest_url,
            headers={"User-Agent": request.user_agent},
            timeout=request.timeout
        )
        
        if response.status_code == 200:
            findings.append(
                create_translated_finding(
                    check="modern-web",
                    i18n_key="modern.pwa_detected",
                    severity="info",
                    i18n_params={"url": manifest_url},
                    evidence=f"Manifest available at: {manifest_url}"
                )
            )
            
            # Analyse du contenu du manifest
            try:
                manifest = response.json()
                scope = manifest.get('scope', '')
                
                # Vérification du scope trop permissif
                if scope == '/' or not scope:
                    findings.append(
                        create_translated_finding(
                            check="modern-web",
                            i18n_key="modern.pwa_scope_permissive",
                            severity="medium",
                            i18n_params={"scope": scope},
                            evidence=f"Scope: '{scope}'"
                        )
                    )
            except (json.JSONDecodeError, ValueError):
                findings.append(
                    create_translated_finding(
                        check="modern-web",
                        i18n_key="modern.pwa_invalid_manifest",
                        severity="low",
                        evidence="JSON parsing failed"
                    )
                )
        
    except requests.RequestException:
        pass
    
    return findings
