<?php

declare(strict_types=1);

// Bounded nonproduction Store report-read harness; default mode is SELECT-only.
$lane = (string)getenv('CDX_REPORT_LANE');
$action = (string)($argv[1] ?? '');
$targets = [
    'A' => ['/tmp/zhct-http-store-a.l5omH8', 'http://127.0.0.1:18097', 21023, 'mysql',
        '04e3f80cb0dddff6ec657f731185013ffffebcb4da48be8402b6d86547e14742',
        '95ce9bcee0f908ace8c86c1978ed9e41791e56a3ab53d53de17972d12e908341'],
    'B' => ['/tmp/zhct-http-store-mysql.dQTTBP', 'http://127.0.0.1:18081', 10001, 'mysql',
        '0581772a6831c86210372684867a5da5cb722855ef52ebfaf6776e1a6f971702',
        '8953e4be37bb3a1f6adf40c9da9b19de5e3eb2f61d595812b080a66bec10b7c2'],
    'C' => ['/tmp/zhct-dm-poc-20260928.fcpiiN/store', 'http://127.0.0.1:18080', 112175, 'dm',
        '0581772a6831c86210372684867a5da5cb722855ef52ebfaf6776e1a6f971702',
        '8953e4be37bb3a1f6adf40c9da9b19de5e3eb2f61d595812b080a66bec10b7c2'],
];
if (!isset($targets[$lane]) || !in_array($action,
        ['--preflight', '--preflight-dish', '--preflight-recharge',
            '--execute', '--execute-dish', '--execute-recharge'], true)
    || (!in_array($action, ['--preflight', '--preflight-dish', '--preflight-recharge'], true)
        && ((string)getenv('CDX_REPORT_EXECUTE') !== 'ROOT_APPROVED_READ3_V2'
            || (string)getenv('CDX_REPORT_SHA') !== hash_file('sha256', __FILE__)))) {
    fwrite(STDERR, "Report read execution disabled\n");
    exit(78);
}
[$root, $base, $pid, $dialect, $mealLogicSha, $userSha] = $targets[$lane];
if ((string)getenv('POC_APP_ROOT') !== $root
    || (string)getenv('POC_BASE_URL') !== $base
    || (string)getenv('POC_DIALECT') !== $dialect
    || is_link($root)
    || hash_file('sha256', $root . '/application/p/controller/Report.php')
        !== '1673113e55dc7f247f697a77ece16ebdb21d1572d8a202c40abb8764cbc83f7e'
    || hash_file('sha256', $root . '/application/p/logic/MealOrder.php') !== $mealLogicSha
    || (in_array($action, ['--preflight-recharge', '--execute-recharge'], true)
        && hash_file('sha256', $root . '/application/p/logic/RechargeOrder.php')
            !== ($lane === 'A'
                ? '8a89a807aef486303dfab7b660d7136d1bdc21886b9f63b2dc60751166f797f5'
                : '100b405138ffc62336202fd65ea6a1838fc2a84288fdec58d33d531436123462'))
    || hash_file('sha256', $root . '/application/model/User.php') !== $userSha) {
    throw new RuntimeException('Approved report source/runtime mismatch');
}
$runtimeReady = static function () use ($root, $base, $pid): bool {
    $cmdline = (string)@file_get_contents('/proc/' . $pid . '/cmdline');
    $environment = (string)@file_get_contents('/proc/' . $pid . '/environ');
    $children = (string)@file_get_contents('/proc/' . $pid . '/task/' . $pid . '/children');
    $boundary = json_decode((string)@file_get_contents($base . '/__poc_boundary'), true);
    $port = (int)parse_url($base, PHP_URL_PORT);
    $hex = strtoupper(str_pad(dechex($port), 4, '0', STR_PAD_LEFT));
    $socketInode = '';
    foreach (@file('/proc/net/tcp', FILE_IGNORE_NEW_LINES) ?: [] as $line) {
        $parts = preg_split('/\s+/', trim($line));
        if (($parts[1] ?? '') === '0100007F:' . $hex
            && ($parts[3] ?? '') === '0A') {
            $socketInode = (string)($parts[9] ?? '');
            break;
        }
    }
    $ownsPort = false;
    if ($socketInode !== '') {
        foreach (@scandir('/proc/' . $pid . '/fd') ?: [] as $fd) {
            if ($fd === '.' || $fd === '..') continue;
            if (@readlink('/proc/' . $pid . '/fd/' . $fd)
                === 'socket:[' . $socketInode . ']') {
                $ownsPort = true;
                break;
            }
        }
    }
    $multiWorker = preg_match('/(?:^|\x00)PHP_CLI_SERVER_WORKERS=(\d+)(?:\x00|$)/',
        $environment, $match) && (int)$match[1] > 1;
    return strpos($cmdline, '127.0.0.1:' . $port) !== false
        && strpos($cmdline, $root . '/public') !== false
        && $environment !== '' && trim($children) === '' && !$multiWorker
        && $ownsPort && is_array($boundary)
        && !empty($boundary['external_stubs'])
        && !empty($boundary['redis_isolated']) && empty($boundary['real_queue']);
};
if (!$runtimeReady()) throw new RuntimeException('Report isolated HTTP boundary absent');
$runtime = (static function (string $path): array {
    $value = require $path;
    if (!is_array($value)) throw new RuntimeException('Invalid report DB config');
    return $value;
})($root . '/application/database.php');
if ((string)($runtime['prefix'] ?? '') !== 'ydy_') {
    throw new RuntimeException('Report table prefix mismatch');
}
if ($dialect === 'mysql') {
    $local = (static function (): array {
        $value = require '/workspace/zhct/zhctproject/store/application/config/local/database.php';
        if (!is_array($value)) throw new RuntimeException('Invalid local report DB config');
        return $value;
    })();
    if ((string)($runtime['type'] ?? '') !== 'mysql'
        || !in_array((string)($runtime['charset'] ?? ''), ['utf8', 'utf8mb4'], true)) {
        throw new RuntimeException('Report MySQL driver/charset mismatch');
    }
    foreach (['hostname', 'database', 'username', 'password'] as $key) {
        if (($runtime[$key] ?? null) !== ($local[$key] ?? null)) {
            throw new RuntimeException('Report runtime differs from code local');
        }
    }
    if ((int)($runtime['hostport'] ?? 3306) !== (int)($local['hostport'] ?? 3306)) {
        throw new RuntimeException('Report MySQL port mismatch');
    }
    $dsn = 'mysql:host=' . $runtime['hostname'] . ';port='
        . (int)($runtime['hostport'] ?? 3306) . ';dbname=' . $runtime['database']
        . ';charset=' . (string)$runtime['charset'];
    $username = (string)$runtime['username'];
    $password = (string)$runtime['password'];
} else {
    if ((string)($runtime['type'] ?? '') !== 'app\\cores\\database\\Dm'
        || (string)getenv('POC_HOST') !== '127.0.0.1'
        || (string)getenv('POC_PORT') !== '5237'
        || strtoupper((string)getenv('POC_SCHEMA')) !== 'ZHCT_APP'
        || strtoupper((string)getenv('POC_USER')) !== 'ZHCT_APP') {
        throw new RuntimeException('Report DM target mismatch');
    }
    foreach (['hostname' => 'POC_HOST', 'hostport' => 'POC_PORT',
        'database' => 'POC_SCHEMA', 'username' => 'POC_USER',
        'password' => 'POC_PASSWORD'] as $key => $envKey) {
        if ((string)($runtime[$key] ?? '') !== (string)getenv($envKey)) {
            throw new RuntimeException('Report DM worker context mismatch');
        }
    }
    $dsn = 'dm:host=127.0.0.1;port=5237;schema=ZHCT_APP';
    $username = (string)getenv('POC_USER');
    $password = (string)getenv('POC_PASSWORD');
}
$connect = static function () use ($dsn, $username, $password): PDO {
    return new PDO($dsn, $username, $password,
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_TIMEOUT => 5]);
};
try {
    $db = $connect();
} catch (Throwable $e) {
    fwrite(STDERR, 'Report database connection failed: ' . get_class($e) . PHP_EOL);
    exit(75);
}
if ($dialect === 'mysql') {
    $identity = (string)$db->query("SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")
        ->fetchColumn();
    $hostFingerprint = null;
    $dmListenerLocal = null;
} else {
    $schema = (string)$db->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")
        ->fetchColumn();
    if (strtoupper($schema) !== 'ZHCT_APP') throw new RuntimeException('Report DM schema mismatch');
    $identity = 'ZHCT_APP|5237|' . $schema;
    $machineId = trim((string)@file_get_contents('/etc/machine-id'));
    if ($machineId === '' || gethostname() === false) throw new RuntimeException('DM host unknown');
    $hostFingerprint = hash('sha256', gethostname() . '|' . $machineId);
    $lines = [];
    $exit = 0;
    @exec('/usr/sbin/ss -ltnp 2>/dev/null', $lines, $exit);
    $dmListenerLocal = false;
    if ($exit === 0) foreach ($lines as $line) {
        if (preg_match('/\*:5237\s+.*users:\(\("dmserver",pid=(\d+),/',
            $line, $match)) {
            $exe = @readlink('/proc/' . $match[1] . '/exe');
            $dmListenerLocal = is_string($exe) && basename($exe) === 'dmserver';
            break;
        }
    }
    if (!$dmListenerLocal) throw new RuntimeException('Report DM listener not local');
}
$dbFingerprint = hash('sha256', $identity);
$approvedDbFingerprint = $dialect === 'mysql'
    ? '003eb5aecf1cd4595b609c1f7f20b9ee325b578309fb9fe14fedaf77584fa401'
    : 'bc98485aed26beab348770a82ae38dbf922b04ab88a210cd7282c4caf0156194';
