<?php
// run_all_security_tests.php - Test de sécurité global de l'application
echo "🛡️ ===============================================\n";
echo "   AUDIT DE SÉCURITÉ COMPLET - KOMBAR FERD\n";
echo "===============================================\n\n";

$startTime = microtime(true);
$totalTests = 0;
$passedTests = 0;
$failedTests = 0;
$warnings = 0;

function runTest($testName, $callable) {
    global $totalTests, $passedTests, $failedTests, $warnings;
    
    echo "🔍 Test: $testName\n";
    $totalTests++;
    
    try {
        $result = $callable();
        if ($result === true) {
            echo "   ✅ PASSÉ\n";
            $passedTests++;
        } elseif ($result === 'warning') {
            echo "   ⚠️ AVERTISSEMENT\n";
            $warnings++;
        } else {
            echo "   ❌ ÉCHOUÉ: $result\n";
            $failedTests++;
        }
    } catch (Exception $e) {
        echo "   ❌ ERREUR: " . $e->getMessage() . "\n";
        $failedTests++;
    }
    
    echo "\n";
}

// ===== TESTS DE CONFIGURATION =====
echo "📋 TESTS DE CONFIGURATION\n";
echo "─────────────────────────────────────────\n";

runTest("Fichier .env existe", function() {
    return file_exists('.env') ? true : "Fichier .env manquant";
});

runTest("Variables d'environnement chargées", function() {
    require_once 'EnvLoader.php';
    EnvLoader::load();
    $required = ['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASS', 'JWT_SECRET'];
    foreach ($required as $var) {
        if (!EnvLoader::get($var)) {
            return "Variable $var manquante";
        }
    }
    return true;
});

runTest("JWT Secret sécurisé", function() {
    require_once 'EnvLoader.php';
    EnvLoader::load();
    $secret = EnvLoader::get('JWT_SECRET');
    if (strlen($secret) < 32) {
        return "JWT_SECRET trop court (minimum 32 caractères)";
    }
    if ($secret === 'your-super-secret-jwt-key-change-this-in-production') {
        return "JWT_SECRET par défaut non changé";
    }
    return true;
});

runTest("Fichier .gitignore protège .env", function() {
    if (!file_exists('.gitignore')) {
        return ".gitignore manquant";
    }
    $gitignore = file_get_contents('.gitignore');
    return strpos($gitignore, '.env') !== false ? true : ".env non protégé par .gitignore";
});

// ===== TESTS JWT =====
echo "🔐 TESTS SYSTÈME JWT\n";
echo "─────────────────────────────────────────\n";

runTest("Création de token JWT", function() {
    require_once 'config.php';
    require_once 'JwtManager.php';
    
    $payload = ['user_id' => 1, 'username' => 'test'];
    $token = JwtManager::createToken($payload);
    
    return !empty($token) && count(explode('.', $token)) === 3 ? true : "Token JWT mal formé";
});

runTest("Vérification de token JWT", function() {
    require_once 'config.php';
    require_once 'JwtManager.php';
    
    $payload = ['user_id' => 1, 'username' => 'test'];
    $token = JwtManager::createToken($payload);
    $decoded = JwtManager::verifyToken($token);
    
    return $decoded['user_id'] === 1 ? true : "Vérification JWT échouée";
});

runTest("Détection token expiré", function() {
    require_once 'config.php';
    require_once 'JwtManager.php';
    
    $payload = ['user_id' => 1];
    $expiredToken = JwtManager::createToken($payload, time() - 1);
    
    try {
        JwtManager::verifyToken($expiredToken);
        return "Token expiré non détecté";
    } catch (Exception $e) {
        return strpos($e->getMessage(), 'expiré') !== false ? true : "Mauvaise erreur d'expiration";
    }
});

