<?php
// Helmyx — Main Entry Point
// ─────────────────────────────────
// Bootstrap order: ROOT_PATH → session → config → core files → autoload → helpers → router

if (!defined('ROOT_PATH')) {
    define('ROOT_PATH', __DIR__);
}

// ── Session ──────────────────────────────────────────────────────────────────
if (session_status() === PHP_SESSION_NONE) {
    session_set_cookie_params([
        'lifetime' => 7200,
        'path'     => '/',
        'domain'   => '',
        'secure'   => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on',
        'httponly' => true,
        'samesite' => 'Lax',
    ]);
    session_start();
}

// ── Config ───────────────────────────────────────────────────────────────────
require_once ROOT_PATH . '/config/config.php';
require_once ROOT_PATH . '/config/database.php';

// ── Platform Defaults ──────────────────────────────────────────────────────────
// Super-admin "System Settings" (organization_settings rows with org_id IS NULL) can
// override these platform-wide defaults; fall back to hardcoded values otherwise.
$platformDefaults = [
    'default_locale'     => 'en_NG',
    'default_currency'   => 'NGN',
    'default_timezone'   => 'Africa/Lagos',
    'platform_fee_rate'  => 0.005,
];
try {
    $rows = Database::getInstance()
        ->query("SELECT setting_key, setting_value FROM organization_settings WHERE org_id IS NULL")
        ->fetchAll();
    foreach ($rows as $row) {
        if (array_key_exists($row['setting_key'], $platformDefaults) && $row['setting_value'] !== null && $row['setting_value'] !== '') {
            $platformDefaults[$row['setting_key']] = $row['setting_value'];
        }
    }
} catch (\Throwable $e) {
    // Database/table not ready yet (e.g. fresh install before migrations) — use hardcoded fallbacks
}
define('DEFAULT_LOCALE', $platformDefaults['default_locale']);
define('DEFAULT_CURRENCY', $platformDefaults['default_currency']);
define('DEFAULT_TIMEZONE', $platformDefaults['default_timezone']);
define('PLATFORM_FEE_RATE', (float) $platformDefaults['platform_fee_rate']);

// ── CSRF Token ───────────────────────────────────────────────────────────────
// Views read $_SESSION[CSRF_TOKEN_NAME] directly, so it must exist for the
// lifetime of the session rather than being generated per-form.
if (empty($_SESSION[CSRF_TOKEN_NAME])) {
    $_SESSION[CSRF_TOKEN_NAME] = bin2hex(random_bytes(32));
}

// ── Core Framework ────────────────────────────────────────────────────────────
require_once ROOT_PATH . '/core/Router.php';
require_once ROOT_PATH . '/core/Model.php';
require_once ROOT_PATH . '/core/Controller.php';
require_once ROOT_PATH . '/core/View.php';
require_once ROOT_PATH . '/core/Auth.php';

// ── Global Aliases ────────────────────────────────────────────────────────────
// Controllers & models use various namespace styles (or none). Alias everything.
$aliases = [
    // No-namespace aliases (for AuthController, SettingsController etc)
    'Controller'          => \Core\Controller::class,
    'Model'               => \Core\Model::class,
    'View'                => \Core\View::class,
    'Auth'                => \Core\Auth::class,
    // App\Core aliases (for Finance controllers)
    'App\\Core\\Controller' => \Core\Controller::class,
    'App\\Core\\Model'      => \Core\Model::class,
    'App\\Core\\View'       => \Core\View::class,
    'App\\Core\\Auth'       => \Core\Auth::class,
    'App\\Core\\Router'     => \Core\Router::class,
    'App\\Core\\Database'   => 'Database',
];
foreach ($aliases as $alias => $original) {
    if (!class_exists($alias, false) && class_exists($original, false)) {
        class_alias($original, $alias);
    }
}

// ── Smart Autoloader ──────────────────────────────────────────────────────────
spl_autoload_register(function (string $class): void {
    // Helper: try a file path
    $tryLoad = function (string $file): bool {
        if (file_exists($file)) {
            require_once $file;
            return true;
        }
        return false;
    };

    // 1. Core\ namespace
    if (str_starts_with($class, 'Core\\')) {
        $tryLoad(ROOT_PATH . '/core/' . substr($class, 5) . '.php');
        return;
    }

    // 2. App\Core\ namespace
    if (str_starts_with($class, 'App\\Core\\')) {
        $name = substr($class, 9); // strip "App\Core\"
        $tryLoad(ROOT_PATH . '/core/' . $name . '.php');
        return;
    }

    // 3. Modules\ or App\Modules\ namespace
    $stripped = preg_replace('/^(App\\\\)?Modules\\\\/', '', $class);
    $parts = explode('\\', $stripped);
    if (count($parts) >= 3) {
        $module = strtolower($parts[0]);
        $layer  = strtolower($parts[1]);  // controllers | models
        $name   = $parts[2];
        if ($tryLoad(ROOT_PATH . "/modules/{$module}/{$layer}/{$name}.php")) return;
    }

    // 4. App\Modules\Finance\Controllers style
    if (str_starts_with($class, 'App\\Modules\\')) {
        $inner = substr($class, 12); // strip "App\Modules\"
        $parts = explode('\\', $inner);
        if (count($parts) >= 3) {
            $module = strtolower($parts[0]);
            $layer  = strtolower($parts[1]);
            $name   = $parts[2];
            if ($tryLoad(ROOT_PATH . "/modules/{$module}/{$layer}/{$name}.php")) return;
        }
    }

    // 5. Fallback: scan all module controllers + models directories
    $baseName = basename(str_replace('\\', '/', $class));
    $modulesDir = ROOT_PATH . '/modules';
    if (!is_dir($modulesDir)) return;
    foreach (scandir($modulesDir) as $module) {
        if ($module[0] === '.') continue;
        if ($tryLoad("{$modulesDir}/{$module}/controllers/{$baseName}.php")) return;
        if ($tryLoad("{$modulesDir}/{$module}/models/{$baseName}.php")) return;
    }
}, prepend: false);

// ── Composer vendor (if installed) ───────────────────────────────────────────
if (file_exists(ROOT_PATH . '/vendor/autoload.php')) {
    require_once ROOT_PATH . '/vendor/autoload.php';
}

// ── Helpers ──────────────────────────────────────────────────────────────────
require_once ROOT_PATH . '/core/Helpers.php';

// ── Dispatch ─────────────────────────────────────────────────────────────────
$router = new \Core\Router();
$router->run();
