<?php

declare(strict_types=1);

$socketPath = getenv('POC_SOCKET');
$script = getenv('POC_SCRIPT');
$dsn = getenv('POC_DSN');
$user = getenv('POC_USER');
$password = getenv('POC_PASSWORD');
$target = getenv('POC_TARGET');
if (!$socketPath || !$script || !$dsn || !$user || !$password || !$target) exit(2);

function fcgiRecord(int $type, string $content = ''): string
{
    $length = strlen($content);
    $padding = (8 - ($length % 8)) % 8;
    return pack('CCnnCC', 1, $type, 1, $length, $padding, 0) . $content . str_repeat("\0", $padding);
}

function fcgiLength(int $length): string
{
    return $length < 128 ? chr($length) : pack('N', $length | 0x80000000);
}

function readExact($stream, int $length): string
{
    $value = '';
    while (strlen($value) < $length) {
        $part = fread($stream, $length - strlen($value));
        if ($part === false || $part === '') throw new RuntimeException('FastCGI response ended early');
        $value .= $part;
    }
    return $value;
}

$params = [
    'GATEWAY_INTERFACE' => 'CGI/1.1',
    'REQUEST_METHOD' => 'GET',
    'SCRIPT_FILENAME' => $script,
    'SCRIPT_NAME' => '/fpm_db_charset_probe.php',
    'DOCUMENT_ROOT' => dirname($script),
    'SERVER_PROTOCOL' => 'HTTP/1.1',
    'SERVER_NAME' => 'localhost',
    'SERVER_PORT' => '80',
    'REMOTE_ADDR' => '127.0.0.1',
    'QUERY_STRING' => '',
    'CONTENT_LENGTH' => '0',
    'POC_DSN' => $dsn,
    'POC_USER' => $user,
    'POC_PASSWORD' => $password,
    'POC_TARGET' => $target,
];
$encoded = '';
foreach ($params as $name => $value) {
    $encoded .= fcgiLength(strlen($name)) . fcgiLength(strlen($value)) . $name . $value;
}
$stream = stream_socket_client('unix://' . $socketPath, $errorCode, $errorMessage, 8);
if (!$stream) throw new RuntimeException('FastCGI socket unavailable');
stream_set_timeout($stream, 10);
fwrite($stream, fcgiRecord(1, pack('nC', 1, 0) . str_repeat("\0", 5)));
fwrite($stream, fcgiRecord(4, $encoded));
fwrite($stream, fcgiRecord(4));
fwrite($stream, fcgiRecord(5));
$stdout = '';
$stderrBytes = 0;
while (true) {
    $header = readExact($stream, 8);
    $parts = unpack('Cversion/Ctype/nid/nlength/Cpadding/Creserved', $header);
    $content = readExact($stream, $parts['length']);
    if ($parts['padding'] > 0) readExact($stream, $parts['padding']);
    if ($parts['type'] === 6) $stdout .= $content;
    if ($parts['type'] === 7) $stderrBytes += strlen($content);
    if ($parts['type'] === 3) break;
}
fclose($stream);
$separator = strpos($stdout, "\r\n\r\n");
if ($separator === false) throw new RuntimeException('FastCGI response headers missing');
$body = substr($stdout, $separator + 4);
$data = json_decode($body, true);
if (!is_array($data)) throw new RuntimeException('FastCGI response was not JSON');
echo json_encode(['ok' => $data['ok'] ?? false, 'rows' => $data['rows'] ?? null,
    'invalid_utf8' => $data['invalid_utf8'] ?? null, 'error_type' => $data['error_type'] ?? null,
    'stderr_bytes' => $stderrBytes]) . PHP_EOL;
if (empty($data['ok']) || ($data['invalid_utf8'] ?? 1) !== 0) exit(1);
