<?php

declare(strict_types=1);

// Legacy image plate, independent of the newer television electronic menu.
$lane = (string)getenv('CDX_LEGACY_PLATE_LANE');
$action = (string)($argv[1] ?? '');
$updateOnly = $action === '--execute-update-only';
$targets = [
    'A' => ['/tmp/zhct-http-store-a.l5omH8', 'http://127.0.0.1:18097', 21023, 'mysql'],
    'B' => ['/tmp/zhct-http-store-mysql.dQTTBP', 'http://127.0.0.1:18081', 10001, 'mysql'],
    'C' => ['/tmp/zhct-dm-poc-20260928.fcpiiN/store', 'http://127.0.0.1:18080', 112175, 'dm'],
];
if (!isset($targets[$lane])
    || !in_array($action, ['--preflight', '--execute', '--execute-update-only'], true)
    || ($action !== '--preflight'
        && ((string)getenv('CDX_LEGACY_PLATE_EXECUTE')
                !== ($updateOnly ? 'ROOT_APPROVED_UPDATE_ONLY_V1' : 'ROOT_APPROVED_V1')
            || (string)getenv('CDX_LEGACY_PLATE_SHA') !== hash_file('sha256', __FILE__)))) {
    fwrite(STDERR, "Legacy plate execution disabled\n");
    exit(78);
}
[$root, $base, $pid, $dialect] = $targets[$lane];
if ((string)getenv('POC_APP_ROOT') !== $root
    || (string)getenv('POC_BASE_URL') !== $base
    || (string)getenv('POC_DIALECT') !== $dialect
    || is_link($root) || !is_file($root . '/application/database.php')) {
    throw new RuntimeException('Isolated legacy runtime mismatch');
}
foreach ([
    'application/p/controller/Equipment.php' => '9a50d04723354ae7db73747926aca9871228fca0c3ffad85b7e13522bb0b102a',
    'application/p/logic/Equipment.php' => '6a741878bbed56cf7f22411f5beb86c84bac9af186146b0e9bdf8438fd5ab297',
    'application/api/controller/Plate.php' => '699e0e7f974486fcc7ffb4bfc98530ae0cca87b200a864be3cab9d0463f64ef1',
    'application/api/service/Plate.php' => '3d97d4d0188cfa4c72ca6931aeae9ce40955415ba9411dd1b4c3bfd7d1ee1d05',
] as $source => $expected) {
    if (hash_file('sha256', $root . '/' . $source) !== $expected) {
        throw new RuntimeException('Legacy plate source drift');
    }
}
$cmdline = (string)@file_get_contents('/proc/' . $pid . '/cmdline');
$singleWorker = static function (int $listenerPid): bool {
    $environment = (string)@file_get_contents('/proc/' . $listenerPid . '/environ');
    $children = (string)@file_get_contents('/proc/' . $listenerPid
        . '/task/' . $listenerPid . '/children');
    if ($environment === '' || trim($children) !== '') return false;
    if (preg_match('/(?:^|\x00)PHP_CLI_SERVER_WORKERS=(\d+)(?:\x00|$)/',
        $environment, $match) && (int)$match[1] > 1) return false;
    return true;
};
if (strpos($cmdline, '127.0.0.1:' . parse_url($base, PHP_URL_PORT)) === false
    || strpos($cmdline, $root . '/public') === false || !$singleWorker($pid)) {
    throw new RuntimeException('Legacy listener/PID/single-worker mismatch');
}
$boundary = json_decode((string)@file_get_contents($base . '/__poc_boundary'), true);
if (!is_array($boundary) || empty($boundary['external_stubs'])
    || empty($boundary['redis_isolated']) || !empty($boundary['real_queue'])) {
    throw new RuntimeException('Legacy side-effect isolation absent');
}
$runtime = (static function (string $path): array {
    $config = require $path;
    if (!is_array($config)) throw new RuntimeException('Invalid runtime DB config');
    return $config;
})($root . '/application/database.php');
if ((string)($runtime['prefix'] ?? '') !== 'ydy_'
    || !in_array((string)($runtime['charset'] ?? ''), ['utf8', 'utf8mb4'], true)) {
    throw new RuntimeException('Legacy runtime prefix/charset mismatch');
}
if ($dialect === 'mysql') {
    if ((string)($runtime['type'] ?? '') !== 'mysql') {
        throw new RuntimeException('Legacy MySQL driver type mismatch');
    }
    $local = (static function (): array {
        $config = require '/workspace/zhct/zhctproject/store/application/config/local/database.php';
        if (!is_array($config)) throw new RuntimeException('Invalid code-local DB config');
        return $config;
    })();
    foreach (['hostname', 'database', 'username', 'password'] as $key) {
        if (($runtime[$key] ?? null) !== ($local[$key] ?? null)) {
            throw new RuntimeException('Legacy runtime differs from code-local MySQL');
        }
    }
    if ((int)($runtime['hostport'] ?? 3306) !== (int)($local['hostport'] ?? 3306)) {
        throw new RuntimeException('Legacy MySQL port mismatch');
    }
    $dsn = 'mysql:host=' . $runtime['hostname'] . ';port='
        . (int)($runtime['hostport'] ?? 3306) . ';dbname=' . $runtime['database']
        . ';charset=' . (string)($runtime['charset'] ?? 'utf8');
    $user = (string)$runtime['username'];
    $password = (string)$runtime['password'];
} else {
    if ((string)($runtime['type'] ?? '') !== 'app\\cores\\database\\Dm') {
        throw new RuntimeException('Legacy DM driver type mismatch');
    }
    if ((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('Wrong nonproduction legacy DM target');
    }
    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('Legacy DM runtime/worker differs');
        }
    }
    $dsn = 'dm:host=127.0.0.1;port=5237;schema=ZHCT_APP';
    $user = (string)getenv('POC_USER');
    $password = (string)getenv('POC_PASSWORD');
}
$connect = static function () use ($dsn, $user, $password): PDO {
    return new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_TIMEOUT => 5]);
};
$db = $connect();
if ($dialect === 'mysql') {
    $dbIdentity = (string)$db->query("SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")
        ->fetchColumn();
    $hostFingerprint = null;
    $localDmListener = null;
} else {
    $schema = (string)$db->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")
        ->fetchColumn();
    if (strtoupper($schema) !== 'ZHCT_APP') throw new RuntimeException('Legacy DM schema differs');
    $dbIdentity = 'ZHCT_APP|5237|' . $schema;
    $machineId = trim((string)@file_get_contents('/etc/machine-id'));
    if ($machineId === '' || gethostname() === false) {
        throw new RuntimeException('Legacy DM host identity unavailable');
    }
    $hostFingerprint = hash('sha256', gethostname() . '|' . $machineId);
    $listeners = [];
    $listenerExit = 0;
    @exec('/usr/sbin/ss -ltnp 2>/dev/null', $listeners, $listenerExit);
    $localDmListener = false;
    if ($listenerExit === 0) {
        foreach ($listeners as $line) {
            if (preg_match('/\*:5237\s+.*users:\(\("dmserver",pid=(\d+),/',
                $line, $match)) {
                $exe = @readlink('/proc/' . $match[1] . '/exe');
                $localDmListener = is_string($exe) && basename($exe) === 'dmserver';
                break;
            }
        }
    }
    if (!$localDmListener) throw new RuntimeException('Legacy 5237 not local dmserver');
}
$dbFingerprint = hash('sha256', $dbIdentity);
if ($action !== '--preflight'
    && ((string)getenv('CDX_LEGACY_PLATE_DB_SHA') !== $dbFingerprint
        || ($dialect === 'dm'
            && (string)getenv('CDX_LEGACY_PLATE_HOST_SHA') !== $hostFingerprint))) {
    throw new RuntimeException('Approved legacy DB/host fingerprint differs');
}
$table = static function (string $name) use ($dialect): string {
    if (!preg_match('/^[a-z_]+$/', $name)) throw new RuntimeException('Invalid legacy table');
    return $dialect === 'dm' ? strtoupper('ydy_' . $name) : 'ydy_' . $name;
};
$counts = [];
foreach (['user', 'equipment', 'plate_dishes', 'upload_file', 'restaurants'] as $name) {
    $counts[$name] = (int)$db->query('SELECT COUNT(*) FROM ' . $table($name))->fetchColumn();
}
$restaurantId = (int)$db->query('SELECT ID FROM ' . $table('restaurants')
    . ' WHERE IS_DELETE=2 ORDER BY ID')->fetchColumn();
