<?php

declare(strict_types=1);

// Five Store PC reads. Default-deny: a separate root approval, script SHA, DB SHA,
// and A baseline are mandatory before any business HTTP or fixture INSERT.
$requestedMode = (string)($argv[1] ?? '');
$laneRequested = (string)getenv('CDX_NEXT5_LANE');
$remainingRequested = (string)getenv('CDX_NEXT5_C_REMAINING') === '1';
$menuRequested = (string)getenv('CDX_NEXT5_MENU_ONLY') === '1';
if (!in_array($requestedMode, ['--preflight', '--execute'], true)
    || !in_array($laneRequested, ['A', 'B', 'C'], true)
    || ($menuRequested && $remainingRequested)
    || ($menuRequested && $requestedMode === '--execute'
        && (string)getenv('CDX_NEXT5_MENU_APPROVAL') !== 'ROOT_APPROVED_MENU_ONLY')
    || ($remainingRequested && ($laneRequested !== 'C'
        || ($requestedMode === '--execute'
            && (string)getenv('CDX_NEXT5_REMAINING_APPROVAL')
                !== 'ROOT_APPROVED_C_NEXT5_REMAINING')))
    || ($requestedMode === '--execute'
        && ((string)getenv('CDX_NEXT5_EXECUTE') !== 'ROOT_APPROVED_NEXT5_V1'
            || (string)getenv('CDX_NEXT5_RUNNER_SHA') !== hash_file('sha256', __FILE__)))) {
    fwrite(STDERR, "NEXT5 formal HTTP and DML disabled\n");
    exit(78);
}
$preflight = __DIR__ . '/preflight_next5.php';
if (!is_file($preflight) || is_link($preflight)
    || hash_file('sha256', $preflight)
        !== '8f262f3645d6c7e082dc5a2d7c32d893d32eb91a3dd2365f7d88cec0db25c4d6') {
    throw new RuntimeException('Frozen next5 preflight drift');
}
$argv[1] = '--preflight';
require $preflight; // Runs fixed PID/config/source/DB identity/leaf-source SELECT gates.
$mode = $requestedMode;
$argv[1] = $requestedMode;
$remainingC = $remainingRequested && $lane === 'C';
$menuOnly = $menuRequested;
if ($mode === '--execute'
    && ((string)getenv('CDX_NEXT5_DB_SHA') !== $approvedDbSha
        || ($dialect === 'dm' && (string)getenv('CDX_NEXT5_HOST_SHA')
            !== 'd56d81988bb0f106946cce91c608fdd0ef1116e5150b23376ea87e086eace4b9'))) {
    throw new RuntimeException('Explicit target approval absent');
}
$extraFiles = [
    'application/p/logic/Login.php' => 'd56c1c6f8e99e6819fa7695ef9397e8d2e33e62e6ee0278fb4cbfe7d1fdabba0',
    'application/base/Security.php' => 'b82e5ed982e6084a2b2942c033d4767428fb6f1012ba628f609477a7563eb4c3',
    'application/base/AdminController.php' => '7565b36fa4dda2c21cc4fa3b37753dbffb7c3a464bb8c11ea0f17ca00bececa5',
    'application/model/Department.php' => $lane === 'A'
        ? 'a0910fe7209b7da3e6a43a1697ea7a049bbd6e94d2c08225cdefe90f368efce8'
        : '9cd5a91f10f238d932d062e1fe8fae74208496b65d639314c545ecec49cc0e1f',
    'application/model/StaffDepartment.php' => 'c450c5b72f6e5f1a9f0c0736922b1ccdc1f160b9637970857cf6b794d6becf29',
    'application/common.php' => $lane === 'A'
        ? '5f0bc855dc205360896f7a08a5d66f3904a39a607cc463f6a70a6add04a55e7e'
        : '1ff0e49451950d671498ad5e1f7380f60448d2f7a39041d4b53370abd6e6d78f',
    'application/route.php' => '081b0186b7f40f0bdd237cecb3e2d678fc9344c656932c0d3b3052404e4f1510',
];
foreach ($extraFiles as $relative => $sha) {
    $path = $root . '/' . $relative;
    if (!is_file($path) || is_link($path) || hash_file('sha256', $path) !== $sha) {
        throw new RuntimeException('Extra route/auth/model source drift: ' . $relative);
    }
}
$connect = static function () use ($dsn, $runtime): PDO {
    return new PDO($dsn, (string)$runtime['username'], (string)$runtime['password'],
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_TIMEOUT => 5]);
};
$sameIdentity = static function (PDO $pdo) use ($dialect, $approvedDbSha): bool {
    $actual = $dialect === 'dm'
        ? 'ZHCT_APP|5237|' . (string)$pdo->query(
            "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn()
        : (string)$pdo->query(
            "SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")
            ->fetchColumn();
    return hash_equals($approvedDbSha, hash('sha256', $actual));
};
$rows = static function (PDO $pdo, string $sql, array $args = [], int $cap = 5000): array {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    $out = [];
    while (($raw = $stmt->fetch(PDO::FETCH_ASSOC)) !== false) {
        if (count($out) >= $cap) throw new RuntimeException('Bounded source row cap exceeded');
        $row = [];
        foreach (array_change_key_case($raw, CASE_LOWER) as $key => $value) {
            $row[$key] = is_resource($value) ? stream_get_contents($value) : $value;
        }
        ksort($row, SORT_STRING);
        $out[] = $row;
    }
    return $out;
};
$scalar = static function (PDO $pdo, string $sql, array $args = []) {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt->fetchColumn();
};
$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));
    $inode = '';
    foreach (@file('/proc/net/tcp', FILE_IGNORE_NEW_LINES) ?: [] as $line) {
        $part = preg_split('/\s+/', trim($line));
        if (($part[1] ?? '') === '0100007F:' . $hex && ($part[3] ?? '') === '0A') {
            $inode = (string)($part[9] ?? '');
            break;
        }
    }
    $owns = false;
    if ($inode !== '') foreach (@scandir('/proc/' . $pid . '/fd') ?: [] as $fd) {
        if ($fd !== '.' && $fd !== '..'
            && @readlink('/proc/' . $pid . '/fd/' . $fd) === 'socket:[' . $inode . ']') {
            $owns = true;
            break;
        }
    }
    return $owns && $environment !== '' && trim($children) === ''
        && strpos($cmdline, '127.0.0.1:' . $port) !== false
        && strpos($cmdline, $root . '/public') !== false
        && !(preg_match('/(?:^|\x00)PHP_CLI_SERVER_WORKERS=(\d+)(?:\x00|$)/', $environment, $m)
            && (int)$m[1] > 1)
        && is_array($boundary) && !empty($boundary['external_stubs'])
        && !empty($boundary['redis_isolated']) && empty($boundary['real_queue']);
};
$bind = static function (array $values): string {
    if (count($values) < 1 || count($values) > 15) {
        throw new RuntimeException('Unbounded staff UUID list');
    }
    return implode(',', array_fill(0, count($values), '?'));
};
$staffRows = $rows($db, 'SELECT s.* FROM ' . $table('staff') . ' s'
    . ' JOIN ' . $table('staff_department') . ' sd ON sd.STAFF_UUID=s.UUID'
    . ' WHERE sd.DEPARTMENT_UUID=? AND s.IS_SHOW=1', [$dept], 16);
