"""
Script de compilation Web Sentinel - Version optimisée
====================================================

Ce script compile Web Sentinel en un exécutable Windows (.exe) optimisé
avec toutes les dépendances et corrections récentes incluses.
"""

import os
import sys
import subprocess
import shutil
from pathlib import Path
import time

def banner():
    """Affiche la bannière de compilation."""
    print("🛡️  WEB SENTINEL - COMPILATEUR OPTIMISÉ")
    print("="*60)
    print("🔐 Scanner de sécurité web avec modules OWASP Top 10 2021")
    print("📦 Compilation en exécutable Windows (.exe)")
    print("="*60)

def check_dependencies():
    """Vérifie toutes les dépendances nécessaires."""
    print("\n📋 Vérification des dépendances...")
    
    dependencies = {
        'PyInstaller': 'pyinstaller',
        'Requests': 'requests', 
        'BeautifulSoup4': 'bs4',
        'Pillow': 'PIL',
        'TKinter': 'tkinter'
    }
    
    missing = []
    for name, module in dependencies.items():
        try:
            __import__(module)
            print(f"✅ {name}: Disponible")
        except ImportError:
            print(f"❌ {name}: Manquant")
            missing.append(name)
    
    if missing:
        print(f"\n⚠️  Dépendances manquantes: {', '.join(missing)}")
        install = input("Installer automatiquement ? (o/N): ")
        if install.lower() in ['o', 'oui', 'y', 'yes']:
            return install_missing_dependencies(missing)
        return False
    
    print("✅ Toutes les dépendances sont disponibles")
    return True

def install_missing_dependencies(missing):
    """Installe les dépendances manquantes."""
    packages = {
        'PyInstaller': 'pyinstaller',
        'Requests': 'requests',
        'BeautifulSoup4': 'beautifulsoup4',
        'Pillow': 'Pillow'
    }
    
    for dep in missing:
        if dep in packages:
            print(f"📦 Installation de {dep}...")
            try:
                subprocess.run([sys.executable, "-m", "pip", "install", packages[dep]], 
                             check=True, capture_output=True)
                print(f"✅ {dep} installé")
            except subprocess.CalledProcessError as e:
                print(f"❌ Erreur installation {dep}: {e}")
                return False
    return True

def clean_build_environment():
    """Nettoie l'environnement de build."""
    print("\n🧹 Nettoyage de l'environnement de build...")
    
    dirs_to_clean = ["build", "dist", "__pycache__"]
    for dir_name in dirs_to_clean:
        if os.path.exists(dir_name):
            print(f"   🗑️  {dir_name}/")
            shutil.rmtree(dir_name)
    
    # Nettoyer les fichiers .spec
    for spec_file in Path(".").glob("*.spec"):
        print(f"   🗑️  {spec_file}")
        spec_file.unlink()
    
    print("✅ Nettoyage terminé")

def compile_optimized_exe():
    """Compile l'exécutable avec les paramètres optimisés."""
    print("\n🚀 Compilation de Web Sentinel (version optimisée)...")
    
    # Paramètres PyInstaller optimisés
    cmd = [
        sys.executable, "-m", "PyInstaller",
        "--onefile",                                    # Un seul fichier
        "--windowed",                                   # Interface graphique
        "--name=WebSentinel",                           # Nom de l'exécutable
        "--distpath=dist",                              # Dossier de sortie
        "--workpath=build",                             # Dossier de travail
        
        # Données et ressources
        "--add-data=web_sentinel;web_sentinel",        # Package principal
        "--add-data=assets;assets",                     # Ressources
        
        # Imports cachés (modules OWASP + dépendances)
        "--hidden-import=tkinter",
        "--hidden-import=tkinter.ttk", 
        "--hidden-import=requests",
        "--hidden-import=ssl",
        "--hidden-import=socket",
        "--hidden-import=concurrent.futures",
        "--hidden-import=threading",
        "--hidden-import=json",
        "--hidden-import=datetime",
        "--hidden-import=pathlib",
        "--hidden-import=urllib.parse",
        "--hidden-import=base64",
        "--hidden-import=hashlib",
        "--hidden-import=hmac",
        
        # Modules Web Sentinel spécifiques
        "--hidden-import=web_sentinel.orchestrator",
        "--hidden-import=web_sentinel.scanner", 
        "--hidden-import=web_sentinel.checks.owasp_security_modules",
        "--hidden-import=web_sentinel.checks.headers",
        "--hidden-import=web_sentinel.checks.tls",
        "--hidden-import=web_sentinel.checks.injection",
        "--hidden-import=web_sentinel.checks.static_analysis",
        "--hidden-import=web_sentinel.checks.osint",
        "--hidden-import=web_sentinel.checks.third_party",
        "--hidden-import=web_sentinel.gui.modern_tabbed_window",
        "--hidden-import=web_sentinel.gui.i18n",
        
        # Options d'optimisation
        "--optimize=2",                                 # Optimisation bytecode
        "--strip",                                      # Suppression symboles debug
        
        # Script principal
        "launch_web_sentinel.py"                        # Point d'entrée optimisé
    ]
    
    # Ajouter l'icône si disponible
    icon_paths = ["assets/icon.ico", "web_sentinel/gui/icon.ico", "resources/icon.ico"]
    for icon_path in icon_paths:
        if os.path.exists(icon_path):
            cmd.insert(-1, f"--icon={icon_path}")
            print(f"🎨 Icône trouvée: {icon_path}")
            break
    
    print("📋 Commande de compilation:")
    print(f"   {' '.join(cmd[:8])} ...")
    
    try:
        print("\n⏳ Compilation en cours (cela peut prendre quelques minutes)...")
        start_time = time.time()
        
        result = subprocess.run(cmd, check=True, capture_output=True, text=True)
        
        end_time = time.time()
        duration = end_time - start_time
        
        print(f"✅ Compilation terminée en {duration:.1f} secondes")
        return True
        
    except subprocess.CalledProcessError as e:
        print(f"❌ Erreur de compilation: {e}")
        if e.stdout:
            print(f"STDOUT: {e.stdout}")
        if e.stderr:
            print(f"STDERR: {e.stderr}")
        return False