if (!hash_equals($approvedDbFingerprint, $dbFingerprint)
    || ($dialect === 'dm' && $hostFingerprint
        !== 'd56d81988bb0f106946cce91c608fdd0ef1116e5150b23376ea87e086eace4b9')) {
    throw new RuntimeException('Database identity differs from independently approved target');
}
if (in_array($action, ['--execute', '--execute-dish'], true)
    && ((string)getenv('CDX_REPORT_DB_SHA') !== $dbFingerprint
        || ($dialect === 'dm'
            && (string)getenv('CDX_REPORT_HOST_SHA') !== $hostFingerprint))) {
    throw new RuntimeException('Approved report DB/host fingerprint differs');
}
$prefix = $dialect === 'dm' ? 'YDY_' : 'ydy_';
$candidateSql = 'SELECT menu.ID AS MENU_ID,menu.MENU_DATE,menu.NUMBER,'
    . ' meal.ID AS MEAL_ID,meal.BIND_TIME,meal.MEAL_DATE,meal.RESTAURANT_ID'
    . ' FROM ' . $prefix . 'initial_menu menu JOIN ' . $prefix . 'meal_order meal'
    . ' ON meal.ID=menu.MEAL_ORDER_ID JOIN ' . $prefix . 'dishes d'
    . ' ON d.UUID=menu.DISHES_UUID WHERE meal.ORDER_STATUS=30'
    . ' AND meal.REFUND_STATUS IN (0,1,2) AND meal.IS_DELETE=0';
