<?php

declare(strict_types=1);

use App\Core\Csrf;
use App\Core\Env;
use App\Core\Session;

/*
 * Global helper functions, autoloaded via composer.json's "files"
 * directive (and required directly by public/index.php as a fallback
 * — see that file). Every one of these is a thin wrapper around a core
 * class; the logic itself always lives in app/core or app/services,
 * never here. Keep this file to simple, stateless one-liners only.
 */

if (!function_exists('config')) {
    /** Dot-notation config access, e.g. config('database.connections.mysql.host'). */
    function config(string $key, mixed $default = null): mixed
    {
        static $cache = [];

        [$file, $path] = array_pad(explode('.', $key, 2), 2, null);

        if (!isset($cache[$file])) {
            $configPath = dirname(__DIR__, 2) . "/config/{$file}.php";
            $cache[$file] = is_file($configPath) ? require $configPath : [];
        }

        if ($path === null) {
            return $cache[$file];
        }

        $value = $cache[$file];
        foreach (explode('.', $path) as $segment) {
            if (!is_array($value) || !array_key_exists($segment, $value)) {
                return $default;
            }
            $value = $value[$segment];
        }

        return $value;
    }
}

if (!function_exists('env')) {
    function env(string $key, mixed $default = null): mixed
    {
        return Env::get($key, $default);
    }
}

if (!function_exists('e')) {
    /** The ONLY function views should use to print user-supplied or DB-sourced text. Escaping is an output concern. */
    function e(mixed $value): string
    {
        return htmlspecialchars((string) ($value ?? ''), ENT_QUOTES, 'UTF-8');
    }
}

if (!function_exists('old')) {
    /** Re-populate a form field after a failed validation redirect. */
    function old(string $key, string $default = ''): string
    {
        $old = Session::getFlash('_old_input', []);

        return e($old[$key] ?? $default);
    }
}

if (!function_exists('csrf_field')) {
    function csrf_field(): string
    {
        return Csrf::field();
    }
}

if (!function_exists('csrf_token')) {
    function csrf_token(): string
    {
        return Csrf::token();
    }
}

if (!function_exists('base_url')) {
    function base_url(string $path = ''): string
    {
        $base = rtrim((string) config('app.url'), '/');

        return $path === '' ? $base : $base . '/' . ltrim($path, '/');
    }
}

if (!function_exists('asset')) {
    /** Cache-busted asset URL: asset('css/style.css') -> /assets/css/style.css?v=<mtime>. */
    function asset(string $path): string
    {
        $relative = ltrim($path, '/');
        $absoluteOnDisk = dirname(__DIR__, 2) . '/public/assets/' . $relative;
        $version = is_file($absoluteOnDisk) ? filemtime($absoluteOnDisk) : time();

        return base_url('assets/' . $relative) . '?v=' . $version;
    }
}

if (!function_exists('redirect_to')) {
    function redirect_to(string $path): never
    {
        header('Location: ' . (str_starts_with($path, 'http') ? $path : base_url($path)));
        exit;
    }
}

if (!function_exists('money')) {
    /** Format a decimal amount using the workspace default currency (CAD unless overridden). */
    function money(float|string $amount, ?string $currency = null): string
    {
        $currency = $currency ?? (string) config('app.default_currency', 'CAD');
        $symbol = $currency === 'CAD' ? 'CA$' : ($currency === 'USD' ? '$' : $currency . ' ');

        return $symbol . number_format((float) $amount, 2);
    }
}

if (!function_exists('now')) {
    function now(): string
    {
        return (new DateTime('now', new DateTimeZone((string) config('app.timezone', 'UTC'))))->format('Y-m-d H:i:s');
    }
}

if (!function_exists('str_random')) {
    function str_random(int $length = 32): string
    {
        return bin2hex(random_bytes((int) ceil($length / 2)));
    }
}

if (!function_exists('array_get')) {
    function array_get(array $array, string $key, mixed $default = null): mixed
    {
        return $array[$key] ?? $default;
    }
}

if (!function_exists('dd')) {
    /** Dev-only debug dump-and-die. Never leave a call to this in committed code outside APP_DEBUG. */
    function dd(mixed ...$vars): never
    {
        echo '<pre style="background:#0B0F19;color:#f4f4f5;padding:1rem;border-radius:8px;">';
        foreach ($vars as $var) {
            var_dump($var);
        }
        echo '</pre>';
        exit(1);
    }
}
