<?php
declare(strict_types=1);

// Fixed read-only probe: no application authentication, writes, or natural rows.
$lane = $argv[1] ?? '';
if (!in_array($lane, ['B', 'C'], true)) throw new RuntimeException('Explicit lane required');
$pdoParams = [PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, PDO::ATTR_STRINGIFY_FETCHES => false,
    PDO::ATTR_EMULATE_PREPARES => false];
if ($lane === 'B') {
    $local = parse_ini_file('/workspace/zhct/zhctproject/ai_api/.env.local', true, INI_SCANNER_RAW);
    if (!is_array($local) || !isset($local['DATABASE'])) throw new RuntimeException('Local config unavailable');
    $c = $local['DATABASE'];
    $charset = (string)($c['CHARSET'] ?? '');
    if ($charset !== 'utf8') throw new RuntimeException('Effective local charset changed; review required');
    $dsn = 'mysql:host=' . $c['HOSTNAME'] . ';port=' . ($c['HOSTPORT'] ?: '3306')
        . ';dbname=' . $c['DATABASE'] . ';charset=' . $charset;
    $db = new PDO($dsn, $c['USERNAME'], $c['PASSWORD'], $pdoParams);
    $expectedSchema = $c['DATABASE'];
} else {
    if (getenv('POC_AI_HOST') !== '127.0.0.1' || getenv('POC_AI_PORT') !== '5238'
        || getenv('POC_AI_SCHEMA') !== 'AIZHCT_APP' || getenv('POC_AI_USER') !== 'AIZHCT_APP') {
        throw new RuntimeException('Approved AI test connection identity changed');
    }
    $db = new PDO('dm:host=127.0.0.1;port=5238;schema=AIZHCT_APP', getenv('POC_AI_USER'), getenv('POC_AI_PASSWORD'), $pdoParams);
    $expectedSchema = 'AIZHCT_APP';
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$journal = [];
$read = static function (string $sql, array $binds = []) use ($db, &$journal): array {
    if (strpos($sql, 'SELECT ') !== 0) throw new RuntimeException('Read-only SQL required');
    $s = $db->prepare($sql);
    foreach ($binds as $i => $value) $s->bindValue($i + 1, $value, PDO::PARAM_STR);
    $s->execute();
    $rows = $s->fetchAll(PDO::FETCH_ASSOC);
    $journal[] = ['SQL' => $sql, 'binds' => array_map(static function ($v) { return ['value' => $v, 'PDO_type' => PDO::PARAM_STR]; }, $binds), 'rows' => count($rows), 'errorInfo' => $s->errorInfo()];
    return $rows;
};
$identity = $lane === 'B'
    ? $read('SELECT DATABASE() AS current_schema, VERSION() AS version')
    : $read("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') AS current_schema FROM DUAL");
if (count($identity) !== 1 || $identity[0]['current_schema'] !== $expectedSchema) throw new RuntimeException('Schema mismatch');
if ($lane === 'B' && strpos((string)$identity[0]['version'], '5.6.') !== 0) throw new RuntimeException('Not MySQL 5.6');
$columns = $lane === 'B'
    ? $read("SELECT COLUMN_NAME,COLUMN_TYPE,IS_NULLABLE,COLUMN_DEFAULT,EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='yoshop_rope_skipping' AND COLUMN_NAME='stopped_at'")
    : $read("SELECT COLUMN_NAME,DATA_TYPE,DATA_PRECISION,DATA_SCALE,NULLABLE,DATA_DEFAULT FROM USER_TAB_COLUMNS WHERE TABLE_NAME='YOSHOP_ROPE_SKIPPING' AND COLUMN_NAME='STOPPED_AT'");
if (count($columns) !== 1) throw new RuntimeException('Exact source column missing');
if ($lane === 'B' && ($columns[0]['column_type'] !== 'bigint(13) unsigned' || $columns[0]['is_nullable'] !== 'NO')) throw new RuntimeException('Source contract changed');
if ($lane === 'C' && (strtoupper($columns[0]['data_type']) !== 'DECIMAL' || (int)$columns[0]['data_precision'] !== 20 || (int)$columns[0]['data_scale'] !== 0 || $columns[0]['nullable'] !== 'N')) throw new RuntimeException('Target contract changed');
$empty = $read($lane === 'B'
    ? 'SELECT stopped_at FROM yoshop_rope_skipping WHERE 1=0'
    : 'SELECT STOPPED_AT FROM AIZHCT_APP.YOSHOP_ROPE_SKIPPING WHERE 1=0');
if ($empty !== []) throw new RuntimeException('Zero-row projection failed');
$values = ['0', '1790000000123', '9007199254740991', '9007199254740993', '9223372036854775807', '18446744073709551615'];
$sql = $lane === 'B'
    ? 'SELECT CAST(? AS UNSIGNED) AS stopped_at,CAST(CAST(? AS UNSIGNED) AS CHAR) AS exact_stopped_at_internal'
    : 'SELECT CAST(? AS DECIMAL(20,0)) AS stopped_at,CAST(CAST(? AS DECIMAL(20,0)) AS VARCHAR(40)) AS exact_stopped_at_internal FROM DUAL';
$observations = [];
foreach ($values as $text) {
    $rows = $read($sql, [$text, $text]);
    if (count($rows) !== 1 || $rows[0]['exact_stopped_at_internal'] !== $text) throw new RuntimeException('Exact server text mismatch');
    $row = $rows[0];
    $observations[] = ['input' => $text, 'native_type' => gettype($row['stopped_at']),
        'native_wire_literal' => json_encode($row['stopped_at']),
        'native_double_be_hex' => is_float($row['stopped_at']) ? bin2hex(pack('E', $row['stopped_at'])) : null,
        'original_service_cast_literal' => json_encode((int)$row['stopped_at']),
        'exact_text' => $row['exact_stopped_at_internal'],
        'source_preserving_cast_literal' => json_encode((int)$row['exact_stopped_at_internal'])];
}
echo json_encode(['probe_revision' => 2, 'explicit_framework_PDO_params' => $pdoParams,
    'lane' => $lane, 'approved_schema_verified' => true,
    'source_mysql56_verified' => $lane === 'B', 'connection_charset' => $lane === 'B' ? 'utf8' : 'original-approved-driver-environment',
    'column_contract' => $columns, 'observations' => $observations,
    'read_journal' => $journal, 'SELECT' => count($journal), 'DML' => 0, 'DDL' => 0, 'HTTP' => 0,
    'natural_rows_read' => 0], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), "\n";