if ($dialect === 'dm') {
    $candidateSql .= ' AND ROWNUM=1';
} else {
    $candidateSql .= ' ORDER BY menu.ID DESC LIMIT 1';
}
$candidate = $db->query($candidateSql)->fetch(PDO::FETCH_ASSOC) ?: [];
$menuDate = substr((string)($candidate['menu_date'] ?? ''), 0, 10);
$bindDate = substr((string)($candidate['bind_time'] ?? ''), 0, 10);
$restaurantId = (int)($candidate['restaurant_id'] ?? 0);
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $menuDate)
    || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $bindDate)
    || $restaurantId <= 0) {
    throw new RuntimeException('No bounded completed order/menu fixture');
}
$joinRowsSql = 'SELECT menu.ID AS MENU_ID,meal.ID AS MEAL_ID,menu.NUMBER,'
    . ' menu.DISHES_UUID AS DISH_UUID,d.NAME AS DISH_NAME,'
    . ' menu.MEAL_TIMES AS MENU_MEAL_TIMES,'
    . ' meal.PAY_PRICE,meal.REFUND_AMOUNT FROM '
    . $prefix . 'initial_menu menu JOIN ' . $prefix . 'meal_order meal'
    . ' ON meal.ID=menu.MEAL_ORDER_ID JOIN ' . $prefix . 'dishes d'
    . ' ON d.UUID=menu.DISHES_UUID WHERE meal.ORDER_STATUS=30'
    . ' AND meal.REFUND_STATUS IN (0,1,2) AND meal.IS_DELETE=0'
    . ' AND menu.MENU_DATE=? AND meal.RESTAURANT_ID=?';
$mealRowsSql = 'SELECT meal.ID,meal.PAY_PRICE,meal.REFUND_AMOUNT,meal.MEAL_TIMES'
    . ' FROM ' . $prefix . 'meal_order meal WHERE meal.ORDER_STATUS=30'
    . ' AND meal.REFUND_STATUS IN (0,1,2) AND meal.IS_DELETE=0'
    . ' AND meal.BIND_TIME BETWEEN ? AND ? AND meal.RESTAURANT_ID=?';
if ($dialect === 'dm') {
    $joinRowsSql .= ' AND ROWNUM<=1001 ORDER BY menu.ID';
    $mealRowsSql .= ' AND ROWNUM<=1001 ORDER BY meal.ID';
} else {
    $joinRowsSql .= ' ORDER BY menu.ID LIMIT 1001';
    $mealRowsSql .= ' ORDER BY meal.ID LIMIT 1001';
}
$fetch = static function (PDO $pdo, string $sql, array $args): array {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
};
$joinArgs = [$menuDate, $restaurantId];
$mealArgs = [$bindDate . ' 00:00:00', $bindDate . ' 23:59:59', $restaurantId];
$joinRows = $fetch($db, $joinRowsSql, $joinArgs);
$mealRows = $fetch($db, $mealRowsSql, $mealArgs);
if (!$joinRows || !$mealRows || count($joinRows) > 1000 || count($mealRows) > 1000) {
    throw new RuntimeException('Report source empty or exceeds 1000-row bound');
}
$sourceBefore = ['menu' => hash('sha256', serialize($joinRows)),
    'meal' => hash('sha256', serialize($mealRows))];