def validate_executable():
    """Valide l'exécutable créé."""
    print("\n🔍 Validation de l'exécutable...")
    
    exe_path = Path("dist/WebSentinel.exe")
    if not exe_path.exists():
        print("❌ Exécutable non trouvé dans dist/")
        return False
    
    # Informations sur le fichier
    exe_size = exe_path.stat().st_size
    exe_size_mb = exe_size / (1024 * 1024)
    mod_time = time.ctime(exe_path.stat().st_mtime)
    
    print(f"📄 Fichier: {exe_path}")
    print(f"📏 Taille: {exe_size_mb:.2f} MB")
    print(f"🕒 Modifié: {mod_time}")
    
    # Test basique de lancement (sans GUI)
    print("🧪 Test de démarrage...")
    try:
        # Test très rapide pour vérifier que l'exe se lance
        result = subprocess.run([str(exe_path), "--help"], 
                              capture_output=True, text=True, timeout=30)
        if result.returncode == 0 or "Web Sentinel" in result.stdout:
            print("✅ L'exécutable semble fonctionnel")
        else:
            print("⚠️  L'exécutable démarre mais avec des avertissements")
    except subprocess.TimeoutExpired:
        print("⚠️  Test de démarrage en cours (normal pour GUI)")
    except Exception as e:
        print(f"⚠️  Impossible de tester: {e}")
    
    return True

def create_distribution_package():
    """Crée un package de distribution."""
    print("\n📦 Création du package de distribution...")
    
    # Créer dossier de distribution
    dist_folder = Path("WebSentinel_Distribution")
    if dist_folder.exists():
        shutil.rmtree(dist_folder)
    
    dist_folder.mkdir()
    
    # Copier l'exécutable
    shutil.copy2("dist/WebSentinel.exe", dist_folder / "WebSentinel.exe")
    
    # Créer un README pour l'utilisateur final
    readme_content = """🛡️ WEB SENTINEL - Scanner de Sécurité Web
================================================

VERSION: OWASP Top 10 2021 Edition
COMPILATION: {date}

📋 CONTENU:
- WebSentinel.exe : Application principale

🚀 UTILISATION:
1. Double-cliquez sur WebSentinel.exe
2. L'interface graphique moderne se lance automatiquement
3. Sélectionnez l'onglet "Scan de Domaine" ou "Code Source (SAST)"
4. Configurez vos paramètres et lancez un scan

🔐 FONCTIONNALITÉS:
✅ 16 modules de sécurité (6 OWASP + 10 existants)
✅ Interface bilingue (français/anglais)
✅ Scan passif et invasif
✅ Rapports HTML et JSON
✅ Historique automatique des scans
✅ Analyse SAST (code source)

📞 SUPPORT:
- Documentation: README.md dans le projet source
- Issues: https://github.com/Taaazzz-prog/Web-Sentinel/issues

⚠️ IMPORTANT:
Utilisez uniquement sur des domaines que vous possédez ou 
pour lesquels vous avez une autorisation explicite.

© 2025 - Web Sentinel Project
""".format(date=time.strftime("%Y-%m-%d %H:%M:%S"))
    
    with open(dist_folder / "README.txt", "w", encoding="utf-8") as f:
        f.write(readme_content)
    
    # Copier la licence si elle existe
    if os.path.exists("LICENSE"):
        shutil.copy2("LICENSE", dist_folder / "LICENSE.txt")
    
    print(f"✅ Package créé dans: {dist_folder}/")
    return dist_folder

def main():
    """Point d'entrée principal."""
    banner()
    
    # Vérifier qu'on est dans le bon répertoire
    if not os.path.exists("web_sentinel"):
        print("❌ Erreur: Dossier 'web_sentinel' non trouvé")
        print("   Exécutez ce script depuis la racine du projet Web Sentinel")
        sys.exit(1)
    
    # Étapes de compilation
    steps = [
        ("Vérification des dépendances", check_dependencies),
        ("Nettoyage de l'environnement", clean_build_environment), 
        ("Compilation optimisée", compile_optimized_exe),
        ("Validation de l'exécutable", validate_executable),
        ("Création du package", create_distribution_package)
    ]
    
    for step_name, step_func in steps:
        print(f"\n🔄 {step_name}...")
        if not step_func():
            print(f"❌ Échec à l'étape: {step_name}")
            sys.exit(1)
    
    print("\n" + "="*60)
    print("🎉 COMPILATION RÉUSSIE !")
    print("="*60)
    print("📁 Fichiers créés:")
    print("   📄 dist/WebSentinel.exe (exécutable principal)")
    print("   📦 WebSentinel_Distribution/ (package complet)")
    print("\n🚀 Pour distribuer:")
    print("   • Partagez le dossier WebSentinel_Distribution/")
    print("   • Ou seulement dist/WebSentinel.exe")
    print("\n✅ Web Sentinel est prêt pour la distribution !")
    
    # Proposer de lancer
    launch = input("\n❓ Tester l'exécutable maintenant ? (o/N): ")
    if launch.lower() in ['o', 'oui', 'y', 'yes']:
        try:
            print("🚀 Lancement de Web Sentinel...")
            subprocess.Popen(["dist/WebSentinel.exe"])
            print("✅ Application lancée")
        except Exception as e:
            print(f"❌ Erreur de lancement: {e}")

if __name__ == "__main__":
    main()