runTest("Extraction token depuis header", function() {
    require_once 'config.php';
    require_once 'JwtManager.php';
    
    $payload = ['user_id' => 1];
    $token = JwtManager::createToken($payload);
    
    $_SERVER['HTTP_AUTHORIZATION'] = "Bearer $token";
    $extractedToken = JwtManager::extractTokenFromHeader();
    
    return $extractedToken === $token ? true : "Extraction de header échouée";
});

// ===== TESTS DE VALIDATION =====
echo "🛡️ TESTS VALIDATION DES ENTRÉES\n";
echo "─────────────────────────────────────────\n";

runTest("Sanitisation XSS", function() {
    require_once 'InputValidator.php';
    
    $malicious = '<script>alert("xss")</script>';
    $sanitized = InputValidator::sanitizeInput($malicious);
    
    return strpos($sanitized, '<script>') === false ? true : "XSS non filtré";
});

runTest("Validation de nom d'utilisateur", function() {
    require_once 'InputValidator.php';
    
    try {
        InputValidator::validate('username', 'ADMIN');
        $valid = true;
    } catch (ValidationException $e) {
        $valid = false;
    }
    
    try {
        InputValidator::validate('username', '<script>');
        return "Nom d'utilisateur malicieux accepté";
    } catch (ValidationException $e) {
        return $valid ? true : "Nom d'utilisateur valide rejeté";
    }
});

runTest("Validation de poids", function() {
    require_once 'InputValidator.php';
    
    // Poids valide
    $valid = InputValidator::validate('poids', '123.45');
    if ($valid !== 123.45) {
        return "Poids valide mal converti";
    }
    
    // Poids négatif
    try {
        InputValidator::validate('poids', '-50');
        return "Poids négatif accepté";
    } catch (ValidationException $e) {
        return true;
    }
});

runTest("Validation d'email", function() {
    require_once 'InputValidator.php';
    
    // Email valide
    $valid = InputValidator::validate('email', 'test@example.com');
    if ($valid !== 'test@example.com') {
        return "Email valide rejeté";
    }
    
    // Email invalide
    try {
        InputValidator::validate('email', 'invalid-email');
        return "Email invalide accepté";
    } catch (ValidationException $e) {
        return true;
    }
});

runTest("Validation paramètres de recherche", function() {
    require_once 'InputValidator.php';
    
    $params = [
        'codePesee' => 'P2025001',
        'limit' => '50',
        'page' => '1',
        'malicious_param' => '<script>'
    ];
    
    $validated = InputValidator::validateSearchParams($params);
    
    // Le paramètre malicieux doit être ignoré
    if (isset($validated['malicious_param'])) {
        return "Paramètre non autorisé accepté";
    }
    
    // Les paramètres valides doivent être conservés
    return ($validated['codePesee'] === 'P2025001' && $validated['limit'] === 50) ? true : "Paramètres valides perdus";
});

// ===== TESTS DE SÉCURITÉ AVANCÉS =====
echo "🔒 TESTS DE SÉCURITÉ AVANCÉS\n";
echo "─────────────────────────────────────────\n";

runTest("Permissions fichier .env", function() {
    if (!file_exists('.env')) {
        return 'warning'; // Déjà testé
    }
    
    $perms = fileperms('.env') & 0777;
    
    // Sur Windows, les permissions sont différentes
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        return 'warning'; // Permissions Windows non critiques pour ce test
    }
    
    return ($perms <= 0600) ? true : "Fichier .env trop permissif (actuellement " . decoct($perms) . ")";
});

runTest("Headers de sécurité configurés", function() {
    require_once 'SecurityMiddleware.php';
    
    // Simuler la configuration des headers
    ob_start();
    SecurityMiddleware::setSecurityHeaders();
    ob_end_clean();
    
    $headers = headers_list();
    
    $securityHeaders = [
        'X-Content-Type-Options',
        'X-Frame-Options',
        'X-XSS-Protection'
    ];
    
    foreach ($securityHeaders as $header) {
        $found = false;
        foreach ($headers as $setHeader) {
            if (strpos($setHeader, $header) === 0) {
                $found = true;
                break;
            }
        }
        if (!$found) {
            return "Header $header manquant";
        }
    }
    
    return true;
});

