<?php

declare(strict_types=1);

// Isolated, read-only DM candidate-driver capability probe. Never prints connection secrets.
$mode = (string) getenv('CDX_DM_FETCH_MODE');
if (!in_array($mode, ['default', 'stringify', 'extra_decimal', 'extra_only'], true)) {
    fwrite(STDERR, "Invalid fetch mode\n");
    exit(2);
}
if ($mode === 'extra_only' && (string) getenv('CDX_ALLOW_UNSAFE_EXTRA_ONLY') !== '1') {
    // A historical CLI probe showed corrupted decimal buffers in this combination.
    fwrite(STDERR, "Unsafe mode disabled; see RESULT.md\n");
    exit(2);
}
$required = ['POC_HOST', 'POC_PORT', 'POC_SCHEMA', 'POC_USER', 'POC_PASSWORD'];
foreach ($required as $key) {
    if ((string) getenv($key) === '') {
        fwrite(STDERR, "Approved DM runtime environment unavailable\n");
        exit(2);
    }
}
$pdoClass = new ReflectionClass('PDO');
$extraDecimal = $pdoClass->getConstant('EXTRA_DECIMAL');
$options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
    PDO::ATTR_STRINGIFY_FETCHES => in_array($mode, ['stringify', 'extra_decimal'], true),
];
if (in_array($mode, ['extra_decimal', 'extra_only'], true) && $extraDecimal !== false) {
    $options[$extraDecimal] = 1;
}
$dsn = 'dm:host=' . getenv('POC_HOST') . ';port=' . getenv('POC_PORT')
    . ';schema=' . getenv('POC_SCHEMA');
$cases = [
    'large_decimal_30_2' => "SELECT CAST('9007199254740993.01' AS DECIMAL(30,2)) AS V FROM DUAL",
    'decimal_20_0_boundaries' => "SELECT"
        . " CAST('9007199254740993' AS DECIMAL(20,0)) AS OVER_2P53,"
        . " CAST('9223372036854775807' AS DECIMAL(20,0)) AS INT64_MAX,"
        . " CAST('18446744073709551615' AS DECIMAL(20,0)) AS UINT64_MAX"
        . ' FROM DUAL',
    'decimal_16_6_time' => "SELECT CAST('1700000000.123456' AS DECIMAL(16,6)) AS V FROM DUAL",
    'aggregate' => "SELECT SUM(CAST('1.20' AS DECIMAL(30,2))) AS SUM_120,"
        . " AVG(CAST('1.20' AS DECIMAL(30,2))) AS AVG_120,"
        . " SUM(CAST('0.00' AS DECIMAL(30,2))) AS SUM_ZERO,"
        . " AVG(CAST('0.00' AS DECIMAL(30,2))) AS AVG_ZERO,"
        . ' COUNT(*) AS COUNT_ROWS FROM DUAL',
    'empty_aggregate' => "SELECT SUM(CAST('1.20' AS DECIMAL(30,2))) AS SUM_EMPTY,"
        . ' COUNT(*) AS COUNT_EMPTY FROM DUAL WHERE 1=0',
    'primitive_types' => "SELECT 7 AS INT_VALUE,"
        . " CAST('9223372036854775807' AS BIGINT) AS BIGINT_VALUE,"
        . ' CAST(1.25 AS FLOAT) AS FLOAT_VALUE,'
        . ' NULL AS NULL_VALUE FROM DUAL',
];
$result = [
    'php_version' => PHP_VERSION,
    'dm_module_version' => phpversion('DM'),
    'pdo_dm_module_version' => phpversion('PDO_DM'),
    'pdo_extra_decimal_constant' => $extraDecimal,
    'mode' => $mode,
    'cases' => [],
];
try {
    $pdo = new PDO($dsn, (string) getenv('POC_USER'), (string) getenv('POC_PASSWORD'), $options);
    $result['pdo_driver'] = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
    foreach ($cases as $name => $sql) {
        try {
            $statement = $pdo->query($sql);
            $row = $statement->fetch(PDO::FETCH_ASSOC);
            $values = [];
            foreach ($row === false ? [] : $row as $column => $value) {
                $values[$column] = [
                    'type' => gettype($value),
                    'string' => $value === null ? null : (string) $value,
                    'float_17_digits' => is_float($value) ? sprintf('%.17g', $value) : null,
                ];
            }
            $result['cases'][$name] = ['status' => 'ok', 'values' => $values];
        } catch (Throwable $error) {
            $result['cases'][$name] = [
                'status' => 'error', 'class' => get_class($error), 'code' => $error->getCode(),
            ];
        }
    }
} catch (Throwable $error) {
    // Exception messages can include DSN or credentials; never serialize them.
    $result['connection'] = [
        'status' => 'error', 'class' => get_class($error), 'code' => $error->getCode(),
    ];
}
echo json_encode($result, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL;
