<?php

declare(strict_types=1);

define('BASE_PATH', dirname(__DIR__));

require BASE_PATH . '/app/helpers/env.php';
load_env(BASE_PATH . '/.env');
require BASE_PATH . '/app/helpers/functions.php';

spl_autoload_register(static function (string $class): void {
    $prefix = 'App\\';
    if (!str_starts_with($class, $prefix)) {
        return;
    }

    $relative = substr($class, strlen($prefix));
    $parts = explode('\\', $relative);
    $file = array_pop($parts);
    $directory = implode('/', array_map('strtolower', $parts));

    $path = BASE_PATH . '/app/' . ($directory !== '' ? $directory . '/' : '') . $file . '.php';

    if (is_file($path)) {
        require $path;
    }
});

use App\Core\Request;
use App\Core\Router;
use App\Core\Session;
use App\Core\Logger;
use App\Middleware\AuthMiddleware;
use App\Middleware\GuestMiddleware;
use App\Middleware\PermissionMiddleware;
use App\Middleware\TenantMiddleware;
use App\Middleware\CsrfMiddleware;
use App\Middleware\NoCsrfMiddleware;
use App\Middleware\SuperadminMiddleware;

set_exception_handler(static function (Throwable $e): void {
    Logger::error($e->getMessage(), ['trace' => $e->getTraceAsString()]);

    if ((bool) config('app.debug', false)) {
        http_response_code(500);
        echo '<h1>Error interno</h1>';
        echo '<pre>' . e($e->getMessage() . "\n" . $e->getTraceAsString()) . '</pre>';
        return;
    }

    http_response_code(500);
    echo 'Error interno del servidor.';
});

set_error_handler(static function (int $severity, string $message, string $file, int $line): bool {
    if (!(error_reporting() & $severity)) {
        return false;
    }

    if (in_array($severity, [E_DEPRECATED, E_USER_DEPRECATED], true)) {
        Logger::warning('Deprecated PHP notice', [
            'message' => $message,
            'file' => $file,
            'line' => $line,
            'severity' => $severity,
        ]);
        return true;
    }

    throw new ErrorException($message, 0, $severity, $file, $line);
});

date_default_timezone_set((string) config('app.timezone', 'America/Bogota'));
enforce_https_redirect_if_needed();
send_security_headers();
Session::start();

$router = new Router();
$router->middlewareAlias('auth', AuthMiddleware::class);
$router->middlewareAlias('guest', GuestMiddleware::class);
$router->middlewareAlias('tenant', TenantMiddleware::class);
$router->middlewareAlias('permission', PermissionMiddleware::class);
$router->middlewareAlias('csrf', CsrfMiddleware::class);
$router->middlewareAlias('no_csrf', NoCsrfMiddleware::class);
$router->middlewareAlias('superadmin', SuperadminMiddleware::class);

$routeFiles = config('routes');
foreach ($routeFiles as $routeFile) {
    $path = BASE_PATH . $routeFile;
    if (!is_file($path)) {
        continue;
    }

    $register = require $path;
    if (is_callable($register)) {
        $register($router);
    }
}

$request = Request::capture();
$router->dispatch($request);
