<?php

declare(strict_types=1);

require_once __DIR__ . '/bootstrap.php';

// Chargement des fichiers principaux
require_once __DIR__ . '/src/Config/AppConfig.php';
require_once __DIR__ . '/src/Core/Database.php';
require_once __DIR__ . '/src/Core/AddressesDatabase.php';
require_once __DIR__ . '/src/Core/Router.php';
require_once __DIR__ . '/src/Core/Session.php';
require_once __DIR__ . '/src/Core/Request.php';
require_once __DIR__ . '/src/Core/Response.php';
require_once __DIR__ . '/src/Utils/ClientDetector.php';
require_once __DIR__ . '/src/Services/LogService.php';

// Chargement des services
require_once __DIR__ . '/src/Services/StripeService.php';

// Chargement des services de sécurité
require_once __DIR__ . '/src/Services/Security/PerformanceMonitor.php';
require_once __DIR__ . '/src/Services/Security/IPBlocker.php';
require_once __DIR__ . '/src/Services/Security/SecurityMonitor.php';
require_once __DIR__ . '/src/Services/Security/AlertService.php';

// Chargement de la classe Controller de base
require_once __DIR__ . '/src/Core/Controller.php';

// Chargement des contrôleurs
require_once __DIR__ . '/src/Controllers/LogController.php';
require_once __DIR__ . '/src/Controllers/LoginController.php';
require_once __DIR__ . '/src/Controllers/EntiteController.php';
require_once __DIR__ . '/src/Controllers/UserController.php';
require_once __DIR__ . '/src/Controllers/OperationController.php';
require_once __DIR__ . '/src/Controllers/PassageController.php';
require_once __DIR__ . '/src/Controllers/VilleController.php';
require_once __DIR__ . '/src/Controllers/FileController.php';
require_once __DIR__ . '/src/Controllers/SectorController.php';
require_once __DIR__ . '/src/Controllers/PasswordController.php';
require_once __DIR__ . '/src/Controllers/ChatController.php';
require_once __DIR__ . '/src/Controllers/SecurityController.php';
require_once __DIR__ . '/src/Controllers/StripeController.php';
require_once __DIR__ . '/src/Controllers/StripeWebhookController.php';
require_once __DIR__ . '/src/Controllers/MigrationController.php';
require_once __DIR__ . '/src/Controllers/HealthController.php';

// Initialiser la configuration
$appConfig = AppConfig::getInstance();
$config = $appConfig->getFullConfig();

// Initialiser la base de données principale
Database::init($config['database']);

// Initialiser la base de données des adresses
AddressesDatabase::init($appConfig->getAddressesDatabaseConfig());

// Configuration CORS
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
$allowedOrigins = $config['api']['allowed_origins'];

// Vérifier si l'origine est autorisée
if (in_array($origin, $allowedOrigins)) {
    header('Access-Control-Allow-Origin: ' . $origin);
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: Content-Type, Authorization, X-App-Identifier');
    header('Access-Control-Allow-Credentials: true');
}

// Gestion des requêtes preflight (OPTIONS)
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    exit(0);
}

// Initialiser la session
Session::start();

// ===== DÉBUT DU MONITORING DE SÉCURITÉ =====
use App\Services\Security\PerformanceMonitor;
use App\Services\Security\IPBlocker;
use App\Services\Security\SecurityMonitor;
use App\Services\Security\AlertService;

// Obtenir l'IP du client
$clientIp = $_SERVER['REMOTE_ADDR'] ?? 'unknown';

// Vérifier si l'IP est bloquée
if (IPBlocker::isBlocked($clientIp)) {
    http_response_code(403);
    Response::json([
        'status' => 'error',
        'message' => 'Access denied. Your IP has been blocked.',
        'error_code' => 'IP_BLOCKED'
    ], 403);
    exit;
}