$money = static function ($value): string {
    return number_format((float)$value, 2, '.', '');
};
$dishExpected = array_fill_keys(['breakfast', 'lunch', 'dinner', 'snack', 'total'], 0.0);
$dishGroups = [];
foreach ($joinRows as $row) {
    $amount = (float)$row['number'];
    $dishExpected['total'] += $amount;
    $groupKey = (string)$row['dish_uuid'];
    if (!isset($dishGroups[$groupKey])) {
        $dishGroups[$groupKey] = ['dish_name' => (string)$row['dish_name']]
            + array_fill_keys(['breakfast', 'lunch', 'dinner', 'snack', 'total'], 0.0);
    }
    $dishGroups[$groupKey]['total'] += $amount;
    $mealTime = (int)$row['menu_meal_times'];
    if ($mealTime >= 1 && $mealTime <= 4) {
        $field = ['breakfast', 'lunch', 'dinner', 'snack'][$mealTime - 1];
        $dishExpected[$field] += $amount;
        $dishGroups[$groupKey][$field] += $amount;
    }
}
foreach ($dishExpected as &$value) $value = $money($value);
unset($value);
foreach ($dishGroups as &$group) {
    foreach (['breakfast', 'lunch', 'dinner', 'snack', 'total'] as $field) {
        $group[$field] = $money($group[$field]);
    }
}
unset($group);
if (count($dishGroups) > 15) {
    throw new RuntimeException('Dish group fixture exceeds one report page');
}
$restaurantExpected = [];
foreach (['breakfast', 'lunch', 'dinner', 'snack', 'allday'] as $name) {
    $restaurantExpected[$name . '_count'] = 0;
    $restaurantExpected[$name . '_amount'] = 0.0;
}
foreach ($mealRows as $row) {
    $net = (float)$row['pay_price'] - (float)$row['refund_amount'];
    $restaurantExpected['allday_count']++;
    $restaurantExpected['allday_amount'] += $net;
    $mealTime = (int)$row['meal_times'];
    if ($mealTime >= 1 && $mealTime <= 4) {
        $name = ['breakfast', 'lunch', 'dinner', 'snack'][$mealTime - 1];
        $restaurantExpected[$name . '_count']++;
        $restaurantExpected[$name . '_amount'] += $net;
    }
}
foreach ($restaurantExpected as $key => &$value) {
    if (substr($key, -7) === '_amount') $value = $money($value);
}
unset($value);
$stallExpected = ['total_count' => count($mealRows),
    'total_amount' => $restaurantExpected['allday_amount']];
$matches = static function (array $actual, array $expected) use ($money): bool {
    foreach ($expected as $key => $value) {
        if (!array_key_exists($key, $actual)) return false;
        if (is_int($value)) {
            if (filter_var($actual[$key], FILTER_VALIDATE_INT) === false
                || (int)$actual[$key] !== $value) return false;
        } elseif (!is_scalar($actual[$key])
            || !is_numeric($actual[$key])
            || $money($actual[$key]) !== $value) return false;
    }
    return true;
};
$markerCount = (int)$db->query('SELECT COUNT(*) FROM ' . $prefix . 'user'
    . " WHERE ACCOUNT LIKE 'CDXRP%'")->fetchColumn();
if (in_array($action, ['--preflight', '--preflight-dish'], true)) {
    echo json_encode(['lane' => $lane, 'mode' => 'select-only-preflight',
        'db_target' => $dialect === 'dm' ? 'nonprod-dm-store' : 'code-local-dev-mysql',
        'database_fingerprint' => $dbFingerprint,
        'host_fingerprint' => $hostFingerprint,
        'dm_listener_local' => $dmListenerLocal,
        'source_join_rows' => count($joinRows),
        'source_meal_rows' => count($mealRows),
        'candidate_dates_present' => true,
        'existing_synthetic_operators' => $markerCount],
        JSON_UNESCAPED_SLASHES) . PHP_EOL;
    exit(0);
}

