<?php
declare(strict_types=1);

function golder_file_env_map(): array
{
    static $map = null;
    if (is_array($map)) {
        return $map;
    }

    $map = [];
    $candidates = [
        dirname(__DIR__) . '/.env',
        dirname(__DIR__, 2) . '/.env',
        dirname(__DIR__, 3) . '/.env',
    ];

    foreach ($candidates as $path) {
        if (!is_file($path) || !is_readable($path)) {
            continue;
        }
        $lines = @file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if (!is_array($lines)) {
            continue;
        }
        foreach ($lines as $line) {
            $raw = trim((string)$line);
            if ($raw === '' || str_starts_with($raw, '#')) {
                continue;
            }
            $eqPos = strpos($raw, '=');
            if ($eqPos === false) {
                continue;
            }
            $key = trim(substr($raw, 0, $eqPos));
            $value = trim(substr($raw, $eqPos + 1));
            if ($key === '') {
                continue;
            }
            if ($value !== '' && strlen($value) >= 2) {
                $first = $value[0];
                $last = $value[strlen($value) - 1];
                if (($first === '"' && $last === '"') || ($first === "'" && $last === "'")) {
                    $value = substr($value, 1, -1);
                }
            }
            $map[$key] = $value;
        }
    }

    return $map;
}

function golder_env(string $key, string $default = ''): string
{
    $value = getenv($key);
    if ($value !== false && $value !== null && $value !== '') {
        return (string)$value;
    }

    $serverValue = $_SERVER[$key] ?? $_ENV[$key] ?? null;
    if (is_string($serverValue) && $serverValue !== '') {
        return $serverValue;
    }

    $fileEnv = golder_file_env_map();
    if (isset($fileEnv[$key]) && $fileEnv[$key] !== '') {
        return (string)$fileEnv[$key];
    }

    return $default;
}

function golder_master_db_config(): array
{
    return [
        'host' => golder_env('GOLDER_MASTER_HOST', '127.0.0.1'),
        'port' => (int)golder_env('GOLDER_MASTER_PORT', '3306'),
        'name' => golder_env('GOLDER_MASTER_DB', 'golder_master'),
        'user' => golder_env('GOLDER_MASTER_USER', 'goldermaster'),
        'pass' => golder_env('GOLDER_MASTER_PASS', 'Mmty2676*'),
    ];
}

function golder_master_pdo(): PDO
{
    static $pdo = null;
    if ($pdo instanceof PDO) {
        return $pdo;
    }
    $cfg = golder_master_db_config();
    $pdo = new PDO(
        sprintf('mysql:host=%s;port=%d;dbname=%s;charset=utf8mb4', $cfg['host'], $cfg['port'], $cfg['name']),
        (string)$cfg['user'],
        (string)$cfg['pass'],
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ]
    );
    return $pdo;
}

function golder_json_response(array $payload, int $statusCode = 200): void
{
    http_response_code($statusCode);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function golder_json_error(int $statusCode, string $code, string $message, array $extra = []): void
{
    $payload = array_merge([
        'status' => 'error',
        'code' => $code,
        'message' => $message,
    ], $extra);
    golder_json_response($payload, $statusCode);
}

function golder_read_json_body(): array
{
    $raw = file_get_contents('php://input');
    if (!is_string($raw) || trim($raw) === '') {
        return [];
    }
    $decoded = json_decode($raw, true);
    return is_array($decoded) ? $decoded : [];
}

function golder_read_json_body_strict(): array
{
    $raw = file_get_contents('php://input');
    if (!is_string($raw) || trim($raw) === '') {
        return [];
    }
    $decoded = json_decode($raw, true);
    if (!is_array($decoded)) {
        golder_json_error(400, 'INVALID_REQUEST', 'Request body must be valid JSON.');
    }
    return $decoded;
}

function golder_uuid4(): string
{
    $bytes = random_bytes(16);
    $bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x40);
    $bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80);
    $hex = bin2hex($bytes);
    return substr($hex, 0, 8) . '-' . substr($hex, 8, 4) . '-' . substr($hex, 12, 4) . '-' . substr($hex, 16, 4) . '-' . substr($hex, 20, 12);
}

function golder_utc_now(): string
{
    return gmdate('Y-m-d H:i:s');
}

function golder_safe_identifier(string $value): bool
{
    return $value !== '' && preg_match('/^[A-Za-z0-9_]+$/', $value) === 1;
}

function golder_canonicalize($value)
{
    if (is_array($value)) {
        if (array_keys($value) !== range(0, count($value) - 1)) {
            ksort($value);
        }
        foreach ($value as $k => $v) {
            $value[$k] = golder_canonicalize($v);
        }
    }
    return $value;
}

function golder_canonical_json(array $payload): string
{
    $normalized = golder_canonicalize($payload);
    $json = json_encode($normalized, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    return is_string($json) ? $json : '{}';
}

function golder_client_ip(): string
{
    $headers = ['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'];
    foreach ($headers as $header) {
        $value = trim((string)($_SERVER[$header] ?? ''));
        if ($value === '') {
            continue;
        }
        $parts = explode(',', $value);
        $candidate = trim((string)$parts[0]);
        if (filter_var($candidate, FILTER_VALIDATE_IP)) {
            return $candidate;
        }
    }
    return '0.0.0.0';
}

function golder_user_agent(): string
{
    return substr(trim((string)($_SERVER['HTTP_USER_AGENT'] ?? 'unknown')), 0, 255);
}

function golder_require_method(string $method): void
{
    if (strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? 'GET')) !== strtoupper($method)) {
        golder_json_error(405, 'METHOD_NOT_ALLOWED', 'Method not allowed.');
    }
}