// Vérifier le rate limiting
if (!SecurityMonitor::checkRateLimit($clientIp)) {
    http_response_code(429);
    Response::json([
        'status' => 'error',
        'message' => 'Too many requests. Please try again later.',
        'error_code' => 'RATE_LIMIT_EXCEEDED'
    ], 429);
    exit;
}

// Démarrer le monitoring de performance
PerformanceMonitor::startRequest();

// Capturer le endpoint pour le monitoring
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
$requestMethod = $_SERVER['REQUEST_METHOD'] ?? 'GET';

// Vérifier les patterns de scan
if (!SecurityMonitor::checkScanPattern($requestUri)) {
    // Pattern suspect détecté, bloquer l'IP temporairement
    IPBlocker::block($clientIp, 3600, 'Suspicious scan pattern detected');
    http_response_code(404);
    Response::json([
        'status' => 'error',
        'message' => 'Not found'
    ], 404);
    exit;
}

// Vérifier les paramètres pour injection SQL
$allParams = array_merge($_GET, $_POST, json_decode(file_get_contents('php://input'), true) ?? []);
if (!empty($allParams) && !SecurityMonitor::checkRequestParameters($allParams)) {
    // Injection SQL détectée, bloquer l'IP définitivement
    IPBlocker::blockPermanent($clientIp, 'SQL injection attempt');
    http_response_code(400);
    Response::json([
        'status' => 'error',
        'message' => 'Bad request'
    ], 400);
    exit;
}

// Créer l'instance de routeur
$router = new Router();

// Enregistrer une fonction de shutdown pour capturer les métriques
register_shutdown_function(function() use ($requestUri, $requestMethod) {
    $statusCode = http_response_code();
    
    // Terminer le monitoring de performance
    PerformanceMonitor::endRequest($requestUri, $requestMethod, $statusCode);
    
    // Vérifier les patterns 404
    if ($statusCode === 404) {
        $clientIp = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        SecurityMonitor::check404Pattern($clientIp);
    }
    
    // Alerter sur les erreurs 500
    if ($statusCode >= 500) {
        $error = error_get_last();
        $errorMessage = $error['message'] ?? null;

        // Si pas d'erreur PHP, c'est probablement une exception capturée
        // Le détail de l'erreur sera dans les logs applicatifs
        if ($errorMessage === null) {
            $errorMessage = 'Exception capturée (voir logs/app.log pour détails)';
        }

        AlertService::trigger('HTTP_500', [
            'endpoint' => $requestUri,
            'method' => $requestMethod,
            'error_message' => $errorMessage,
            'error_file' => $error['file'] ?? 'N/A',
            'error_line' => $error['line'] ?? 0,
            'stack_trace' => 'Consulter logs/app.log pour le stack trace complet',
            'message' => "Erreur serveur 500 sur $requestUri"
        ], 'ERROR');
    }
    
    // Nettoyer périodiquement les IPs expirées (1% de chance)
    if (rand(1, 100) === 1) {
        IPBlocker::cleanupExpired();
    }
});

// Gérer les erreurs non capturées
set_exception_handler(function($exception) use ($requestUri, $requestMethod) {
    // Logger l'erreur
    error_log("Uncaught exception: " . $exception->getMessage());
    
    // Créer une alerte
    AlertService::trigger('UNCAUGHT_EXCEPTION', [
        'endpoint' => $requestUri,
        'method' => $requestMethod,
        'exception' => get_class($exception),
        'message' => $exception->getMessage(),
        'file' => $exception->getFile(),
        'line' => $exception->getLine(),
        'trace' => substr($exception->getTraceAsString(), 0, 1000)
    ], 'ERROR');
    
    // Retourner une erreur 500
    http_response_code(500);
    Response::json([
        'status' => 'error',
        'message' => 'Internal server error'
    ], 500);
});

// Gérer la requête
try {
    $router->handle();
} catch (Exception $e) {
    // Les exceptions sont gérées par le handler ci-dessus
    throw $e;
}