$recharge = null;
$aiDb = null;
if (in_array($action, ['--preflight-recharge', '--execute-recharge'], true)) {
    $aiConfig = $runtime['ai_zhct'] ?? [];
    if (!is_array($aiConfig) || !$aiConfig) {
        throw new RuntimeException('Store AI secondary configuration absent');
    }
    if ($dialect === 'mysql') {
        $localAi = $local['ai_zhct'] ?? [];
        foreach (['hostname', 'database', 'username', 'password', 'prefix'] as $key) {
            if (($aiConfig[$key] ?? null) !== ($localAi[$key] ?? null)) {
                throw new RuntimeException('AI secondary differs from code local');
            }
        }
        if ((int)($aiConfig['hostport'] ?? 3306)
            !== (int)($localAi['hostport'] ?? $local['hostport'] ?? 3306)) {
            throw new RuntimeException('AI secondary port differs from code local');
        }
        $aiDsn = 'mysql:host=' . $aiConfig['hostname'] . ';port='
            . (int)($aiConfig['hostport'] ?? 3306) . ';dbname=' . $aiConfig['database']
            . ';charset=' . (string)$runtime['charset'];
    } else {
        foreach (['hostname' => 'POC_AI_HOST', 'hostport' => 'POC_AI_PORT',
            'database' => 'POC_AI_SCHEMA', 'username' => 'POC_AI_USER',
            'password' => 'POC_AI_PASSWORD'] as $key => $envKey) {
            if ((string)($aiConfig[$key] ?? '') !== (string)getenv($envKey)) {
                throw new RuntimeException('AI secondary differs from isolated worker');
            }
        }
        if ((string)$aiConfig['hostname'] !== '127.0.0.1'
            || (int)$aiConfig['hostport'] !== 5238
            || strtoupper((string)$aiConfig['database']) !== 'AIZHCT_APP'
            || strtoupper((string)$aiConfig['username']) !== 'AIZHCT_APP') {
            throw new RuntimeException('AI secondary target outside approved DM instance');
        }
        $aiDsn = 'dm:host=127.0.0.1;port=5238;schema=AIZHCT_APP';
    }
    $connectAi = static function () use ($aiDsn, $aiConfig): PDO {
        return new PDO($aiDsn, (string)$aiConfig['username'],
            (string)$aiConfig['password'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_TIMEOUT => 5]);
    };
    try { $aiDb = $connectAi(); }
    catch (Throwable $e) {
        fwrite(STDERR, 'Approved AI database connection failed: ' . get_class($e) . PHP_EOL);
        exit(75);
    }
    $aiIdentity = $dialect === 'mysql'
        ? (string)$aiDb->query("SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")
            ->fetchColumn()
        : 'AIZHCT_APP|5238|' . (string)$aiDb->query(
            "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")
            ->fetchColumn();
    $aiApproved = $dialect === 'mysql'
        ? '210f925e093f71e26a8c8923f0f626e3be0a15ccff3d386bba21feef695c8a5b'
        : '628c12663da929e593de74c9c58e5bcfab0530fbfbcb1d90a9ed7b736a45fd5e';
    if (!hash_equals($aiApproved, hash('sha256', $aiIdentity))
        || (string)($aiConfig['prefix'] ?? '') !== 'yoshop_') {
        throw new RuntimeException('Approved AI secondary identity/prefix mismatch');
    }
    $accountSql = 'SELECT u.ACCOUNT,s.AI_USER_ID,s.NAME FROM ' . $prefix . 'user u'
        . ' JOIN ' . $prefix . 'staff s ON s.UUID=u.STAFF_UUID'
        . " WHERE u.ACCOUNT LIKE 'CDXPAY%' AND s.NAME=u.ACCOUNT";
    $accountSql .= $dialect === 'dm'
        ? ' AND ROWNUM<=50 ORDER BY u.ACCOUNT'
        : ' ORDER BY u.ACCOUNT LIMIT 50';
    $accounts = $db->query($accountSql)->fetchAll(PDO::FETCH_ASSOC);
    $aiPrefix = $dialect === 'dm' ? 'YOSHOP_' : 'yoshop_';
    $rechargeSql = 'SELECT ORDER_ID,USER_ID,PAY_METHOD,PLATFORM,PAY_PRICE,'
        . ' GIFT_MONEY,ACTUAL_MONEY,RECHARGE_DATE,PAY_STATUS,IS_DELETE FROM '
        . $aiPrefix . 'recharge_order WHERE USER_ID=? AND IS_DELETE=0'
        . ' AND PAY_STATUS=20 ORDER BY ORDER_ID DESC'
        . ($dialect === 'dm' ? ' FETCH FIRST 2 ROWS ONLY' : ' LIMIT 2');
    foreach ($accounts as $account) {
        if ((int)$account['ai_user_id'] <= 0
            || !preg_match('/^CDXPAY[A-F0-9]{8}$/D', (string)$account['account'])) continue;
        $rows = $fetch($aiDb, $rechargeSql, [(int)$account['ai_user_id']]);
        if (count($rows) !== 1) continue;
        $row = $rows[0];
        $date = substr((string)$row['recharge_date'], 0, 10);
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) continue;
        $recharge = ['account' => (string)$account['account'],
            'ai_user_id' => (int)$account['ai_user_id'],
            'date' => $date, 'row' => $row,
            'source_sha' => hash('sha256', serialize($row))];
        break;
    }
    if ($recharge === null) {
        throw new RuntimeException('No bounded synthetic completed recharge source');
    }
}
if ($action === '--preflight-recharge') {
    echo json_encode(['lane' => $lane, 'mode' => 'select-only-recharge-preflight',
        'store_database_fingerprint' => $dbFingerprint,
        'ai_database_fingerprint' => hash('sha256', $aiIdentity),
        'synthetic_recharge_source_found' => true,
        'source_date_present' => true, 'existing_synthetic_operators' => $markerCount],
        JSON_UNESCAPED_SLASHES) . PHP_EOL;
    exit(0);
}

if ($markerCount !== 0) throw new RuntimeException('Old report operator needs review');
$db->query('SELECT ID,UUID,ACCOUNT,PWD,SALT,NAME,TYPE,CREATE_TIME,CREATE_BY,IS_DELETE'
    . ' FROM ' . $prefix . 'user WHERE 1=0');
$marker = 'CDXRP' . strtoupper(bin2hex(random_bytes(8)));
$journalDir = sys_get_temp_dir() . '/zhct-report3-' . $marker;
if (file_exists($journalDir) || !mkdir($journalDir, 0700)) {
    throw new RuntimeException('Private report recovery directory unavailable');
}
chmod($journalDir, 0700);
$journal = ['lane' => $lane, 'marker' => $marker,
    'database_fingerprint' => $dbFingerprint, 'operator_id' => 0,
    'status' => 'prepared'];
