<?php

declare(strict_types=1);

$dialect = (string)getenv('POC_DIALECT');
$role = (string)getenv('POC_ROLE');
$stringify = (string)getenv('POC_STRINGIFY_FETCHES') === '1';
if (!in_array($dialect, ['mysql', 'dm'], true)
    || !in_array($role, ['store', 'ai'], true)) {
    throw new RuntimeException('Explicit dialect and business role required');
}
if ($dialect === 'mysql') {
    $local = parse_ini_file((string)getenv('POC_MYSQL_LOCAL_ENV'), true, INI_SCANNER_RAW);
    $config = $local[$role === 'ai' ? 'DATABASE' : 'DATABASE_ZHCT'] ?? null;
    if (!is_array($config)) throw new RuntimeException('Selected local config unavailable');
    $host = (string)$config['HOSTNAME'];
    $port = (int)$config['HOSTPORT'];
    $schema = (string)$config['DATABASE'];
    $user = (string)$config['USERNAME'];
    $password = (string)$config['PASSWORD'];
    $dsn = "mysql:host=$host;port=$port;dbname=$schema;charset=utf8mb4";
} else {
    $prefix = $role === 'ai' ? 'POC_AI_' : 'POC_';
    $host = (string)getenv($prefix . 'HOST');
    $port = (int)getenv($prefix . 'PORT');
    $schema = (string)getenv($prefix . 'SCHEMA');
    $user = (string)getenv($prefix . 'USER');
    $password = (string)getenv($prefix . 'PASSWORD');
    if ($host === '' || $port <= 0 || $schema === '' || $user === '' || $password === '') {
        throw new RuntimeException('Approved non-production DM environment unavailable');
    }
    $dsn = "dm:host=$host;port=$port;schema=$schema";
}
$pdo = new PDO($dsn, $user, $password, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_STRINGIFY_FETCHES => $stringify,
    PDO::ATTR_EMULATE_PREPARES => false,
]);
$cases = [
    'constants' => 'SELECT CAST(1.20 AS DECIMAL(5,2)) AS DECIMAL_LITERAL,'
        . ' 7 AS INTEGER_LITERAL, 1.25E0 AS FLOATING_LITERAL,'
        . ' NULL AS NULL_LITERAL FROM DUAL',
    'aggregate' => 'SELECT SUM(CAST(1.20 AS DECIMAL(5,2))) AS SUM_DECIMAL,'
        . ' COUNT(*) AS COUNT_ROWS,'
        . ' AVG(CAST(1.20 AS DECIMAL(5,2))) AS AVG_DECIMAL FROM DUAL',
    'empty_aggregate' => 'SELECT SUM(CAST(1.20 AS DECIMAL(5,2))) AS SUM_EMPTY,'
        . ' COUNT(*) AS COUNT_EMPTY FROM DUAL WHERE 1=0',
    'precision_constants' => "SELECT CAST('9007199254740993.01' AS DECIMAL(30,2)) AS LARGE_DECIMAL,"
        . ($dialect === 'mysql'
            ? " CAST('9223372036854775807' AS SIGNED) AS INT64_MAX,"
            : " CAST('9223372036854775807' AS BIGINT) AS INT64_MAX,")
        . " CAST('0.00' AS DECIMAL(30,2)) AS DECIMAL_ZERO FROM DUAL",
    'precision_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 FROM DUAL",
    'precision_column_shapes' => "SELECT"
        . " CAST('9007199254740993' AS DECIMAL(20,0)) AS DECIMAL20_OVER_2P53,"
        . " CAST(CAST('9007199254740993' AS DECIMAL(20,0)) AS VARCHAR(40)) AS EXACT_OVER_2P53,"
        . " CAST('9223372036854775807' AS DECIMAL(20,0)) AS DECIMAL20_INT64_MAX,"
        . " CAST(CAST('9223372036854775807' AS DECIMAL(20,0)) AS VARCHAR(40)) AS EXACT_INT64_MAX,"
        . " CAST('18446744073709551615' AS DECIMAL(20,0)) AS DECIMAL20_UINT64_MAX,"
        . " CAST(CAST('18446744073709551615' AS DECIMAL(20,0)) AS VARCHAR(40)) AS EXACT_UINT64_MAX,"
        . " CAST('1700000000.123456' AS DECIMAL(16,6)) AS DECIMAL16_MICROTIME,"
        . " CAST(CAST('1700000000.123456' AS DECIMAL(16,6)) AS VARCHAR(40)) AS EXACT_MICROTIME FROM DUAL",
];
if ($dialect === 'dm') {
    $cases['float_cast'] = 'SELECT CAST(1.25 AS FLOAT) AS FLOAT_CAST FROM DUAL';
}
if ($role === 'ai') {
    $table = $dialect === 'dm' ? 'YOSHOP_CONFIG_ENUM' : 'yoshop_config_enum';
    $cases['config_enum_column'] = 'SELECT RATIO AS RATIO_DECIMAL, ID AS ID_INTEGER'
        . " FROM $table WHERE ID=(SELECT MIN(ID) FROM $table)";
    $cases['config_enum_aggregate'] = 'SELECT SUM(RATIO) AS SUM_RATIO,'
        . " COUNT(*) AS COUNT_ROWS FROM $table WHERE ENUM_TYPE='2'";
}
$results = [];
foreach ($cases as $label => $sql) {
    try {
        $statement = $pdo->query($sql);
        $count = $statement->columnCount();
        $meta = [];
        for ($index = 0; $index < $count; $index++) {
            try {
                $raw = $statement->getColumnMeta($index);
                if ($raw === false) {
                    $meta[] = ['index' => $index, 'supported' => false];
                    continue;
                }
                $selected = [];
                foreach (['name', 'native_type', 'pdo_type', 'len', 'precision', 'scale',
                    'flags', 'table'] as $key) {
                    if (array_key_exists($key, $raw)) $selected[$key] = $raw[$key];
                }
                $meta[] = ['index' => $index, 'supported' => true,
                    'keys' => array_keys($raw), 'selected' => $selected];
            } catch (Throwable $error) {
                $meta[] = ['index' => $index, 'supported' => false,
                    'error_class' => get_class($error), 'error_code' => $error->getCode()];
            }
        }
        $row = $statement->fetch(PDO::FETCH_NUM);
        foreach ($meta as $index => &$column) {
            $value = $row === false ? null : ($row[$index] ?? null);
            $column['row_present'] = $row !== false;
            $column['value_is_null'] = $value === null;
            $column['php_value_type'] = gettype($value);
            if (strpos($label, 'precision_') === 0) {
                $column['synthetic_value_string'] = $value === null ? null : (string)$value;
                if (is_float($value)) {
                    $column['synthetic_float_17_digits'] = sprintf('%.17g', $value);
                }
            }
        }
        unset($column);
        $results[$label] = ['status' => 'ok', 'columns' => $meta];
    } catch (Throwable $error) {
        $results[$label] = ['status' => 'error',
            'error_class' => get_class($error), 'error_code' => $error->getCode()];
    }
}
$mysqlHealth = null;
if ($dialect === 'mysql') {
    $wanted = ['Threads_connected', 'Threads_running', 'Max_used_connections',
        'Aborted_clients', 'Aborted_connects', 'Uptime'];
    $mysqlHealth = [];
    try {
        $statusSql = "SHOW GLOBAL STATUS WHERE Variable_name IN ('Threads_connected',"
            . "'Threads_running','Max_used_connections','Aborted_clients',"
            . "'Aborted_connects','Uptime')";
        foreach ($pdo->query($statusSql) as $status) {
            $name = (string)$status['Variable_name'];
            if (in_array($name, $wanted, true)) {
                $mysqlHealth[$name] = (int)$status['Value'];
            }
        }
        foreach ($pdo->query("SHOW GLOBAL VARIABLES LIKE 'max_connections'") as $variable) {
            $mysqlHealth['max_connections'] = (int)$variable['Value'];
        }
    } catch (Throwable $error) {
        $mysqlHealth = ['error_class' => get_class($error), 'error_code' => $error->getCode()];
    }
}
echo json_encode(['dialect' => $dialect, 'role' => $role,
    'php_version' => PHP_VERSION, 'pdo_driver' => $pdo->getAttribute(PDO::ATTR_DRIVER_NAME),
    'requested_stringify_fetches' => $stringify,
    'cases' => $results, 'mysql_health' => $mysqlHealth],
    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