$staffByUuid = [];
foreach ($staffRows as $row) $staffByUuid[(string)$row['uuid']] = $row;
$ordinaryUuids = array_keys($staffByUuid);
sort($ordinaryUuids, SORT_STRING);
if (count($ordinaryUuids) !== (int)$ordinary['n']
    || count($ordinaryUuids) < 1 || count($ordinaryUuids) > 15) {
    throw new RuntimeException('Visible leaf staff source drift');
}
$descendants = (int)$scalar($db, 'SELECT COUNT(*) FROM ' . $table('department')
    . ' WHERE UUID<>? AND STATUS=1 AND IS_SHOW=1 AND DEPARTMENT_PATH LIKE ?',
    [$dept, '%' . $dept . '%']);
if ($descendants !== 0) throw new RuntimeException('Leaf path expansion would exceed selected window');
$date = substr((string)$lastDate, 0, 10);
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
    throw new RuntimeException('Natural menu date unavailable');
}
$source = static function (PDO $pdo) use ($rows, $table, $bind, $ordinaryUuids, $date): array {
    $in = $bind($ordinaryUuids);
    $sets = [
        'department' => $rows($pdo, 'SELECT * FROM ' . $table('department'), [], 3000),
        'sport' => $rows($pdo, 'SELECT * FROM ' . $table('sport'), [], 600),
        'staff' => $rows($pdo, 'SELECT * FROM ' . $table('staff')
            . ' WHERE UUID IN (' . $in . ')', $ordinaryUuids, 16),
        'staff_department' => $rows($pdo, 'SELECT * FROM '
            . $table('staff_department') . ' WHERE STAFF_UUID IN (' . $in . ')',
            $ordinaryUuids, 100),
        'menu_recommend' => $rows($pdo, 'SELECT * FROM '
            . $table('menu_recommend') . ' WHERE STAFF_UUID IN (' . $in . ')',
            $ordinaryUuids, 6000),
        // This is a collateral relation fingerprint, not a claim that getMenuList reads it.
        'date_menu' => $rows($pdo, 'SELECT * FROM ' . $table('date_menu')
            . ' WHERE STAFF_UUID IN (' . $in . ') AND MENU_DATE=?',
            array_merge($ordinaryUuids, [$date]), 2000),
    ];
    $counts = [];
    $hashes = [];
    foreach ($sets as $name => $items) {
        $canonical = [];
        foreach ($items as $item) $canonical[] = serialize($item);
        sort($canonical, SORT_STRING);
        $counts[$name] = count($items);
        $hashes[$name] = hash('sha256', implode("\n", $canonical));
    }
    return [$sets, $counts, $hashes];
};
[$sourceRows, $sourceCounts, $sourceHashes] = $source($db);
if ($sourceCounts['sport'] < 1 || $sourceCounts['department'] < 1
    || $sourceCounts['staff'] !== count($ordinaryUuids)
    || $sourceCounts['menu_recommend'] < 1) {
    throw new RuntimeException('Natural source missing');
}
$oldActors = (int)$scalar($db, 'SELECT COUNT(*) FROM ' . $table('user')
    . " WHERE ACCOUNT LIKE 'CDXN5%'");
