<?php

declare(strict_types=1);

function base_path(string $path = ''): string
{
    $base = dirname(__DIR__);
    return $path ? $base . DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : $base;
}

function public_path(string $path = ''): string
{
    return base_path('public' . ($path ? DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : ''));
}

function storage_path(string $path = ''): string
{
    return base_path('storage' . ($path ? DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : ''));
}

function env(string $key, $default = null)
{
    if (array_key_exists($key, $_ENV)) {
        return $_ENV[$key];
    }

    if (array_key_exists($key, $_SERVER)) {
        return $_SERVER[$key];
    }

    return $default;
}

function config(string $key, $default = null)
{
    static $configs = [];

    $parts = explode('.', $key);
    $file = array_shift($parts);

    if (!isset($configs[$file])) {
        $path = base_path('config/' . $file . '.php');
        if (!is_file($path)) {
            return $default;
        }
        $configs[$file] = require $path;
    }

    $value = $configs[$file];
    foreach ($parts as $part) {
        if (!is_array($value) || !array_key_exists($part, $value)) {
            return $default;
        }
        $value = $value[$part];
    }

    return $value;
}

function e($value): string
{
    return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

function redirect(string $url): void
{
    if (session_status() === PHP_SESSION_ACTIVE) {
        session_write_close();
    }

    header('Location: ' . $url);
    exit;
}

function current_url(array $override = []): string
{
    $query = array_merge($_GET, $override);
    return '?' . http_build_query($query);
}

function url_to(string $page, array $params = []): string
{
    $params = array_merge(['page' => $page, 'lang' => current_lang()], $params);
    return 'index.php?' . http_build_query($params);
}

function lang_url(string $targetLang): string
{
    return 'index.php' . current_url(['lang' => normalize_lang($targetLang)]);
}

function normalize_lang($value): string
{
    $value = strtolower(trim((string) $value));
    return in_array($value, ['en', 'ar'], true) ? $value : 'en';
}

function current_lang(): string
{
    static $lang = null;
    if ($lang !== null) {
        return $lang;
    }

    $requested = $_GET['lang'] ?? null;
    if ($requested !== null) {
        $lang = normalize_lang($requested);
        if (!headers_sent()) {
            setcookie('hmh_lang', $lang, time() + 31536000, '/', '', false, true);
        }
        return $lang;
    }

    if (isset($_COOKIE['hmh_lang'])) {
        $lang = normalize_lang($_COOKIE['hmh_lang']);
        return $lang;
    }

    $lang = normalize_lang(env('APP_LOCALE', 'en'));
    return $lang;
}

function current_dir(): string
{
    return current_lang() === 'ar' ? 'rtl' : 'ltr';
}

function opposite_lang(): string
{
    return current_lang() === 'ar' ? 'en' : 'ar';
}

function t(string $key, array $replace = []): string
{
    /*
     * Important:
     * Translation files use flat keys such as "dashboard.title".
     * The generic config() helper uses dot notation, so calling
     * config('i18n.en.dashboard.title') would incorrectly look for
     * ['en']['dashboard']['title']. We therefore load the language
     * dictionary first, then read the flat translation key directly.
     */
    $lang = current_lang();
    $dictionary = config('i18n.' . $lang, []);
    if (!is_array($dictionary)) {
        $dictionary = [];
    }

    $line = array_key_exists($key, $dictionary) ? $dictionary[$key] : null;

    if ($line === null && $lang !== 'en') {
        $fallback = config('i18n.en', []);
        if (is_array($fallback) && array_key_exists($key, $fallback)) {
            $line = $fallback[$key];
        }
    }

    if ($line === null) {
        $line = $key;
    }

    $line = (string) $line;
    foreach ($replace as $name => $value) {
        $line = str_replace('%' . $name . '%', (string) $value, $line);
    }
    return $line;
}

function normalize_hospital_code($value): string
{
    $value = strtolower(trim((string) $value));
    return preg_replace('/[^a-z0-9_\-]/', '', $value) ?: 'njch';
}

function default_hospital(): string
{
    $code = normalize_hospital_code(env('DEFAULT_HOSPITAL', 'njch'));
    $hospitals = config('hospitals', []);
    $readiness = config('branch_readiness.branches', []);

    $isLive = static function (string $hospitalCode) use ($hospitals, $readiness): bool {
        if (!is_array($hospitals) || !array_key_exists($hospitalCode, $hospitals)) {
            return false;
        }

        $branch = is_array($readiness) ? ($readiness[$hospitalCode] ?? null) : null;
        if (!is_array($branch)) {
            return false;
        }

        return strtoupper(trim((string)($branch['state'] ?? ''))) === 'READY'
            && filter_var($branch['include_in_live_views'] ?? false, FILTER_VALIDATE_BOOLEAN) === true;
    };

    if ($isLive($code)) {
        return $code;
    }

    if (is_array($hospitals)) {
        foreach (array_keys($hospitals) as $hospitalCode) {
            $hospitalCode = normalize_hospital_code((string)$hospitalCode);
            if ($isLive($hospitalCode)) {
                return $hospitalCode;
            }
        }
    }

    throw new RuntimeException('No branch is approved for live dashboard access.');
}

function safe_int($value, int $default): int
{
    if ($value === null || $value === '') {
        return $default;
    }

    return filter_var($value, FILTER_VALIDATE_INT) !== false ? (int) $value : $default;
}

function money_number($value): string
{
    return number_format((float) $value, 2);
}

function compact_money($value): string
{
    $n = (float) $value;
    $abs = abs($n);
    if ($abs >= 1000000000) {
        return number_format($n / 1000000000, 2) . 'B';
    }
    if ($abs >= 1000000) {
        return number_format($n / 1000000, 2) . 'M';
    }
    if ($abs >= 1000) {
        return number_format($n / 1000, 1) . 'K';
    }
    return number_format($n, 0);
}