$fileId = (int)$db->query('SELECT ID FROM ' . $table('upload_file')
    . " WHERE TYPE=1 AND IS_DELETE=0 AND FILE_PATH<>'' ORDER BY ID DESC")->fetchColumn();
if ($restaurantId <= 0 || $fileId <= 0) {
    throw new RuntimeException('No safe legacy restaurant/image fixture');
}
$filePagePosition = $db->query('SELECT COUNT(*) FROM ' . $table('upload_file')
    . ' WHERE TYPE=1 AND IS_DELETE=0 AND ID>' . $fileId)->fetchColumn();
if ((int)$filePagePosition >= 15) {
    throw new RuntimeException('Selected image is outside first fileList page');
}
foreach (['equipment', 'plate_dishes', 'upload_file'] as $smallTable) {
    if ($counts[$smallTable] > 1000) {
        throw new RuntimeException('Full fingerprint table exceeds review limit');
    }
}
$markerCount = 0;
foreach (['user' => 'ACCOUNT', 'equipment' => 'CODE'] as $name => $column) {
    $markerCount += (int)$db->query('SELECT COUNT(*) FROM ' . $table($name)
        . " WHERE $column LIKE 'CDXLP%'")->fetchColumn();
}
$markerCount += (int)$db->query('SELECT COUNT(*) FROM ' . $table('plate_dishes')
    . " WHERE CREATE_BY LIKE 'CDXLP%'")->fetchColumn();