$writeJournal = static function (array $changes) use (&$journal, $journalDir): void {
    $journal = array_merge($journal, $changes);
    $next = $journalDir . '/recovery.next';
    if (file_put_contents($next, json_encode($journal, JSON_UNESCAPED_SLASHES)) === false) {
        throw new RuntimeException('Report recovery journal write failed');
    }
    chmod($next, 0600);
    if (!rename($next, $journalDir . '/recovery.json')) {
        throw new RuntimeException('Report recovery journal replace failed');
    }
};
$writeJournal([]);
$operatorId = 0;
$results = [];
$failure = '';
$cleanup = [];
$httpSent = false;
$httpConfirmed = true;
try {
    $stmt = $db->prepare('SELECT COUNT(*) FROM ' . $prefix . 'user'
        . ' WHERE UUID=? OR ACCOUNT=?');
    $stmt->execute([$marker, $marker]);
    if ((int)$stmt->fetchColumn() !== 0) throw new RuntimeException('Report marker collision');
    $stmt = $db->prepare('INSERT INTO ' . $prefix . 'user'
        . ' (UUID,ACCOUNT,PWD,SALT,NAME,TYPE,CREATE_TIME,CREATE_BY,IS_DELETE)'
        . ' VALUES (?,?,?,?,?,?,?,?,?)');
    $stmt->execute([$marker, $marker, 'DISABLED', strtoupper(bin2hex(random_bytes(8))),
        $marker, 0, date('Y-m-d H:i:s'), 'CODEX', 0]);
    $stmt = $db->prepare('SELECT ID FROM ' . $prefix . 'user'
        . ' WHERE UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?');
    $stmt->execute([$marker, $marker, 'CODEX']);
    $operatorId = (int)$stmt->fetchColumn();
    if ($operatorId <= 0) throw new RuntimeException('Report operator source missing');
    $writeJournal(['status' => 'operator_inserted', 'operator_id' => $operatorId]);
    require_once $root . '/application/base/Security.php';
    $token = \app\base\Security::encrypt(implode("\t",
        [(string)$operatorId, $marker, $marker, '0', '', '', $marker]));
    if (!is_string($token) || $token === '') {
        throw new RuntimeException('Report synthetic token unavailable');
    }
    $forms = [
        'dishSalesVolumeList' => ['start_date' => $menuDate,
            'end_date' => $menuDate, 'restaurantIds' => (string)$restaurantId, 'page' => 1],
        'restaurantOperatingSummaryList' => ['start_date' => $bindDate,
            'end_date' => $bindDate, 'restaurantIds' => (string)$restaurantId, 'page' => 1],
        'stallRevenueSettlementList' => ['start_date' => $bindDate,
            'end_date' => $bindDate, 'restaurantIds' => (string)$restaurantId, 'page' => 1],
    ];
    if ($action === '--execute-dish') {
        $forms = ['dishSalesVolumeList' => $forms['dishSalesVolumeList']];
    }
    if ($action === '--execute-recharge') {
        $forms = ['rechargeStatisticList' => [
            'start_date' => $recharge['date'], 'end_date' => $recharge['date'],
            'nickname' => $recharge['account'],
            'pay_method' => (string)$recharge['row']['pay_method'], 'page' => 1]];
    }
    $allPositive = true;
    foreach ($forms as $name => $form) {
        if (!$runtimeReady()) throw new RuntimeException('Report runtime isolation drift');
        $ctx = stream_context_create(['http' => ['method' => 'POST',
            'header' => "Content-Type: application/x-www-form-urlencoded\r\n"
                . 'token: ' . $token . "\r\n",
            'content' => http_build_query($form, '', '&', PHP_QUERY_RFC3986),
            'timeout' => 20, 'ignore_errors' => true]]);
        $cap = $action === '--execute-dish' ? 256 * 1024 : 4 * 1024 * 1024;
        $httpConfirmed = false;
        $httpSent = true;
        $stream = @fopen($base . '/p/report/' . $name, 'rb', false, $ctx);
        $body = is_resource($stream)
            ? stream_get_contents($stream, $cap + 1) : false;
        $streamMeta = is_resource($stream) ? stream_get_meta_data($stream) : [];
        if (is_resource($stream)) fclose($stream);
        if (!is_string($body) || !empty($streamMeta['timed_out'])
            || strlen($body) > $cap) {
            throw new RuntimeException('Report HTTP response incomplete or exceeds bounded size');
        }
        $httpConfirmed = true;
        $headers = $http_response_header ?? [];
        preg_match('/HTTP\/\S+\s+(\d+)/', (string)($headers[0] ?? ''), $httpMatch);
        $response = is_string($body) ? json_decode($body, true) : null;
        $http = (int)($httpMatch[1] ?? 0);
        $code = is_array($response) ? ($response['code'] ?? null) : null;
        $data = is_array($response) ? ($response['data'] ?? null) : null;
        $rows = is_array($data) ? ($data['data'] ?? null) : null;
        $summary = is_array($data) ? ($data['summary'] ?? null) : null;
        $types = static function (array $value): array {
            $out = array_map('gettype', $value);
            ksort($out);
            return $out;
        };
        $responseForHash = $response;
        if (is_array($responseForHash)) unset($responseForHash['trace_id']);
        if ($name === 'rechargeStatisticList') {
            $source = $recharge['row'];
            $row = is_array($rows) && count($rows) === 1 ? $rows[0] : [];
            $fieldAmounts = ['pay_amount' => 'pay_price',
                'gift_amount' => 'gift_money',
                'recharge_amount' => 'actual_money'];
            $rowMatch = is_array($row) && $row
                && (int)($row['user_id'] ?? 0) === $recharge['ai_user_id']
                && (string)($row['pay_method'] ?? '') === (string)$source['pay_method']
                && (string)($row['platform_group'] ?? '') ===
                    ((string)$source['platform'] === 'PC' ? '线下' : '线上')
                && (string)($row['recharge_date'] ?? '') ===
                    $recharge['date'] . '至' . $recharge['date']
                && (string)($row['user']['name'] ?? '') === $recharge['account'];
            foreach ($fieldAmounts as $responseField => $sourceField) {
                if (!isset($row[$responseField]) || !is_numeric($row[$responseField])
                    || $money($row[$responseField]) !== $money($source[$sourceField])) {
                    $rowMatch = false;
                }
            }
            $summaryMatch = is_array($data)
                && (int)($data['total'] ?? 0) === 1
                && (int)($data['per_page'] ?? 0) === 15
                && isset($data['total_pay_price'], $data['total_gift_money'], $data['total_price'])
                && $money($data['total_pay_price']) === $money($source['pay_price'])
                && $money($data['total_gift_money']) === $money($source['gift_money'])
                && $money($data['total_price']) === $money($source['actual_money']);
            $positive = $http === 200 && $code === 0 && $rowMatch && $summaryMatch;
            $allPositive = $allPositive && $positive;
            $results[$name] = ['http' => $http, 'code' => $code,
                'positive' => $positive, 'row_match' => $rowMatch,
                'totals_match' => $summaryMatch,
                'rows' => is_array($rows) ? count($rows) : null,
                'top_key_types' => is_array($response) ? $types($response) : [],
                'data_key_types' => is_array($data) ? $types($data) : [],
                'first_row_key_types' => is_array($row) ? $types($row) : [],
                'response_sha256' => is_array($responseForHash)
                    ? hash('sha256', json_encode($responseForHash,
                        JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) : null];
            continue;
        }
        $expected = $name === 'dishSalesVolumeList' ? $dishExpected
            : ($name === 'restaurantOperatingSummaryList'
                ? $restaurantExpected : $stallExpected);
        $summaryMatch = is_array($summary) && $matches($summary, $expected);
        $rowMatch = is_array($rows) && count($rows) > 0;
        $remainingDishGroups = array_values($dishGroups);
        if ($name === 'dishSalesVolumeList' && $rowMatch) {
            $rowMatch = count($rows) === count($remainingDishGroups);
        }
        if ($rowMatch) {
            foreach ($rows as $row) {
                if (!is_array($row)) { $rowMatch = false; break; }
                $valid = $name === 'restaurantOperatingSummaryList'
                    ? substr((string)($row['date'] ?? ''), 0, 10) === $bindDate
                        && $matches($row, $restaurantExpected)
                    : (int)($row['restaurant_id'] ?? 0) === $restaurantId
                        && ($name === 'stallRevenueSettlementList'
                            ? $matches($row, $stallExpected) : true);
                if ($valid && $name === 'dishSalesVolumeList') {
                    $valid = false;
                    foreach ($remainingDishGroups as $index => $group) {
                        if ((string)($row['dish_name'] ?? '') === $group['dish_name']
                            && $matches($row, array_intersect_key($group, $dishExpected))) {
                            foreach (['breakfast', 'lunch', 'dinner', 'snack', 'total'] as $field) {
                                $number = (float)$group[$field];
                                $correctType = $number == (int)$number
                                    ? is_int($row[$field]) : is_float($row[$field]);
                                if (!$correctType) continue 2;
                            }
                            unset($remainingDishGroups[$index]);
                            $valid = true;
                            break;
                        }
                    }
                }
                if (!$valid) { $rowMatch = false; break; }
            }
            if ($name === 'dishSalesVolumeList' && $remainingDishGroups) $rowMatch = false;
        }
        $positive = $http === 200 && $code === 0
            && is_array($rows) && count($rows) > 0
            && $summaryMatch && $rowMatch;
        $allPositive = $allPositive && $positive;
        $results[$name] = [
            'http' => $http, 'code' => $code, 'positive' => $positive,
            'summary_match' => $summaryMatch, 'row_scope_match' => $rowMatch,
            'rows' => is_array($rows) ? count($rows) : null,
            'top_key_types' => is_array($response) ? $types($response) : [],
            'data_key_types' => is_array($data) ? $types($data) : [],
            'first_row_key_types' => is_array($rows) && isset($rows[0])
                ? $types($rows[0]) : [],
            'summary_key_types' => is_array($summary) ? $types($summary) : [],
            'response_sha256' => is_array($responseForHash)
                ? hash('sha256', json_encode($responseForHash,
                    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) : null,
            'message_sha12' => substr(hash('sha256',
                (string)($response['message'] ?? '')), 0, 12),
        ];
    }
    if (!$allPositive) throw new RuntimeException('Report positive branch failed');
    $token = '';
    $verifyDb = $connect();
    $joinedAfter = $fetch($verifyDb, $joinRowsSql, $joinArgs);
    $mealAfter = $fetch($verifyDb, $mealRowsSql, $mealArgs);
    if (hash('sha256', serialize($joinedAfter)) !== $sourceBefore['menu']
        || hash('sha256', serialize($mealAfter)) !== $sourceBefore['meal']) {
        throw new RuntimeException('Report source changed during read requests');
    }
    if ($recharge !== null) {
        $rechargeAfter = $fetch($aiDb,
            'SELECT ORDER_ID,USER_ID,PAY_METHOD,PLATFORM,PAY_PRICE,GIFT_MONEY,'
                . ' ACTUAL_MONEY,RECHARGE_DATE,PAY_STATUS,IS_DELETE FROM '
                . ($dialect === 'dm' ? 'YOSHOP_' : 'yoshop_')
                . 'recharge_order WHERE ORDER_ID=? AND USER_ID=?',
            [(int)$recharge['row']['order_id'], $recharge['ai_user_id']]);
        if (count($rechargeAfter) !== 1
            || hash('sha256', serialize($rechargeAfter[0])) !== $recharge['source_sha']) {
            throw new RuntimeException('Recharge source changed during read request');
        }
        $results['recharge_source_unchanged'] = true;
    }
    $results['source_unchanged'] = true;
} catch (Throwable $e) {
    $failure = get_class($e) . ':' . hash('sha256', $e->getMessage());
} finally {
    $cleanup['http_worker_stopped'] = !is_dir('/proc/' . $pid);
    $cleanup['http_runtime_ready'] = !$cleanup['http_worker_stopped']
        && $runtimeReady();
    $cleanup['http_outcome_confirmed'] = !$httpSent || $httpConfirmed;
    $cleanup['barrier_safe'] = ($cleanup['http_runtime_ready']
        || $cleanup['http_worker_stopped'])
        && ($cleanup['http_worker_stopped'] || $cleanup['http_outcome_confirmed']);
    if ($cleanup['barrier_safe']) {
        try {
            $db = $connect();
            $cleanupIdentity = $dialect === 'mysql'
                ? (string)$db->query("SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")
                    ->fetchColumn()
                : 'ZHCT_APP|5237|' . (string)$db->query(
                    "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")
                    ->fetchColumn();
            if (!hash_equals($approvedDbFingerprint, hash('sha256', $cleanupIdentity))) {
                throw new RuntimeException('Cleanup DB identity differs');
            }
            $stmt = $db->prepare('SELECT ID FROM ' . $prefix . 'user'
                . ' WHERE UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?');
            $stmt->execute([$marker, $marker, 'CODEX']);
            $owned = $stmt->fetchAll(PDO::FETCH_ASSOC);
            if (count($owned) > 1) throw new RuntimeException('Ambiguous report operator cleanup');
            if ($owned) {
                $id = (int)$owned[0]['id'];
                if ($operatorId > 0 && $id !== $operatorId) {
                    throw new RuntimeException('Report operator ID drift');
                }
                $delete = $db->prepare('DELETE FROM ' . $prefix . 'user'
                    . ' WHERE ID=? AND UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?');
                $delete->execute([$id, $marker, $marker, 'CODEX']);
                if ($delete->rowCount() !== 1) {
                    throw new RuntimeException('Exact report operator cleanup affected rows mismatch');
                }
            }
        } catch (Throwable $e) {
            $cleanup['error_class'] = get_class($e);
            $cleanup['error_sha256'] = hash('sha256', $e->getMessage());
        }
    }
    try {
        $db = $connect();
        $stmt = $db->prepare('SELECT COUNT(*) FROM ' . $prefix . 'user'
            . ' WHERE UUID=? OR ACCOUNT=?');
        $stmt->execute([$marker, $marker]);
        $cleanup['operator_zero'] = (int)$stmt->fetchColumn() === 0;
    } catch (Throwable $e) {
        $cleanup['verify_error_class'] = get_class($e);
    }
}
$clean = !empty($cleanup['barrier_safe']) && !empty($cleanup['operator_zero'])
    && empty($cleanup['error_class']);
try {
    $writeJournal(['status' => $clean ? 'cleaned' : 'needs_recovery',
        'cleanup' => $cleanup, 'failure' => $failure]);
} catch (Throwable $e) {
    $cleanup['journal_error_class'] = get_class($e);
    $clean = false;
}
echo json_encode(['lane' => $lane, 'suite' => 'store-report-read3',
    'marker' => $marker, 'source_join_rows' => count($joinRows),
    'source_dish_groups' => count($dishGroups),
    'source_meal_rows' => count($mealRows),
    'results' => $results, 'failure' => $failure, 'cleanup' => $cleanup],
    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
if ($failure !== '' || !$clean) exit(1);
