"""
Contrôleur de scan pour les GUI
Gère la logique de scan indépendamment de l'interface
"""

import threading
from typing import List, Callable, Optional
from datetime import datetime
from pathlib import Path

from ....model import ScanRequest
from ....scanner import SentinelScanner
from ....reporting import HistoryStore, ReportEngine


class ScanController:
    """
    Contrôleur de scan réutilisable pour tous les GUI.
    Gère l'exécution des scans en arrière-plan et les callbacks.
    """
    
    def __init__(self):
        self.scanner = SentinelScanner()
        
        # Chemin par défaut pour l'historique
        history_path = Path.home() / ".web-sentinel" / "history.json"
        self.history_store = HistoryStore(history_path)
        
        self.is_scanning = False
        self.current_thread: Optional[threading.Thread] = None
        self.scan_results: List = []
        
        # Callbacks
        self.on_scan_start: Optional[Callable] = None
        self.on_scan_progress: Optional[Callable[[str], None]] = None
        self.on_scan_complete: Optional[Callable[[List], None]] = None
        self.on_scan_error: Optional[Callable[[str], None]] = None
    
    def start_scan(
        self,
        domains: List[str],
        modules: List[str],
        allow_invasive: bool = False,
        timeout: float = 5.0,
        use_history: bool = True
    ):
        """
        Lance un scan en arrière-plan.
        
        Args:
            domains: Liste des domaines à scanner
            modules: Liste des modules à activer
            allow_invasive: Autoriser les tests invasifs
            timeout: Timeout des requêtes en secondes
            use_history: Utiliser l'historique
        """
        if self.is_scanning:
            if self.on_scan_error:
                self.on_scan_error("Un scan est déjà en cours")
            return
        
        if not domains:
            if self.on_scan_error:
                self.on_scan_error("Aucun domaine spécifié")
            return
        
        # Marquer comme en cours
        self.is_scanning = True
        self.scan_results = []
        
        # Callback de démarrage
        if self.on_scan_start:
            self.on_scan_start()
        
        # Lancer le scan dans un thread
        self.current_thread = threading.Thread(
            target=self._run_scan,
            args=(domains, modules, allow_invasive, timeout, use_history),
            daemon=True
        )
        self.current_thread.start()
    
    def _run_scan(
        self,
        domains: List[str],
        modules: List[str],
        allow_invasive: bool,
        timeout: float,
        use_history: bool
    ):
        """Exécute le scan (appelé dans un thread séparé)."""
        try:
            all_findings = []
            
            for domain in domains:
                # Progression
                if self.on_scan_progress:
                    self.on_scan_progress(f"🔍 Scan de {domain}...")
                
                # Créer la requête de scan
                request = ScanRequest(
                    target=domain,
                    timeout=timeout,
                    allow_invasive=allow_invasive,
                    modules=modules
                )
                
                # Exécuter le scan
                findings = list(self.scanner.scan(request))
                all_findings.extend(findings)
                
                # Progression
                if self.on_scan_progress:
                    self.on_scan_progress(
                        f"✅ {domain}: {len(findings)} vulnérabilités détectées"
                    )
                
                # Sauvegarder dans l'historique
                if use_history:
                    try:
                        self.history_store.save_scan(domain, findings)
                    except Exception as e:
                        print(f"⚠️ Erreur sauvegarde historique: {e}")
            
            # Stocker les résultats
            self.scan_results = all_findings
            
            # Callback de complétion
            if self.on_scan_complete:
                self.on_scan_complete(all_findings)
        
        except Exception as e:
            # Callback d'erreur
            if self.on_scan_error:
                self.on_scan_error(f"Erreur pendant le scan: {str(e)}")
        
        finally:
            self.is_scanning = False
    
    def stop_scan(self):
        """Arrête le scan en cours (non implémenté - scan non interruptible pour l'instant)."""
        # Note: L'arrêt d'un scan en cours nécessiterait des modifications
        # dans le scanner pour supporter l'interruption
        pass
    
    def get_last_results(self) -> List:
        """Récupère les résultats du dernier scan."""
        return self.scan_results
    
    def export_results(self, filepath: str, format: str = "json"):
        """
        Exporte les résultats du dernier scan.
        
        Args:
            filepath: Chemin du fichier de sortie
            format: Format d'export ('json' ou 'html')
        """
        if not self.scan_results:
            raise ValueError("Aucun résultat à exporter")
        
        engine = ReportEngine()
        
        if format == "json":
            engine.export_json(self.scan_results, filepath)
        elif format == "html":
            engine.export_html(self.scan_results, filepath)
        else:
            raise ValueError(f"Format non supporté: {format}")
    
    def get_history(self, domain: str) -> List:
        """
        Récupère l'historique des scans pour un domaine.
        
        Args:
            domain: Nom du domaine
            
        Returns:
            Liste des scans passés
        """
        try:
            return self.history_store.get_history(domain)
        except Exception as e:
            print(f"⚠️ Erreur récupération historique: {e}")
            return []
    
    def clear_history(self, domain: Optional[str] = None):
        """
        Efface l'historique.
        
        Args:
            domain: Nom du domaine (None = tout l'historique)
        """
        try:
            if domain:
                # Effacer l'historique d'un domaine spécifique
                # (non implémenté dans HistoryStore actuel)
                pass
            else:
                # Effacer tout l'historique
                self.history_store = HistoryStore()
        except Exception as e:
            print(f"⚠️ Erreur effacement historique: {e}")