if ($action === '--preflight') {
    echo json_encode(['lane' => $lane, 'mode' => 'select-only-preflight',
        'db_target' => $dialect === 'dm' ? 'nonprod-dm-store' : 'code-local-dev-mysql',
        'runtime_isolated' => true, 'table_counts' => $counts,
        'restaurant_and_image_present' => true,
        'existing_synthetic_marker_rows' => $markerCount,
        'database_fingerprint' => $dbFingerprint,
        'host_fingerprint' => $hostFingerprint,
        'dm_listener_local' => $localDmListener], JSON_UNESCAPED_SLASHES) . PHP_EOL;
    exit(0);
}

if ($markerCount !== 0) throw new RuntimeException('Old legacy marker requires review');
$db->query('SELECT ID,UUID,ACCOUNT,PWD,SALT,NAME,TYPE,CREATE_TIME,CREATE_BY,IS_DELETE'
    . ' FROM ' . $table('user') . ' WHERE 1=0');
$db->query('SELECT ID,CODE,NAME,TYPE,RESTAURANT_ID,DEL_FLAG,CREATE_TIME,'
    . ' CREATE_BY,UPDATE_TIME,UPDATE_BY FROM ' . $table('equipment') . ' WHERE 1=0');
$db->query('SELECT ID,EQUIPMENT_ID,MENU_DATE,MORNING_FILE_ID,NOON_FILE_ID,'
    . ' NIGHT_FILE_ID,NIGHT_SNACK_FILE_ID,IS_DELETE,CREATE_BY'
    . ' FROM ' . $table('plate_dishes') . ' WHERE 1=0');
$sourceBefore = [];
foreach (['equipment', 'plate_dishes', 'upload_file'] as $name) {
    $sourceBefore[$name] = hash('sha256', serialize($db->query('SELECT * FROM '
        . $table($name) . ' ORDER BY ID')->fetchAll(PDO::FETCH_ASSOC)));
}
$marker = 'CDXLP' . strtoupper(bin2hex(random_bytes(8)));
$day = date('Y-m-d');
$journalDir = sys_get_temp_dir() . '/zhct-legacy-plate-' . $marker;
if (file_exists($journalDir) || !mkdir($journalDir, 0700)) {
    throw new RuntimeException('Private legacy recovery directory unavailable');
}
chmod($journalDir, 0700);
$journal = ['lane' => $lane, 'marker' => $marker,
    'database_fingerprint' => $dbFingerprint, 'day' => $day,
    'status' => 'prepared', 'operator_id' => 0,
    'equipment_id' => 0, 'plate_id' => 0];