if ($oldActors !== 0) throw new RuntimeException('Prior next5 actor residue');
if ($dialect === 'dm') {
    $ddlStmt = $db->prepare('CALL SP_TABLEDEF(?, ?)');
    $ddlStmt->execute(['ZHCT_APP', 'YDY_USER']);
    $ddl = $ddlStmt->fetchColumn();
    if (is_resource($ddl)) $ddl = stream_get_contents($ddl);
    $autoId = preg_match('/"ID"\s+[A-Z0-9]+\s+AUTO_INCREMENT\s+NOT\s+NULL/i',
        (string)$ddl) === 1;
    $trigger = (int)$scalar($db, 'SELECT COUNT(*) FROM USER_TRIGGERS WHERE TABLE_NAME=?',
        ['YDY_USER']);
    $fk = (int)$scalar($db, "SELECT COUNT(*) FROM USER_CONSTRAINTS"
        . " WHERE TABLE_NAME=? AND CONSTRAINT_TYPE='R'", ['YDY_USER'])
        + (int)$scalar($db, 'SELECT COUNT(*) FROM ALL_CONSTRAINTS c'
            . ' JOIN ALL_CONSTRAINTS parent ON c.R_OWNER=parent.OWNER'
            . ' AND c.R_CONSTRAINT_NAME=parent.CONSTRAINT_NAME'
            . " WHERE c.CONSTRAINT_TYPE='R' AND parent.OWNER='ZHCT_APP'"
            . ' AND parent.TABLE_NAME=?', ['YDY_USER']);
} else {
    $autoId = (int)$scalar($db, 'SELECT COUNT(*) FROM information_schema.COLUMNS'
        . ' WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? AND COLUMN_NAME=?'
        . " AND EXTRA LIKE '%auto_increment%'", ['ydy_user', 'id']) === 1;
    $trigger = (int)$scalar($db, 'SELECT COUNT(*) FROM information_schema.TRIGGERS'
        . ' WHERE TRIGGER_SCHEMA=DATABASE() AND EVENT_OBJECT_TABLE=?', ['ydy_user']);
    $fk = (int)$scalar($db, 'SELECT COUNT(*) FROM information_schema.KEY_COLUMN_USAGE'
        . ' WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=?'
        . ' AND REFERENCED_TABLE_NAME IS NOT NULL', ['ydy_user'])
        + (int)$scalar($db, 'SELECT COUNT(*) FROM information_schema.KEY_COLUMN_USAGE'
            . ' WHERE REFERENCED_TABLE_SCHEMA=DATABASE() AND REFERENCED_TABLE_NAME=?',
            ['ydy_user']);
}
if (!$autoId || $trigger !== 0 || $fk !== 0) {
    throw new RuntimeException('Actor table identity/FK/trigger drift');
}
$pre = ['lane' => $lane, 'mode' => 'select-only-preflight',
    'frozen_preflight_sha' => hash_file('sha256', $preflight),
    'runtime_and_db_identity_locked' => true,
    'leaf_department_sha12' => substr(hash('sha256', $dept), 0, 12),
    'menu_date' => $date, 'source_counts' => $sourceCounts,
    'source_hashes' => $sourceHashes,
    'actor_auto_id_fk0_trigger0' => true, 'prior_actor_rows' => $oldActors,
    'business_http' => 0, 'dml' => 0];
