<?php

declare(strict_types=1);

use App\Core\Config;

if (!function_exists('env')) {
    function env(
        string $key,
        mixed $default = null
    ): mixed {
        $environment = $GLOBALS['environment'] ?? [];

        return array_key_exists($key, $environment)
            ? $environment[$key]
            : $default;
    }
}

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

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

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

        $path = ltrim($path, '/');

        return $path === ''
            ? $baseUrl
            : $baseUrl . '/' . $path;
    }
}

if (!function_exists('asset')) {
    function asset(string $path): string
    {
        return base_url(
            'assets/' . ltrim($path, '/')
        );
    }
}

if (!function_exists('upload_url')) {
    function upload_url(string $path): string
    {
        return base_url(
            'uploads/' . ltrim($path, '/')
        );
    }
}

if (!function_exists('format_time')) {
    function format_time(?string $time): string
    {
        if (!$time) {
            return '';
        }

        $timestamp = strtotime($time);

        return $timestamp
            ? date('H:i', $timestamp)
            : '';
    }
}

if (!function_exists('redirect')) {
    function redirect(
        string $path,
        int $status = 302
    ): never {
        $url = preg_match(
            '/^https?:\/\//i',
            $path
        )
            ? $path
            : base_url($path);

        /*
         * Discard any accidental buffered output before redirecting.
         * This prevents legacy-library notices from breaking headers.
         */
        while (ob_get_level() > 0) {
            ob_end_clean();
        }

        if (headers_sent($file, $line)) {
            error_log(
                "Redirect headers already sent in {$file} on line {$line}"
            );

            echo '<script>';
            echo 'window.location.href = '
                . json_encode($url)
                . ';';
            echo '</script>';

            echo '<noscript>';
            echo '<meta http-equiv="refresh" content="0;url='
                . e($url)
                . '">';
            echo '</noscript>';

            exit;
        }

        header(
            'Location: ' . $url,
            true,
            $status
        );

        exit;
    }
}

if (!function_exists('asset')) {
    function asset(
        string $path
    ): string {
        return base_url(
            'assets/'
            . ltrim(
                $path,
                '/'
            )
        );
    }
}

if (!function_exists('upload_url')) {
    function upload_url(
        string $path
    ): string {
        return base_url(
            'uploads/'
            . ltrim(
                $path,
                '/'
            )
        );
    }
}

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

if (!function_exists('csrf_field')) {
    function csrf_field(): string
    {
        return '<input type="hidden" name="_token" value="'
            . e(csrf_token())
            . '">';
    }
}

if (!function_exists('flash')) {
    function flash(
        string $key,
        ?string $message = null
    ): mixed {
        if ($message !== null) {
            $_SESSION['_flash'][$key] =
                $message;

            return null;
        }

        $value =
            $_SESSION['_flash'][$key]
            ?? null;

        unset(
            $_SESSION['_flash'][$key]
        );

        return $value;
    }
}

if (!function_exists('set_old_input')) {
    function set_old_input(
        array $input
    ): void {
        unset(
            $input['_token'],
            $input['password'],
            $input['password_confirmation']
        );

        $_SESSION['_old'] = $input;
    }
}

if (!function_exists('old')) {
    function old(
        string $key,
        mixed $default = ''
    ): mixed {
        return $_SESSION['_old'][$key]
            ?? $default;
    }
}

if (!function_exists('clear_old_input')) {
    function clear_old_input(): void
    {
        unset($_SESSION['_old']);
    }
}

if (!function_exists('set_errors')) {
    function set_errors(
        array $errors
    ): void {
        $_SESSION['_errors'] =
            $errors;
    }
}

if (!function_exists('get_errors')) {
    function get_errors(): array
    {
        $errors =
            $_SESSION['_errors']
            ?? [];

        unset(
            $_SESSION['_errors']
        );

        return $errors;
    }
}

if (!function_exists('error_for')) {
    function error_for(
        array $errors,
        string $field
    ): ?string {
        return $errors[$field]
            ?? null;
    }
}

if (!function_exists('selected')) {
    function selected(
        mixed $value,
        mixed $expected
    ): string {
        return (string) $value
            === (string) $expected
                ? 'selected'
                : '';
    }
}

if (!function_exists('checked')) {
    function checked(
        mixed $value,
        mixed $expected = 1
    ): string {
        if (is_array($value)) {
            return in_array(
                (string) $expected,
                array_map(
                    'strval',
                    $value
                ),
                true
            )
                ? 'checked'
                : '';
        }

        return (string) $value
            === (string) $expected
                ? 'checked'
                : '';
    }
}