$writeJournal = static function (array $changes) use (&$journal, $journalDir): void {
    $journal = array_merge($journal, $changes);
    $next = $journalDir . '/recovery.next';
    $target = $journalDir . '/recovery.json';
    $body = json_encode($journal, JSON_UNESCAPED_SLASHES);
    if (!is_string($body) || file_put_contents($next, $body) === false) {
        throw new RuntimeException('Private recovery journal write failed');
    }
    chmod($next, 0600);
    if (!rename($next, $target)) {
        throw new RuntimeException('Private recovery journal replace failed');
    }
};
$writeJournal([]);
$operatorId = 0;
$equipmentId = 0;
$plateId = 0;
$results = [];
$cleanup = [];
$failure = '';
$failurePhase = '';
$phase = 'fixture-start';
$assert = static function (bool $condition, string $reason): void {
    if (!$condition) throw new RuntimeException($reason);
};
$post = static function (string $path, array $form, string $token = '') use ($base): array {
    $headers = "Content-Type: application/x-www-form-urlencoded\r\n";
    if ($token !== '') $headers .= 'token: ' . $token . "\r\n";
    $ctx = stream_context_create(['http' => ['method' => 'POST', 'header' => $headers,
        'content' => http_build_query($form, '', '&', PHP_QUERY_RFC3986),
        'timeout' => 30, 'ignore_errors' => true]]);
    $body = @file_get_contents($base . $path, false, $ctx);
    $headers = $http_response_header ?? [];
    preg_match('/HTTP\/\S+\s+(\d+)/', (string)($headers[0] ?? ''), $match);
    $json = is_string($body) ? json_decode($body, true) : null;
    return ['http' => isset($match[1]) ? (int)$match[1] : 0,
        'json' => is_array($json) ? $json : null];
};
$success = static function (array $response): bool {
    return $response['http'] === 200 && is_array($response['json'])
        && ($response['json']['code'] ?? null) === 0;
};
try {
    $stmt = $db->prepare('SELECT COUNT(*) FROM ' . $table('user')
        . ' WHERE UUID=? OR ACCOUNT=?');
    $stmt->execute([$marker, $marker]);
    $assert((int)$stmt->fetchColumn() === 0, 'Synthetic operator collision');
    $stmt = $db->prepare('SELECT COUNT(*) FROM ' . $table('equipment')
        . ' WHERE CODE=?');
    $stmt->execute([$marker]);
    $assert((int)$stmt->fetchColumn() === 0, 'Synthetic equipment collision');

    $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]);
    $stmt = $db->prepare('SELECT ID FROM ' . $table('user')
        . ' WHERE UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?');
    $stmt->execute([$marker, $marker, 'CODEX']);
    $operatorId = (int)(($stmt->fetch(PDO::FETCH_ASSOC) ?: [])['id'] ?? 0);
    $assert($operatorId > 0, 'Synthetic 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]));
    $assert(is_string($token) && $token !== '', 'Synthetic token unavailable');

    $now = date('Y-m-d H:i:s');
    $phase = 'equipment-fixture';
    $stmt = $db->prepare('INSERT INTO ' . $table('equipment')
        . ' (CODE,NAME,TYPE,RESTAURANT_ID,DEL_FLAG,CREATE_TIME,CREATE_BY,'
        . ' UPDATE_TIME,UPDATE_BY) VALUES (?,?,?,?,?,?,?,?,?)');
    $stmt->execute([$marker, $marker, 8, $restaurantId, 0,
        $now, $marker, $now, $marker]);
    $stmt = $db->prepare('SELECT ID,TYPE,RESTAURANT_ID,DEL_FLAG FROM '
        . $table('equipment') . ' WHERE CODE=? AND NAME=? AND CREATE_BY=?');
    $stmt->execute([$marker, $marker, $marker]);
    $equipment = $stmt->fetch(PDO::FETCH_ASSOC) ?: [];
    $equipmentId = (int)($equipment['id'] ?? 0);
    $assert($equipmentId > 0 && (int)($equipment['type'] ?? 0) === 8
        && (int)($equipment['restaurant_id'] ?? 0) === $restaurantId
        && (int)($equipment['del_flag'] ?? 1) === 0,
        'Synthetic equipment source mismatch');
    $writeJournal(['status' => 'equipment_inserted', 'equipment_id' => $equipmentId]);
    $results['equipment_fixture_source_readback'] = true;

    if (!$updateOnly) {
        $list = $post('/p/equipment/plateList', ['page' => 1, 'pageSize' => 15], $token);
        $listed = false;
        foreach (($list['json']['data']['rows'] ?? []) as $item) {
            if ((int)($item['id'] ?? 0) === $equipmentId
                && (string)($item['code'] ?? '') === $marker) $listed = true;
        }
        $assert($success($list) && $listed, 'Legacy plate list missing fixture');
        $results['plate_list_includes_fixture'] = true;

        $emptyDetail = $post('/p/equipment/plateDetail',
            ['equipment_id' => $equipmentId, 'menu_date' => $day], $token);
        $emptyData = $emptyDetail['json']['data'] ?? null;
        $assert($success($emptyDetail) && is_array($emptyData)
            && (int)($emptyData['id'] ?? 0) === $equipmentId
            && (int)($emptyData['morning_file_id'] ?? -1) === 0,
            'Legacy plate empty detail contract failed');
        $results['plate_detail_empty_no_source_row'] = true;
    }

    $phase = 'file-list';
    $files = $post('/p/common/fileList', ['type' => 1], $token);
    $selectedFile = null;
    foreach (($files['json']['data']['data'] ?? []) as $item) {
        if ((int)($item['id'] ?? 0) === $fileId) $selectedFile = $item;
    }
    $fileUrl = is_array($selectedFile) ? (string)($selectedFile['file_url'] ?? '') : '';
    $assert($success($files) && $fileUrl !== '',
        'Existing image not found in fileList with URL');
    $results['file_list_existing_image_url'] = ['url_present' => true,
        'url_type' => gettype($fileUrl)];

    if ($updateOnly) {
        $phase = 'direct-plate-fixture';
        $fixture = $db->prepare('INSERT INTO ' . $table('plate_dishes')
            . ' (EQUIPMENT_ID,MENU_DATE,MORNING_FILE_ID,NOON_FILE_ID,'
            . ' NIGHT_FILE_ID,NIGHT_SNACK_FILE_ID,IS_DELETE,CREATE_BY)'
            . ' VALUES (?,?,?,?,?,?,?,?)');
        $fixture->execute([$equipmentId, $day, $fileId, $fileId,
            $fileId, $fileId, 0, $marker]);
    } else {
        $phase = 'plate-create-http';
        $updateStarted = microtime(true);
        $update = $post('/p/equipment/plateUpdate', [
            'equipment_id' => $equipmentId, 'menu_date' => $day,
            'morning_file_id' => $fileId, 'noon_file_id' => $fileId,
            'night_file_id' => $fileId, 'night_snack_file_id' => $fileId,
        ], $token);
        if (!$success($update)) {
            $results['plate_update_safe_diagnostic'] = [
                'http' => $update['http'],
                'business_code' => $update['json']['code'] ?? null,
                'elapsed_ms' => (int)round((microtime(true) - $updateStarted) * 1000),
                'message_sha12' => substr(hash('sha256',
                    (string)($update['json']['message'] ?? '')), 0, 12),
            ];
        }
        $assert($success($update), 'Legacy plate update HTTP failed');
    }
    $stmt = $db->prepare('SELECT ID,MORNING_FILE_ID,NOON_FILE_ID,NIGHT_FILE_ID,'
        . ' NIGHT_SNACK_FILE_ID,MENU_DATE,CREATE_BY FROM ' . $table('plate_dishes')
        . ' WHERE EQUIPMENT_ID=? AND IS_DELETE=0');
    $stmt->execute([$equipmentId]);
    $plateRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $assert(count($plateRows) === 1, 'Legacy plate update row missing or duplicated');
    $plate = $plateRows[0];
    $plateId = (int)$plate['id'];
    $assert($plateId > 0 && (string)$plate['create_by'] === $marker
        && substr((string)$plate['menu_date'], 0, 10) === $day
        && (int)$plate['morning_file_id'] === $fileId
        && (int)$plate['noon_file_id'] === $fileId
        && (int)$plate['night_file_id'] === $fileId
        && (int)$plate['night_snack_file_id'] === $fileId,
        'Legacy plate file IDs differ from input');
    $writeJournal(['status' => 'plate_inserted', 'plate_id' => $plateId]);
    $stmt = $db->prepare('SELECT UPDATE_BY FROM ' . $table('equipment')
        . ' WHERE ID=? AND CODE=?');
    $stmt->execute([$equipmentId, $marker]);
    $assert((string)$stmt->fetchColumn() === $marker,
        'Legacy equipment update metadata mismatch');
    $results[$updateOnly ? 'direct_plate_fixture_source_readback'
        : 'plate_update_two_table_source_readback'] = true;

    if (!$updateOnly) {
        $detail = $post('/p/equipment/plateDetail',
            ['equipment_id' => $equipmentId, 'menu_date' => $day], $token);
        $detailData = $detail['json']['data'] ?? null;
        $assert($success($detail) && is_array($detailData)
            && (int)($detailData['id'] ?? 0) === $equipmentId,
            'Legacy plate detail after update failed');
        foreach (['morning', 'noon', 'night', 'night_snack'] as $meal) {
            $assert((int)($detailData[$meal . '_file_id'] ?? 0) === $fileId
                && (string)($detailData[$meal . '_file_url'] ?? '') === $fileUrl,
                'Legacy plate detail image field mismatch');
        }
        $results['plate_detail_four_images_source_match'] = true;

        $image = $post('/api/plate/dishes', ['code' => $marker]);
        $imageUrl = $image['json']['data']['img_url'] ?? null;
        $assert($success($image) && is_string($imageUrl)
            && $imageUrl !== '' && $imageUrl === $fileUrl,
            'Legacy device image URL differs from existing upload source');
        $results['device_image_nonempty_source_match'] = ['url_type' => 'string'];
    }

    $phase = 'plate-clear-http';
    $assert(date('Y-m-d') === $day, 'Legacy test crossed business day');
    $clearImage = $post('/p/equipment/plateUpdate', [
        'equipment_id' => $equipmentId, 'menu_date' => $day,
        'morning_file_id' => 0, 'noon_file_id' => 0,
        'night_file_id' => 0, 'night_snack_file_id' => 0,
    ], $token);
    $stmt = $db->prepare('SELECT ID,MENU_DATE,IS_DELETE,MORNING_FILE_ID,'
        . ' NOON_FILE_ID,NIGHT_FILE_ID,NIGHT_SNACK_FILE_ID FROM '
        . $table('plate_dishes')
        . ' WHERE EQUIPMENT_ID=? AND CREATE_BY=?');
    $stmt->execute([$equipmentId, $marker]);
    $clearedRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $assert($success($clearImage) && count($clearedRows) === 1
        && (int)$clearedRows[0]['id'] === $plateId
        && substr((string)$clearedRows[0]['menu_date'], 0, 10) === $day
        && (int)$clearedRows[0]['is_delete'] === 0
        && (int)$clearedRows[0]['morning_file_id'] === 0
        && (int)$clearedRows[0]['noon_file_id'] === 0
        && (int)$clearedRows[0]['night_file_id'] === 0
        && (int)$clearedRows[0]['night_snack_file_id'] === 0,
        'Legacy existing plate clear update did not preserve row ID');
    $assert(date('Y-m-d') === $day, 'Legacy test crossed business day');
    $phase = 'empty-device-http';
    $emptyImageStarted = microtime(true);
    $emptyImage = $post('/api/plate/dishes', ['code' => $marker]);
    if (!$success($emptyImage)
        || ($emptyImage['json']['data']['img_url'] ?? null) !== '') {
        $results['empty_image_safe_diagnostic'] = [
            'http' => $emptyImage['http'],
            'business_code' => $emptyImage['json']['code'] ?? null,
            'elapsed_ms' => (int)round((microtime(true) - $emptyImageStarted) * 1000),
            'img_url_type' => gettype($emptyImage['json']['data']['img_url'] ?? null),
            'img_url_empty' => ($emptyImage['json']['data']['img_url'] ?? null) === '',
            'message_sha12' => substr(hash('sha256',
                (string)($emptyImage['json']['message'] ?? '')), 0, 12),
        ];
    }
    $assert($success($emptyImage)
        && ($emptyImage['json']['data']['img_url'] ?? null) === '',
        'Legacy device did not return empty image after update');
    $assert(date('Y-m-d') === $day, 'Legacy test crossed business day');
    $results['update_existing_plate_to_empty_same_id'] = true;

    $phase = 'plate-restore-http';
    $restoreImage = $post('/p/equipment/plateUpdate', [
        'equipment_id' => $equipmentId, 'menu_date' => $day,
        'morning_file_id' => $fileId, 'noon_file_id' => $fileId,
        'night_file_id' => $fileId, 'night_snack_file_id' => $fileId,
    ], $token);
    $stmt = $db->prepare('SELECT ID,MENU_DATE,IS_DELETE,MORNING_FILE_ID,'
        . ' NOON_FILE_ID,NIGHT_FILE_ID,NIGHT_SNACK_FILE_ID FROM '
        . $table('plate_dishes') . ' WHERE EQUIPMENT_ID=? AND CREATE_BY=?');
    $stmt->execute([$equipmentId, $marker]);
    $restoredRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $assert($success($restoreImage) && count($restoredRows) === 1
        && (int)$restoredRows[0]['id'] === $plateId
        && substr((string)$restoredRows[0]['menu_date'], 0, 10) === $day
        && (int)$restoredRows[0]['is_delete'] === 0
        && (int)$restoredRows[0]['morning_file_id'] === $fileId
        && (int)$restoredRows[0]['noon_file_id'] === $fileId
        && (int)$restoredRows[0]['night_file_id'] === $fileId
        && (int)$restoredRows[0]['night_snack_file_id'] === $fileId,
        'Legacy existing plate restore update did not preserve row ID');
    $assert(date('Y-m-d') === $day, 'Legacy test crossed business day');
    $phase = 'restored-device-http';
    $restoredImage = $post('/api/plate/dishes', ['code' => $marker]);
    $assert($success($restoredImage)
        && ($restoredImage['json']['data']['img_url'] ?? null) === $fileUrl,
        'Legacy device image not restored after update');
    $assert(date('Y-m-d') === $day, 'Legacy test crossed business day');
    $results['update_existing_plate_restore_nonempty_same_id'] = true;
    $token = '';
} catch (Throwable $e) {
    $failure = get_class($e) . ':' . hash('sha256', $e->getMessage());
    $failurePhase = $phase;
} finally {
    $barrier = json_decode((string)@file_get_contents($base . '/__poc_boundary'), true);
    $currentCmdline = (string)@file_get_contents('/proc/' . $pid . '/cmdline');
    $barrierSafe = is_array($barrier) && !empty($barrier['external_stubs'])
        && !empty($barrier['redis_isolated']) && empty($barrier['real_queue'])
        && strpos($currentCmdline, '127.0.0.1:' . parse_url($base, PHP_URL_PORT)) !== false
        && strpos($currentCmdline, $root . '/public') !== false
        && $singleWorker($pid);
    $cleanup['barrier_safe'] = $barrierSafe;
    if ($barrierSafe) {
        try {
            $db = $connect();
            $stmt = $db->prepare('SELECT ID,CODE,NAME,CREATE_BY FROM '
                . $table('equipment') . ' WHERE CODE=? AND CREATE_BY=?');
            $stmt->execute([$marker, $marker]);
            $ownedEquipment = $stmt->fetchAll(PDO::FETCH_ASSOC);
            if (count($ownedEquipment) > 1) throw new RuntimeException('Ambiguous equipment cleanup');
            $ownedPlateRows = [];
            if ($ownedEquipment) {
                $ownedId = (int)$ownedEquipment[0]['id'];
                if ($equipmentId > 0 && $ownedId !== $equipmentId) {
                    throw new RuntimeException('Equipment ID drift');
                }
                if ((string)$ownedEquipment[0]['name'] !== $marker) {
                    throw new RuntimeException('Equipment identity drift');
                }
                $stmt = $db->prepare('SELECT ID,EQUIPMENT_ID,MENU_DATE,CREATE_BY FROM '
                    . $table('plate_dishes') . ' WHERE EQUIPMENT_ID=?');
                $stmt->execute([$ownedId]);
                $ownedPlateRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
                if (count($ownedPlateRows) > 2) {
                    throw new RuntimeException('Unexpected plate cleanup scope');
                }
                foreach ($ownedPlateRows as $row) {
                    if (substr((string)$row['menu_date'], 0, 10) !== $day
                        || (string)$row['create_by'] !== $marker
                        || ($plateId > 0 && (int)$row['id'] !== $plateId)) {
                        throw new RuntimeException('Unrecognized synthetic plate row');
                    }
                }
            }
            $db->beginTransaction();
            foreach ($ownedPlateRows as $row) {
                $delete = $db->prepare('DELETE FROM ' . $table('plate_dishes')
                    . ' WHERE ID=? AND EQUIPMENT_ID=? AND CREATE_BY=?');
                $delete->execute([(int)$row['id'], (int)$row['equipment_id'],
                    $marker]);
                $check = $db->prepare('SELECT COUNT(*) FROM ' . $table('plate_dishes')
                    . ' WHERE ID=? AND EQUIPMENT_ID=?');
                $check->execute([(int)$row['id'], (int)$row['equipment_id']]);
                if ((int)$check->fetchColumn() !== 0) {
                    throw new RuntimeException('Plate row exact delete failed');
                }
            }
            if ($ownedEquipment) {
                $delete = $db->prepare('DELETE FROM ' . $table('equipment')
                    . ' WHERE ID=? AND CODE=? AND NAME=? AND CREATE_BY=?');
                $delete->execute([(int)$ownedEquipment[0]['id'],
                    $marker, $marker, $marker]);
            }
            $query = $db->prepare('SELECT COUNT(*) FROM ' . $table('equipment')
                . ' WHERE CODE=?');
            $query->execute([$marker]);
            if ((int)$query->fetchColumn() !== 0) {
                throw new RuntimeException('Equipment cleanup failed');
            }
            $query = $db->prepare('SELECT COUNT(*) FROM ' . $table('plate_dishes')
                . ' WHERE CREATE_BY=?');
            $query->execute([$marker]);
            if ((int)$query->fetchColumn() !== 0) {
                throw new RuntimeException('Plate row cleanup failed');
            }
            $db->commit();
        } catch (Throwable $e) {
            if (isset($db) && $db->inTransaction()) {
                try { $db->rollBack(); } catch (Throwable $rollbackError) {
                    $cleanup['rollback_error_class'] = get_class($rollbackError);
                }
            }
            $cleanup['business_error_class'] = get_class($e);
            $cleanup['business_error_sha256'] = hash('sha256', $e->getMessage());
        }
        // Remove the synthetic actor even if a fixture row needs manual recovery.
        try {
            $db = $connect();
            $query = $db->prepare('SELECT ID FROM ' . $table('user')
                . ' WHERE UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?');
            $query->execute([$marker, $marker, 'CODEX']);
            $ownedActors = $query->fetchAll(PDO::FETCH_ASSOC);
            if (count($ownedActors) > 1) throw new RuntimeException('Ambiguous actor cleanup');
            if ($ownedActors) {
                $ownedId = (int)$ownedActors[0]['id'];
                if ($operatorId > 0 && $ownedId !== $operatorId) {
                    throw new RuntimeException('Actor ID drift');
                }
                $delete = $db->prepare('DELETE FROM ' . $table('user')
                    . ' WHERE ID=? AND UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?');
                $delete->execute([$ownedId, $marker, $marker, 'CODEX']);
            }
        } catch (Throwable $e) {
            $cleanup['actor_error_class'] = get_class($e);
            $cleanup['actor_error_sha256'] = hash('sha256', $e->getMessage());
        }
    }
    try {
        $verify = $connect();
        $query = $verify->prepare('SELECT COUNT(*) FROM ' . $table('user')
            . ' WHERE UUID=? OR ACCOUNT=?');
        $query->execute([$marker, $marker]);
        $cleanup['actor_zero'] = (int)$query->fetchColumn() === 0;
        $query = $verify->prepare('SELECT COUNT(*) FROM ' . $table('equipment')
            . ' WHERE CODE=?');
        $query->execute([$marker]);
        $cleanup['equipment_zero'] = (int)$query->fetchColumn() === 0;
        $query = $verify->prepare('SELECT COUNT(*) FROM ' . $table('plate_dishes')
            . ' WHERE CREATE_BY=?');
        $query->execute([$marker]);
        $cleanup['plate_zero'] = (int)$query->fetchColumn() === 0;
        $cleanup['source_counts_restored'] = true;
        $cleanup['source_fingerprints_unchanged'] = true;
        foreach (['equipment', 'plate_dishes', 'upload_file'] as $name) {
            $rows = $verify->query('SELECT * FROM ' . $table($name)
                . ' ORDER BY ID')->fetchAll(PDO::FETCH_ASSOC);
            $cleanup['source_counts_restored'] = $cleanup['source_counts_restored']
                && count($rows) === $counts[$name];
            $cleanup['source_fingerprints_unchanged']
                = $cleanup['source_fingerprints_unchanged']
                    && hash('sha256', serialize($rows)) === $sourceBefore[$name];
        }
    } catch (Throwable $e) {
        $cleanup['verify_error_class'] = get_class($e);
        $cleanup['verify_error_sha256'] = hash('sha256', $e->getMessage());
    }
}
$clean = !empty($cleanup['barrier_safe']) && !empty($cleanup['actor_zero'])
    && !empty($cleanup['equipment_zero']) && !empty($cleanup['plate_zero'])
    && !empty($cleanup['source_counts_restored'])
    && !empty($cleanup['source_fingerprints_unchanged'])
    && empty($cleanup['business_error_class']) && empty($cleanup['actor_error_class'])
    && empty($cleanup['rollback_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' => $updateOnly ? 'legacy-image-plate-update-only' : 'legacy-image-plate',
    'marker' => $marker, 'journal_dir' => $journalDir,
    'results' => $results,
    'failure' => $failure, 'failure_phase' => $failurePhase,
    'cleanup' => $cleanup],
    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
if ($failure !== '' || !$clean) exit(1);