if ($mode === '--preflight') {
    echo json_encode($pre, JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(0);
}
if (!function_exists('bccomp')) throw new RuntimeException('BCMath decimal checker unavailable');
$hourMinute = date('H:i');
if ($hourMinute >= '23:58' || $hourMinute <= '00:02') {
    throw new RuntimeException('Near-midnight isolated tmp cleanup window');
}
$baseline = null;
if ($lane !== 'A') {
    $baselineJson = (string)getenv('CDX_NEXT5_A_CONTRACT_JSON');
    $baselineSha = (string)getenv('CDX_NEXT5_A_CONTRACT_SHA');
    if ($baselineJson === '' || $baselineSha === ''
        || !hash_equals($baselineSha, hash('sha256', $baselineJson))) {
        throw new RuntimeException('A baseline contract and SHA required');
    }
    $baseline = json_decode($baselineJson, true);
    if (!is_array($baseline) || ($baseline['lane'] ?? '') !== 'A'
        || ($baseline['db_sha'] ?? '')
            !== '003eb5aecf1cd4595b609c1f7f20b9ee325b578309fb9fe14fedaf77584fa401'
        || !isset($baseline['routes']) || !is_array($baseline['routes'])) {
        throw new RuntimeException('A baseline contract invalid');
    }
}
$departmentMap = [];
$activeDepartmentMap = [];
foreach ($sourceRows['department'] as $row) {
    $departmentMap[(string)$row['uuid']] = $row;
    if ((int)$row['status'] === 1 && (int)$row['is_show'] === 1) {
        $activeDepartmentMap[(string)$row['uuid']] = $row;
    }
}
$sportMap = [];
foreach ($sourceRows['sport'] as $row) $sportMap[(string)$row['uuid']] = $row;
$relatedDepartmentMap = [];
foreach ($sourceRows['staff_department'] as $row) {
    $relatedDepartmentMap[(string)$row['staff_uuid']][(string)$row['department_uuid']] = true;
}
$selectedAthlete = '';
foreach ($staffUuids as $candidate) {
    if (!isset($staffByUuid[$candidate], $relatedDepartmentMap[$candidate][$dept])) continue;
    $allRelatedKnown = true;
    foreach ($relatedDepartmentMap[$candidate] as $relatedUuid => $_) {
        if (!isset($departmentMap[$relatedUuid])) $allRelatedKnown = false;
    }
    if ($allRelatedKnown) { $selectedAthlete = (string)$candidate; break; }
}
if ($selectedAthlete === '') throw new RuntimeException('No bounded athlete for UUID route');
if (!preg_match('/^[0-9A-Fa-f]{8}(-[0-9A-Fa-f]{4}){3}-[0-9A-Fa-f]{12}$/',
    $selectedAthlete)) {
    throw new RuntimeException('Selected staff UUID format outside approved scalar contract');
}
$flattenTree = static function (array $nodes, string $parent, array &$seen)
    use (&$flattenTree): void {
    foreach ($nodes as $node) {
        if (!is_array($node) || !isset($node['uuid'], $node['puuid'])
            || (string)$node['puuid'] !== $parent) {
            throw new RuntimeException('Tree parent/shape mismatch');
        }
        $uuid = (string)$node['uuid'];
        if (isset($seen[$uuid])) throw new RuntimeException('Duplicate tree node');
        $seen[$uuid] = $node;
        if (isset($node['children'])) {
            if (!is_array($node['children']) || !$node['children']) {
                throw new RuntimeException('Empty/nonarray tree children');
            }
            $flattenTree($node['children'], $uuid, $seen);
        }
    }
};
$reachable = static function (array $all): array {
    $found = [];
    $queue = ['0'];
    $steps = 0;
    while ($queue) {
        $parent = array_shift($queue);
        foreach ($all as $uuid => $row) {
            if ((string)$row['puuid'] === $parent && !isset($found[$uuid])) {
                $found[$uuid] = $row;
                $queue[] = $uuid;
            }
        }
        if (++$steps > count($all) + 1) throw new RuntimeException('Source hierarchy cycle');
    }
    return $found;
};
$assertTree = static function (array $nodes, array $sourceMap) use ($flattenTree, $reachable): array {
    $seen = [];
    $flattenTree($nodes, '0', $seen);
    $expected = $reachable($sourceMap);
    if (count($seen) !== count($expected) || count($seen) < 1) {
        throw new RuntimeException('Tree reachable node count mismatch');
    }
    foreach ($seen as $uuid => $node) {
        if (!isset($expected[$uuid]) || (string)$node['name'] !== (string)$expected[$uuid]['name']
            || (string)$node['puuid'] !== (string)$expected[$uuid]['puuid']) {
            throw new RuntimeException('Tree row differs from source');
        }
        if (!array_key_exists('chhildShow', $node) || $node['chhildShow'] !== false) {
            throw new RuntimeException('Tree UI key/type mismatch');
        }
    }
    return array_values($seen);
};
$flattenGroups = static function (array $groups): array {
    $flat = [];
    foreach ($groups as $group) {
        if (!is_array($group) || !isset($group['department_name'], $group['staff_info'])
            || !is_array($group['staff_info']) || !$group['staff_info']) {
            throw new RuntimeException('Grouped staff response shape mismatch');
        }
        foreach ($group['staff_info'] as $row) {
            if (!is_array($row) || (string)($row['department_name'] ?? '')
                !== (string)$group['department_name']) {
                throw new RuntimeException('Grouped staff row/dept mismatch');
            }
            $flat[] = $row;
        }
    }
    return $flat;
};
$profile = static function (array $businessRows): array {
    $keys = [];
    $types = [];
    foreach ($businessRows as $row) {
        if (!is_array($row)) throw new RuntimeException('Business row not object');
        foreach ($row as $field => $value) {
            if ($field === 'children' || $field === 'staff_info') continue;
            $keys[$field] = true;
            $types[$field][gettype($value)] = true;
        }
    }
    $fieldNames = array_keys($keys);
    sort($fieldNames, SORT_STRING);
    $out = [];
    foreach ($fieldNames as $field) {
        $out[$field] = array_keys($types[$field]);
        sort($out[$field], SORT_STRING);
    }
    return $out;
};
$assertBaseline = static function (string $routeKey, string $sha, array $typeProfile)
    use ($lane, $baseline): void {
    if ($lane === 'A') return;
    $old = $baseline['routes'][$routeKey] ?? null;
    if (!is_array($old) || !isset($old['response_sha'], $old['type_profile'])) {
        throw new RuntimeException('A baseline route absent');
    }
    if ($lane === 'B' && !hash_equals((string)$old['response_sha'], $sha)) {
        throw new RuntimeException('A/B complete response SHA mismatch');
    }
    if ($lane === 'C') {
        $oldTypes = $old['type_profile'];
        if (!is_array($oldTypes) || array_keys($oldTypes) !== array_keys($typeProfile)) {
            throw new RuntimeException('C response field-key contract mismatch');
        }
        foreach ($typeProfile as $field => $observed) {
            $allowed = $oldTypes[$field];
            if (!is_array($allowed)) throw new RuntimeException('A type profile malformed');
            foreach ($observed as $type) {
                if (!in_array($type, $allowed, true)) {
                    throw new RuntimeException('C response JSON type differs from A');
                }
            }
        }
    }
};
$assertStaff = static function (array $row, ?string $restrictedDept = null)
    use ($staffByUuid, $relatedDepartmentMap, $departmentMap): void {
    $uuid = (string)($row['uuid'] ?? '');
    $deptUuid = (string)($row['department_id'] ?? '');
    if (!isset($staffByUuid[$uuid], $relatedDepartmentMap[$uuid][$deptUuid],
        $departmentMap[$deptUuid])
        || ($restrictedDept !== null && $deptUuid !== $restrictedDept)
        || (string)($row['name'] ?? '') !== (string)$staffByUuid[$uuid]['name']
        || (string)($row['department_name'] ?? '') !== (string)$departmentMap[$deptUuid]['name']) {
        throw new RuntimeException('Staff/dept response differs from source');
    }
};
$assertMealRows = static function (array $payload) use ($ordinaryUuids, $staffByUuid): array {
    if (!isset($payload['rows'], $payload['total']) || !is_array($payload['rows'])
        || (int)$payload['total'] !== count($ordinaryUuids)
        || count($payload['rows']) !== count($ordinaryUuids)) {
        throw new RuntimeException('Menu list rows/total mismatch');
    }
    $seen = [];
    foreach ($payload['rows'] as $row) {
        $uuid = (string)($row['uuid'] ?? '');
        if (!isset($staffByUuid[$uuid]) || isset($seen[$uuid])) {
            throw new RuntimeException('Menu list staff/duplicate mismatch');
        }
        $seen[$uuid] = true;
        $src = $staffByUuid[$uuid];
        $name = (string)$src['name'];
        if (!empty($src['nickname']) && !empty($src['is_wx'])) {
            $name .= '(' . $src['nickname'] . ')';
        }
        if ((string)($row['name'] ?? '') !== $name) {
            throw new RuntimeException('Menu list name formatting differs from source');
        }
        foreach (['take_meal', 'personnel_umber', 'sex', 'nickname', 'is_wx'] as $key) {
            if ((string)($row[$key] ?? '') !== (string)($src[$key] ?? '')) {
                throw new RuntimeException('Menu list scalar source mismatch');
            }
        }
        foreach (['height', 'weight'] as $key) {
            if (is_numeric($row[$key] ?? null) && is_numeric($src[$key] ?? null)) {
                if (bccomp((string)$row[$key], (string)$src[$key], 4) !== 0) {
                    throw new RuntimeException('Menu list decimal source mismatch');
                }
            } elseif ((string)($row[$key] ?? '') !== (string)($src[$key] ?? '')) {
                throw new RuntimeException('Menu list nullable metric mismatch');
            }
        }
        if ((string)($row['menu_model'] ?? '') !== (string)($src['grade'] ?? '')) {
            throw new RuntimeException('Menu list grade alias mismatch');
        }
    }
    return $payload['rows'];
};
$queueState = static function (PDO $pdo) use ($query, $table): array {
    $row = $query($pdo, 'SELECT COUNT(*) AS TOTAL,'
        . ' SUM(CASE WHEN STATUS=0 THEN 1 ELSE 0 END) AS PENDING FROM '
        . $table('export_log'));
    return [(int)($row['total'] ?? -1), (int)($row['pending'] ?? -1)];
};
$queueBefore = $queueState($db);
if ($queueBefore[0] < 0 || $queueBefore[1] !== 0) {
    throw new RuntimeException('Queue preflight unavailable or pending');
}
$marker = 'CDXN5' . strtoupper(bin2hex(random_bytes(6)));
if ((int)$scalar($db, 'SELECT COUNT(*) FROM ' . $table('user')
    . ' WHERE UUID=? OR ACCOUNT=?', [$marker, $marker]) !== 0) {
    throw new RuntimeException('Random actor marker collision');
}
$privateDir = sys_get_temp_dir() . '/zhct-next5-' . $marker;
if (file_exists($privateDir) || !mkdir($privateDir, 0700)) {
    throw new RuntimeException('Private recovery directory unavailable');
}
chmod($privateDir, 0700);
$journalPath = $privateDir . '/recovery.json';
$journal = ['lane' => $lane, 'marker' => $marker,
    'source_hashes' => $sourceHashes, 'queue_before' => $queueBefore,
    'state' => 'prepared'];
$saveJournal = static function () use (&$journal, $privateDir, $journalPath): void {
    $next = $privateDir . '/recovery.next';
    if (file_put_contents($next, json_encode($journal, JSON_UNESCAPED_SLASHES)) === false) {
        throw new RuntimeException('Private journal write failed');
    }
    chmod($next, 0600);
    if (!rename($next, $journalPath)) throw new RuntimeException('Private journal rename failed');
};
$saveJournal();
$actorId = 0;
$httpSent = false;
$httpConfirmed = true;
$cleaned = false;
$privateCleared = false;
$sourcesUnchanged = false;
$queueUnchanged = false;
$results = [];
$negativeResults = [];
$failure = '';
$http = static function (string $path, array $form, string $token, int $cap)
    use ($base, $runtimeReady, &$httpSent, &$httpConfirmed): array {
    if (!$runtimeReady()) throw new RuntimeException('HTTP boundary drift immediately before request');
    $headers = "Content-Type: application/x-www-form-urlencoded\r\n";
    if ($token !== '') $headers .= 'token: ' . $token . "\r\n";
    $context = stream_context_create(['http' => [
        'method' => 'POST', 'header' => $headers,
        'content' => http_build_query($form, '', '&', PHP_QUERY_RFC3986),
        'timeout' => 20, 'ignore_errors' => true]]);
    $httpConfirmed = false;
    $httpSent = true;
    $stream = @fopen($base . $path, 'rb', false, $context);
    $body = is_resource($stream) ? stream_get_contents($stream, $cap + 1) : false;
    $meta = is_resource($stream) ? stream_get_meta_data($stream) : [];
    if (is_resource($stream)) fclose($stream);
    if (!is_string($body) || !empty($meta['timed_out']) || strlen($body) > $cap) {
        throw new RuntimeException('HTTP outcome incomplete/oversized');
    }
    $httpConfirmed = true;
    $responseHeaders = $http_response_header ?? [];
    if (strpos((string)($responseHeaders[0] ?? ''), ' 200 ') === false) {
        throw new RuntimeException('HTTP status mismatch');
    }
    $json = json_decode($body, true);
    if (!is_array($json) || !array_key_exists('code', $json)
        || !array_key_exists('message', $json)) {
        throw new RuntimeException('JSON envelope invalid');
    }
    return [$json, hash('sha256', $body)];
};
$positive = static function (array $json): array {
    if ((int)($json['code'] ?? -1) !== 0
        || !array_key_exists('data', $json) || !is_array($json['data'])) {
        throw new RuntimeException('Positive HTTP business response failed');
    }
    return $json['data'];
};
try {
    // A new connection confirms the selected source has not changed since preflight.
    $fresh = $connect();
    if (!$sameIdentity($fresh) || $source($fresh)[2] !== $sourceHashes
        || $queueState($fresh) !== $queueBefore) {
        throw new RuntimeException('Source/queue drift before actor or HTTP');
    }
    $stmt = $db->prepare('INSERT INTO ' . $table('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]);
    if ($stmt->rowCount() !== 1) throw new RuntimeException('Actor insert affected rows mismatch');
    $actorId = (int)$scalar($db, 'SELECT ID FROM ' . $table('user')
        . ' WHERE UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?',
        [$marker, $marker, 'CODEX']);
    if ($actorId <= 0) throw new RuntimeException('Actor ID not found');
    $journal['actor_id'] = $actorId;
    $journal['state'] = 'actor_committed';
    $saveJournal();
    require_once $root . '/application/base/Security.php';
    $token = \app\base\Security::encrypt(implode("\t",
        [(string)$actorId, $marker, $marker, '0', '', '', $marker]));
    if (!is_string($token) || $token === '') {
        throw new RuntimeException('Synthetic test token unavailable');
    }
    $calls = [
        'staff_tree' => ['/p/staff/tree', [], 4194304, 'tree'],
        'staff_sport' => ['/p/staff/sport', [], 1048576, 'sport'],
        'staff_by_uuid_flat' => ['/p/dateMenu/getStaffByUuid',
            ['staff_uuid' => $selectedAthlete, 'flag' => 'false'], 524288, 'by_uuid'],
        'staff_by_uuid_grouped' => ['/p/dateMenu/getStaffByUuid',
            ['staff_uuid' => $selectedAthlete, 'flag' => 'true'], 524288, 'by_uuid_grouped'],
        'staff_by_department_flat' => ['/p/dateMenu/getStaffByDepartment',
            ['department_uuid' => $dept, 'flag' => 'false'], 524288, 'by_dept'],
        'staff_by_department_grouped' => ['/p/dateMenu/getStaffByDepartment',
            ['department_uuid' => $dept, 'flag' => 'true'], 524288, 'by_dept_grouped'],
        'get_menu_list' => ['/p/dateMenu/getMenuList',
            ['department_uuid' => $dept, 'date' => $date, 'page' => '1'],
            524288, 'menu_list'],
    ];
    $positiveCalls = $calls;
    if ($remainingC) {
        unset($positiveCalls['staff_tree'], $positiveCalls['staff_sport']);
    }
    if ($menuOnly) {
        $positiveCalls = ['get_menu_list' => $calls['get_menu_list']];
    }
    $authCalls = $menuOnly ? $positiveCalls : $calls;
    // Every route must reject no-auth. No network, file, print, payment, or queue route is called.
    $checkedPaths = [];
    foreach ($authCalls as $call) {
        if (isset($checkedPaths[$call[0]])) continue;
        $checkedPaths[$call[0]] = true;
        [$negative] = $http($call[0], $call[1], '', $call[2]);
        if ((int)$negative['code'] === 0) {
            throw new RuntimeException('Unauthenticated route was accepted');
        }
        $negativeResults[$call[0]] = [
            'code' => $negative['code'],
            'code_type' => gettype($negative['code']),
            'message_sha' => hash('sha256', (string)$negative['message']),
            'message_type' => gettype($negative['message'])];
    }
    if ($lane !== 'A') {
        $expectedAuth = $menuOnly
            ? array_intersect_key($baseline['auth_negative'] ?? [],
                ['/p/dateMenu/getMenuList' => true])
            : ($baseline['auth_negative'] ?? null);
        if (!is_array($expectedAuth) || $negativeResults !== $expectedAuth) {
            throw new RuntimeException('Unauthenticated response contract differs from A');
        }
    }
    foreach ($positiveCalls as $key => $call) {
        [$path, $form, $cap, $kind] = $call;
        [$json, $sha] = $http($path, $form, $token, $cap);
        $data = $positive($json);
        if ($kind === 'tree') {
            if (!isset($data['department'], $data['project'])
                || !is_array($data['department']) || !is_array($data['project'])) {
                throw new RuntimeException('Staff tree envelope differs');
            }
            $businessRows = $assertTree($data['department'], $activeDepartmentMap);
        } elseif ($kind === 'sport') {
            $businessRows = $assertTree($data, $sportMap);
        } elseif ($kind === 'by_uuid' || $kind === 'by_uuid_grouped') {
            $businessRows = $kind === 'by_uuid_grouped' ? $flattenGroups($data) : $data;
            if (count($businessRows) !== 1
                || (string)($businessRows[0]['uuid'] ?? '') !== $selectedAthlete) {
                throw new RuntimeException('UUID-filtered staff row count/value mismatch');
            }
            $assertStaff($businessRows[0]);
        } elseif ($kind === 'by_dept' || $kind === 'by_dept_grouped') {
            $businessRows = $kind === 'by_dept_grouped' ? $flattenGroups($data) : $data;
            $seen = [];
            foreach ($businessRows as $row) {
                $assertStaff($row, $dept);
                $uuid = (string)$row['uuid'];
                if (!in_array($uuid, $staffUuids, true) || isset($seen[$uuid])) {
                    throw new RuntimeException('Dept-filtered athlete relation mismatch');
                }
                $seen[$uuid] = true;
            }
            if (count($seen) !== count($staffUuids)) {
                throw new RuntimeException('Dept-filtered athlete row count mismatch');
            }
        } else {
            $businessRows = $assertMealRows($data);
        }
        $typeProfile = $profile($businessRows);
        $typeProfile['__envelope_code'] = [gettype($json['code'])];
        $typeProfile['__envelope_message'] = [gettype($json['message'])];
        $typeProfile['__envelope_data'] = [gettype($json['data'])];
        ksort($typeProfile, SORT_STRING);
        $assertBaseline($key, $sha, $typeProfile);
        $results[$key] = ['response_sha' => $sha,
            'type_profile' => $typeProfile, 'business_rows' => count($businessRows)];
        $journal['state'] = 'route_' . $key . '_confirmed';
        $saveJournal();
    }
    // Required-parameter boundaries; these do not perform table writes.
    [$missingMenu] = $http('/p/dateMenu/getMenuList', [], $token, 524288);
    if ((int)$missingMenu['code'] === 0) {
        throw new RuntimeException('Missing department accepted by menu list');
    }
    if (!$menuOnly) {
        [$missingDept] = $http('/p/dateMenu/getStaffByDepartment', [], $token, 524288);
        if ((int)$missingDept['code'] !== 0 || !isset($missingDept['data'])
            || !is_array($missingDept['data']) || $missingDept['data'] !== []) {
            throw new RuntimeException('Missing department legacy empty contract mismatch');
        }
    }
    $after = $connect();
    if (!$sameIdentity($after)) throw new RuntimeException('Post-HTTP DB identity drift');
    $sourceAfter = $source($after);
    $sourcesUnchanged = $sourceAfter[2] === $sourceHashes
        && $sourceAfter[1] === $sourceCounts;
    $queueUnchanged = $queueState($after) === $queueBefore;
    if (!$sourcesUnchanged || !$queueUnchanged) {
        throw new RuntimeException('Windowed business source or queue changed');
    }
} catch (Throwable $e) {
    $failure = get_class($e) . ':' . hash('sha256', $e->getMessage());
} finally {
    $workerStopped = !is_dir('/proc/' . $pid);
    $cleanupSafe = ($workerStopped || $runtimeReady())
        && ($workerStopped || !$httpSent || $httpConfirmed);
    if ($cleanupSafe) {
        try {
            $cleanupDb = $connect();
            if (!$sameIdentity($cleanupDb)) throw new RuntimeException('Cleanup DB identity drift');
            $ownerRows = $rows($cleanupDb, 'SELECT ID,UUID,ACCOUNT,NAME,TYPE,CREATE_BY'
                . ' FROM ' . $table('user') . ' WHERE UUID=? OR ACCOUNT=?',
                [$marker, $marker], 2);
            if (count($ownerRows) > 1) throw new RuntimeException('Actor ownership ambiguity');
            foreach ($ownerRows as $owner) {
                if ((string)$owner['uuid'] !== $marker
                    || (string)$owner['account'] !== $marker
                    || (string)$owner['name'] !== $marker
                    || (int)$owner['type'] !== 0
                    || (string)$owner['create_by'] !== 'CODEX'
                    || ($actorId > 0 && (int)$owner['id'] !== $actorId)) {
                    throw new RuntimeException('Actor ownership drift');
                }
                foreach (['user_role', 'user_data'] as $relationTable) {
                    if ((int)$scalar($cleanupDb, 'SELECT COUNT(*) FROM '
                        . $table($relationTable) . ' WHERE USER_UUID=?', [$marker]) !== 0) {
                        throw new RuntimeException('Actor has unexpected permission association');
                    }
                }
                $cleanupDb->beginTransaction();
                try {
                    $stmt = $cleanupDb->prepare('DELETE FROM ' . $table('user')
                        . ' WHERE ID=? AND UUID=? AND ACCOUNT=? AND NAME=?'
                        . ' AND TYPE=0 AND CREATE_BY=?');
                    $stmt->execute([(int)$owner['id'], $marker, $marker, $marker, 'CODEX']);
                    if ($stmt->rowCount() !== 1) {
                        throw new RuntimeException('Exact actor cleanup affected rows mismatch');
                    }
                    $cleanupDb->commit();
                } catch (Throwable $e) {
                    if ($cleanupDb->inTransaction()) $cleanupDb->rollBack();
                    throw $e;
                }
            }
            $zeroDb = $connect();
            if (!$sameIdentity($zeroDb)
                || (int)$scalar($zeroDb, 'SELECT COUNT(*) FROM ' . $table('user')
                    . ' WHERE UUID=? OR ACCOUNT=?', [$marker, $marker]) !== 0) {
                throw new RuntimeException('Independent actor-zero check failed');
            }
            $cleaned = true;
        } catch (Throwable $e) {
            $failure .= ($failure === '' ? '' : ';') . 'cleanup:'
                . get_class($e) . ':' . hash('sha256', $e->getMessage());
        }
    } else {
        $failure .= ($failure === '' ? '' : ';')
            . ($httpSent && !$httpConfirmed && !$workerStopped
                ? 'cleanup:unknown_http_outcome' : 'cleanup:runtime_drift');
    }
    if ($cleaned) {
        if (is_file($journalPath)) @unlink($journalPath);
        if (is_file($privateDir . '/recovery.next')) @unlink($privateDir . '/recovery.next');
        $privateCleared = @rmdir($privateDir);
        if (!$privateCleared) $failure .= ';private_journal_not_removed';
    } else {
        $journal['state'] = 'requires_manual_recovery';
        try { $saveJournal(); } catch (Throwable $e) { /* Retain prior journal. */ }
    }
}
$contract = ['lane' => $lane, 'db_sha' => $approvedDbSha,
    'routes' => $results, 'auth_negative' => $negativeResults];
$result = ['lane' => $lane, 'candidate_department_sha12' => substr(hash('sha256', $dept), 0, 12),
    'contract' => $contract, 'source_counts' => $sourceCounts,
    'source_hashes_before' => $sourceHashes,
    'source_unchanged' => $sourcesUnchanged, 'queue_unchanged' => $queueUnchanged,
    'actor_independent_zero' => $cleaned, 'private_journal_removed' => $privateCleared,
    'private_recovery_pointer' => $cleaned ? null : $privateDir,
    'failure' => $failure];
echo json_encode($result, JSON_UNESCAPED_SLASHES), PHP_EOL;
if ($failure !== '' || count($results) !== ($menuOnly ? 1 : ($remainingC ? 5 : 7)) || !$sourcesUnchanged
    || !$queueUnchanged || !$cleaned || !$privateCleared) exit(1);
