<?php

declare(strict_types=1);

namespace App\Core;

/**
 * Env
 *
 * Minimal .env file loader. Deliberately dependency-free so the app can
 * boot before `composer install` has ever been run (composer is still
 * used for PHPMailer and other third-party packages — see composer.json
 * — but the app's own bootstrap never blocks on it).
 *
 * If the team prefers vlucas/phpdotenv instead, swap the load() body for
 * `Dotenv\Dotenv::createImmutable(...)->load();` — everything downstream
 * reads through Env::get(), so nothing else needs to change.
 */
final class Env
{
    private static bool $loaded = false;

    /** @var array<string,string> */
    private static array $values = [];

    public static function load(string $path): void
    {
        if (self::$loaded) {
            return;
        }

        if (!is_file($path)) {
            // No .env present (e.g. first-time setup). Fall back to real
            // environment variables only — do not throw, so CLI tools
            // like `php bin/generate_key.php` can still run.
            self::$loaded = true;
            return;
        }

        $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if ($lines === false) {
            self::$loaded = true;
            return;
        }

        foreach ($lines as $line) {
            $line = trim($line);

            if ($line === '' || str_starts_with($line, '#')) {
                continue;
            }

            if (!str_contains($line, '=')) {
                continue;
            }

            [$key, $value] = explode('=', $line, 2);
            $key = trim($key);
            $value = self::stripQuotes(trim($value));

            self::$values[$key] = $value;

            // Also expose to getenv()/$_ENV for third-party libraries
            // (PHPMailer, etc.) that read the real process environment.
            if (getenv($key) === false) {
                putenv("{$key}={$value}");
                $_ENV[$key] = $value;
            }
        }

        self::$loaded = true;
    }

    public static function get(string $key, mixed $default = null): mixed
    {
        if (array_key_exists($key, self::$values)) {
            return self::castType(self::$values[$key]);
        }

        $envValue = getenv($key);
        if ($envValue !== false) {
            return self::castType($envValue);
        }

        return $default;
    }

    private static function castType(string $value): bool|string|null
    {
        return match (strtolower($value)) {
            'true', '(true)' => true,
            'false', '(false)' => false,
            'null', '(null)' => null,
            'empty', '(empty)' => '',
            default => $value,
        };
    }

    private static function stripQuotes(string $value): string
    {
        if (strlen($value) >= 2) {
            $first = $value[0];
            $last = $value[-1];
            if ($first === $last && ($first === '"' || $first === "'")) {
                return substr($value, 1, -1);
            }
        }

        return $value;
    }
}
