<?php
/**
 * Bundled minimal implementation of vlucas/phpdotenv 5.x.
 *
 * Implements only the surface area BlackRed uses:
 *   - Dotenv::createImmutable($path)
 *   - $dotenv->load() — parses .env, populates $_ENV
 *
 * Supports:
 *   - KEY=value
 *   - KEY="quoted value"  /  KEY='quoted value'
 *   - Whole-line comments starting with #
 *   - Trailing whitespace
 *   - Blank lines
 *
 * Does NOT support:
 *   - Variable interpolation (${OTHER_KEY}) — we don't use it
 *   - Multi-line values — we don't use them
 *   - Inline comments after values — we don't use them
 *
 * Why a bundled implementation? This shared host has no Composer access. We
 * include this implementation directly so the application can run without
 * Composer. To upgrade to the real upstream package, run `composer install`
 * — Composer's autoloader takes precedence.
 *
 * Original library: https://github.com/vlucas/phpdotenv (BSD-3-Clause)
 */

declare(strict_types=1);

namespace Dotenv;

use RuntimeException;

final class Dotenv
{
    private function __construct(private readonly string $path)
    {
    }

    public static function createImmutable(string $path): self
    {
        return new self($path);
    }

    /**
     * Load .env from the configured path. Populates $_ENV with parsed values.
     * Idempotent in practice: re-running just re-reads and overwrites.
     *
     * @return array<string, string> The loaded key-value pairs
     * @throws RuntimeException if .env is unreadable
     */
    public function load(): array
    {
        $file = rtrim($this->path, '/\\') . '/.env';
        if (!is_file($file)) {
            throw new RuntimeException("Cannot find .env at {$file}");
        }
        if (!is_readable($file)) {
            throw new RuntimeException(".env is not readable: {$file}");
        }

        $loaded = [];
        $handle = @fopen($file, 'rb');
        if ($handle === false) {
            throw new RuntimeException("Cannot open .env: {$file}");
        }

        try {
            while (($line = fgets($handle)) !== false) {
                $line = rtrim($line, "\r\n");
                $trimmed = ltrim($line);

                // Skip blank lines and full-line comments
                if ($trimmed === '' || $trimmed[0] === '#') {
                    continue;
                }

                $eq = strpos($trimmed, '=');
                if ($eq === false) {
                    // Malformed line; skip silently rather than crash.
                    continue;
                }

                $key = rtrim(substr($trimmed, 0, $eq));
                $value = ltrim(substr($trimmed, $eq + 1));

                // Validate key shape: alphanumeric and underscore, must start with letter/underscore.
                if (!preg_match('/^[A-Za-z_][A-Za-z0-9_]*$/', $key)) {
                    continue;
                }

                // Strip surrounding matching quotes if present.
                $value = $this->unquote($value);

                $_ENV[$key] = $value;
                $loaded[$key] = $value;
            }
        } finally {
            fclose($handle);
        }

        return $loaded;
    }

    /**
     * Strip surrounding single or double quotes if both ends match.
     * Trailing whitespace outside quotes is also trimmed.
     */
    private function unquote(string $value): string
    {
        $value = rtrim($value);
        $len = strlen($value);
        if ($len >= 2) {
            $first = $value[0];
            $last = $value[$len - 1];
            if (($first === '"' && $last === '"') || ($first === "'" && $last === "'")) {
                return substr($value, 1, -1);
            }
        }
        return $value;
    }
}
