"""
Module d'analyse des configurations backend pour Web Sentinel.
Détecte les configurations de sécurité non visibles dans les réponses HTTP.
Version corrigée avec localisation complète.
"""

from __future__ import annotations

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

import requests

from ..model import Finding, ScanRequest

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

# Endpoints d'information communs
INFO_ENDPOINTS = [
    '/.well-known/security.txt',
    '/robots.txt',
    '/sitemap.xml',
    '/health',
    '/status',
    '/info',
    '/actuator/health',  # Spring Boot
    '/api/health',
    '/.env',  # Fichier de configuration (ne devrait pas être accessible)
    '/package.json',  # Node.js (ne devrait pas être accessible)
]

# Endpoints typiques des environnements de développement
DEV_ENDPOINTS = [
    '/debug',
    '/test',
    '/dev',
    '/swagger-ui',
    '/api-docs',
    '/phpmyadmin',
    '/adminer',
    '/__debug__',
    '/telescope',  # Laravel Telescope
]


def evaluate_backend_configuration(request: ScanRequest) -> Iterable[Finding]:
    """
    Analyse les configurations de sécurité backend via les endpoints d'information
    et les patterns de configuration accessibles publiquement.
    """
    findings: List[Finding] = []
    
    if not request.allow_invasive:
        findings.append(
            Finding(
                check="backend-config",
                title="Backend analysis requires invasive mode",
                severity="info",
                description="Backend configuration analysis requires --allow-invasive flag for enhanced detection.",
                remediation="Run scan with --allow-invasive if you have legitimate access to the application.",
                impact="Limited to HTTP response analysis only.",
                i18n_key="backend.analysis_requires_invasive",
            )
        )
        return findings
    
    # Analyse des endpoints publics d'information
    findings.extend(_analyze_public_endpoints(request))
    
    # Analyse des pages d'erreur
    findings.extend(_analyze_error_pages(request))
    
    # Détection d'outils de développement
    findings.extend(_analyze_development_indicators(request))
    
    return findings


def _analyze_public_endpoints(request: ScanRequest) -> List[Finding]:
    """
    Analyse les endpoints publics qui peuvent révéler des informations de configuration.
    """
    findings: List[Finding] = []
    base_url = f"https://{request.domain}"
    
    for endpoint in INFO_ENDPOINTS:
        url = urljoin(base_url, endpoint)
        try:
            response = requests.get(
                url,
                headers={"User-Agent": request.user_agent},
                timeout=request.timeout
            )
            
            if response.status_code == 200:
                if endpoint == '/.well-known/security.txt':
                    findings.append(
                        Finding(
                            check="backend-config",
                            title="Security.txt found",
                            severity="info",
                            description=f"Security policy information available at {endpoint}",
                            remediation="Review security.txt for contact information and policies.",
                            evidence=f"Accessible at: {url}",
                            i18n_key="backend.security_txt_found",
                            i18n_params={"endpoint": endpoint, "url": url}
                        )
                    )
                
                elif endpoint in ['/.env', '/package.json']:
                    findings.append(
                        Finding(
                            check="backend-config",
                            title="Sensitive configuration file exposed",
                            severity="high",
                            description=f"Configuration file {endpoint} is publicly accessible",
                            remediation="Restrict access to configuration files via web server configuration.",
                            evidence=f"Accessible at: {url}",
                            impact="Configuration files may contain sensitive information.",
                            i18n_key="backend.config_file_exposed",
                            i18n_params={"endpoint": endpoint, "url": url}
                        )
                    )
                
                elif '/actuator/' in endpoint:
                    content = response.text.lower()
                    if '"diskspace"' in content or '"db"' in content:
                        findings.append(
                            Finding(
                                check="backend-config",
                                title="Detailed health endpoint exposed",
                                severity="medium",
                                description="Spring Boot Actuator health endpoint reveals internal system details",
                                remediation="Configure management.endpoint.health.show-details=when-authorized",
                                evidence=f"Detailed health info at: {url}",
                                impact="Internal system information may aid in reconnaissance.",
                                i18n_key="backend.actuator_details_exposed",
                                i18n_params={"url": url}
                            )
                        )
                    
        except requests.RequestException:
            continue
    
    return findings


def _analyze_error_pages(request: ScanRequest) -> List[Finding]:
    """
    Analyse les pages d'erreur pour détecter des fuites d'information sur la configuration.
    """
    findings: List[Finding] = []
    base_url = f"https://{request.domain}"
    
    # Test d'endpoints inexistants pour déclencher des pages d'erreur
    test_endpoints = [
        '/nonexistent-page-12345',
        '/admin/nonexistent',
        '/api/nonexistent',
    ]
    
    for endpoint in test_endpoints:
        url = urljoin(base_url, endpoint)
        try:
            response = requests.get(
                url,
                headers={"User-Agent": request.user_agent},
                timeout=request.timeout
            )
            
            if response.status_code in [404, 500]:
                content = response.text.lower()
                
                # Détection d'informations sensibles dans les erreurs
                if any(pattern in content for pattern in ['stack trace', 'exception', 'debug']):
                    findings.append(
                        Finding(
                            check="backend-config",
                            title="Verbose error pages detected",
                            severity="medium",
                            description="Error pages reveal stack traces or debug information",
                            remediation="Configure custom error pages and disable debug mode in production.",
                            evidence=f"Verbose error at: {url}",
                            impact="Debug information may reveal application structure and vulnerabilities.",
                            i18n_key="backend.verbose_error_pages",
                            i18n_params={"url": url}
                        )
                    )
                    break  # Une seule détection suffit
                    
        except requests.RequestException:
            continue
    
    return findings


def _analyze_development_indicators(request: ScanRequest) -> List[Finding]:
    """
    Détecte les indicateurs suggérant un environnement de développement en production.
    """
    findings: List[Finding] = []
    base_url = f"https://{request.domain}"
    
    for endpoint in DEV_ENDPOINTS:
        url = urljoin(base_url, endpoint)
        try:
            response = requests.get(
                url,
                headers={"User-Agent": request.user_agent},
                timeout=request.timeout
            )
            
            if response.status_code == 200:
                findings.append(
                    Finding(
                        check="backend-config",
                        title="Development tool accessible in production",
                        severity="high",
                        description=f"Development endpoint {endpoint} is accessible in production",
                        remediation="Disable development tools and debug interfaces in production environment.",
                        evidence=f"Accessible at: {url}",
                        impact="Development tools may expose sensitive application data and functionality.",
                        i18n_key="backend.dev_tool_accessible",
                        i18n_params={"endpoint": endpoint, "url": url}
                    )
                )
                
        except requests.RequestException:
            continue
    
    return findings