runTest("Rate limiting fonctionnel", function() {
    require_once 'SecurityMiddleware.php';
    
    // Difficile à tester sans vraie requête, vérifier que la méthode existe
    $reflection = new ReflectionClass('SecurityMiddleware');
    $methods = $reflection->getMethods();
    
    foreach ($methods as $method) {
        if ($method->getName() === 'checkRateLimit') {
            return true;
        }
    }
    
    return "Méthode checkRateLimit manquante";
});

runTest("Logging de sécurité", function() {
    if (!is_dir('logs')) {
        return 'warning'; // Dossier logs non critique en dev
    }
    
    if (!is_writable('logs')) {
        return "Dossier logs non accessible en écriture";
    }
    
    return true;
});

// ===== TESTS D'INTÉGRATION =====
echo "🔄 TESTS D'INTÉGRATION\n";
echo "─────────────────────────────────────────\n";

runTest("Auth service avec JWT", function() {
    try {
        require_once 'config.php';
        require_once 'auth.php';
        require_once 'JwtManager.php';
        
        $authService = new AuthService();
        
        // Test avec des données simulées (sans DB)
        return true; // Classes chargées sans erreur
        
    } catch (Exception $e) {
        return "Erreur de chargement: " . $e->getMessage();
    }
});

runTest("Pesees service avec validation", function() {
    try {
        require_once 'InputValidator.php';
        require_once 'pesees.php'; // Peut échouer sans DB
        
        return true; // Classes chargées
        
    } catch (Exception $e) {
        // Acceptable si pas de DB
        if (strpos($e->getMessage(), 'database') !== false) {
            return 'warning';
        }
        return "Erreur inattendue: " . $e->getMessage();
    }
});

runTest("Configuration complète", function() {
    require_once 'config.php';
    
    $config = DatabaseConfig::getSecurityConfig();
    
    $required = ['jwt_secret', 'max_login_attempts', 'session_timeout'];
    foreach ($required as $key) {
        if (!isset($config[$key])) {
            return "Configuration $key manquante";
        }
    }
    
    return true;
});

// ===== RÉSULTATS =====
$endTime = microtime(true);
$duration = round(($endTime - $startTime) * 1000, 2);

echo "📊 RÉSULTATS DE L'AUDIT DE SÉCURITÉ\n";
echo "===============================================\n";
echo "🔍 Tests exécutés:    $totalTests\n";
echo "✅ Tests passés:      $passedTests\n";
echo "⚠️  Avertissements:   $warnings\n";
echo "❌ Tests échoués:     $failedTests\n";
echo "⏱️  Durée:            {$duration}ms\n";
echo "===============================================\n\n";

// Score de sécurité
$score = round((($passedTests + $warnings * 0.5) / $totalTests) * 100, 1);
echo "🛡️ SCORE DE SÉCURITÉ: $score%\n\n";

if ($score >= 90) {
    echo "🎉 EXCELLENT! Votre application est très sécurisée.\n";
    echo "✅ Prêt pour la production avec supervision continue.\n\n";
} elseif ($score >= 75) {
    echo "👍 BIEN! Sécurité acceptable avec quelques améliorations.\n";
    echo "⚠️  Corrigez les tests échoués avant la production.\n\n";
} elseif ($score >= 50) {
    echo "⚠️  MOYEN! Plusieurs problèmes de sécurité à corriger.\n";
    echo "❌ NE PAS déployer en production sans corrections.\n\n";
} else {
    echo "🚨 CRITIQUE! Sécurité insuffisante.\n";
    echo "❌ Corrections URGENTES requises.\n\n";
}

echo "📚 Consultez SECURITY_COMPLETE_GUIDE.md pour plus de détails.\n";
echo "🔧 Exécutez les scripts de correction si nécessaire.\n";
?>