<?php

declare(strict_types=1);

// Read only the isolated C response log and nonproduction DM Store source.
if (($argv[1] ?? '') !== '--read-only'
    || (string)getenv('POC_SCHEMA') !== 'ZHCT_APP'
    || (string)getenv('POC_HOST') !== '127.0.0.1'
    || (string)getenv('POC_PORT') !== '5237') exit(78);
set_exception_handler(static function (Throwable $e): void {
    fwrite(STDERR, 'Small5 C diagnostic failed ' . get_class($e) . ':'
        . hash('sha256', $e->getMessage()) . PHP_EOL);
    exit(1);
});
$root = '/tmp/zhct-dm-poc-20260928.fcpiiN/store';
$lines = file($root . '/runtime/log/202610/04.log', FILE_IGNORE_NEW_LINES);
if (!is_array($lines)) throw new RuntimeException('C report log unreadable');
$response = null;
foreach ($lines as $i => $line) {
    if (strpos($line, 'POST 127.0.0.1:18080/p/Ontoanalysis/StaffInfo') === false) continue;
    foreach (array_slice($lines, $i + 1, 5) as $after) {
        if (strpos($after, '[ log ] ') !== 0) continue;
        $decoded = json_decode(substr($after, 8), true);
        if (is_array($decoded)) $response = $decoded;
        break;
    }
}
if (!is_array($response) || ($response['code'] ?? null) !== 0
    || !is_array($response['data'] ?? null)) {
    throw new RuntimeException('C StaffInfo business log absent');
}
$actual = $response['data'];
$db = new PDO('dm:host=127.0.0.1;port=5237;schema=ZHCT_APP',
    (string)getenv('POC_USER'), (string)getenv('POC_PASSWORD'),
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_TIMEOUT => 5]);
$identity = 'ZHCT_APP|5237|' . (string)$db->query(
    "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn();
if (hash('sha256', $identity)
    !== 'bc98485aed26beab348770a82ae38dbf922b04ab88a210cd7282c4caf0156194') {
    throw new RuntimeException('C diagnostic DB identity drift');
}
$candidate = (string)$db->query('SELECT UUID FROM YDY_STAFF WHERE ID=2')->fetchColumn();
if (substr(hash('sha256', $candidate), 0, 12) !== '407d05f42f03') {
    throw new RuntimeException('C diagnostic staff source drift');
}
$sql = 'SELECT a.UUID,a.NAME,a.HEAD_IMG,a.SEX,a.HEIGHT,a.BIRTHDAY,a.WEIGHT,'
    . ' f.UUID D_UUID,f.NAME D_NAME,c.NAME S_NAME,a.SPORT_EVENT_UUID,'
    . ' IFNULL(b.STATUS,2) STATUS,a.GRADE,a.SPORT_UUID'
    . ' FROM YDY_STAFF a'
    . ' LEFT JOIN YDY_MEMBER_WEIGHT_STATUS b ON a.UUID=b.STAFF_UUID'
    . ' LEFT JOIN YDY_SPORT c ON a.SPORT_UUID=c.UUID'
    . ' LEFT JOIN YDY_STAFF_DEPARTMENT sd ON a.UUID=sd.STAFF_UUID'
    . ' LEFT JOIN YDY_DEPARTMENT f ON sd.DEPARTMENT_UUID=f.UUID'
    . ' WHERE a.UUID=? ORDER BY b.ID DESC FETCH FIRST 1 ROW ONLY';
$stmt = $db->prepare($sql);
$stmt->execute([$candidate]);
$source = $stmt->fetch(PDO::FETCH_ASSOC);
if (!is_array($source)) throw new RuntimeException('C joined source row absent');
foreach ($source as $key => $value) {
    if (is_resource($value)) $source[$key] = stream_get_contents($value);
}
$metaStmt = $db->prepare('SELECT DATA_TYPE,DATA_PRECISION,DATA_SCALE,NULLABLE'
    . ' FROM USER_TAB_COLUMNS WHERE TABLE_NAME=? AND COLUMN_NAME=?');
$metaStmt->execute(['YDY_STAFF', 'HEIGHT']);
$heightMeta = $metaStmt->fetch(PDO::FETCH_ASSOC);
if (!is_array($heightMeta)) throw new RuntimeException('C HEIGHT metadata absent');
$aTypes = ['age' => 'integer', 'birthday' => 'string', 'd_name' => 'string',
    'd_uuid' => 'string', 'grade' => 'integer', 'head_img' => 'string',
    'height' => 'string', 'name' => 'string', 's_name' => 'string',
    'sex' => 'integer', 'sport_event_uuid' => 'string',
    'sport_uuid' => 'string', 'status' => 'string', 'uuid' => 'string',
    'weight' => 'number-by-value', 'y_name' => 'string'];
$actualTypes = array_map('gettype', $actual);
ksort($actualTypes);
$valueMismatches = [];
$literalMismatches = [];
foreach (['uuid', 'name', 'sex', 'height', 'birthday', 'weight',
    'd_uuid', 'd_name', 's_name', 'status', 'grade', 'sport_uuid'] as $key) {
    $left = $actual[$key] ?? null;
    $right = $source[$key] ?? null;
    if ((string)$left !== (string)$right) $literalMismatches[] = $key;
    $equal = in_array($key, ['height', 'weight'], true)
        && is_numeric($left) && is_numeric($right)
        ? bccomp((string)$left, (string)$right, 2) === 0
        : (string)$left === (string)$right;
    if (!$equal) $valueMismatches[] = $key;
}
$typeDifferences = [];
$contractMismatches = [];
foreach ($aTypes as $key => $expected) {
    $actualType = $actualTypes[$key] ?? 'missing';
    if ($actualType !== $expected) $typeDifferences[$key] =
        ['a' => $expected, 'c' => $actualType];
    if ($key === 'weight') {
        $integral = bccomp((string)$source['weight'],
            bcadd((string)$source['weight'], '0', 0), 2) === 0;
        $expected = $integral ? 'integer' : 'double';
    }
    if ($actualType !== $expected) $contractMismatches[$key] =
        ['expected' => $expected, 'actual' => $actualType];
}
$heightActual = $actual['height'] ?? null;
$heightRaw = $source['height'] ?? null;
echo json_encode(['route' => 'StaffInfo', 'http_log_response_code' => $response['code'],
    'height_column' => ['type' => $heightMeta['data_type'],
        'precision' => $heightMeta['data_precision'],
        'scale' => $heightMeta['data_scale'],
        'nullable' => $heightMeta['nullable']],
    'height' => ['actual_type' => gettype($heightActual),
        'raw_pdo_type' => gettype($heightRaw),
        'actual_strict_two_decimal_string' => is_string($heightActual)
            && preg_match('/^-?\d+\.\d{2}$/D', $heightActual) === 1,
        'literal_string_equal_to_raw_pdo' =>
            (string)$heightActual === (string)$heightRaw,
        'actual_sha12' => substr(hash('sha256', (string)$heightActual), 0, 12),
        'raw_sha12' => substr(hash('sha256', (string)$heightRaw), 0, 12),
        'bc_equal_at_scale2' => is_numeric($heightActual) && is_numeric($heightRaw)
            && bccomp((string)$heightActual, (string)$heightRaw, 2) === 0],
    'core_value_mismatch_fields' => $valueMismatches,
    'first_literal_mismatch_field' => $literalMismatches[0] ?? null,
    'literal_mismatch_fields' => $literalMismatches,
    'a_vs_c_type_difference_fields' => $typeDifferences,
    'a_contract_mismatch_fields' => $contractMismatches,
    'c_response_field_types' => $actualTypes,
    'business_http_executed' => false, 'dml_executed' => false],
    JSON_UNESCAPED_SLASHES), PHP_EOL;
