<?php
declare(strict_types=1);

// A/B local-development MySQL draft. Default path is read-only.
require __DIR__ . '/ab_readonly_preflight.php';
const CDX_HEALTH_AB_WRITE_TOKEN = 'CDX_HEALTH_AB_WRITE_APPROVED_20261002_V1';
$caseSet = (string)getenv('CDX_HEALTH_CASE_SET');
if ($caseSet === '') $caseSet = 'all';
if (!in_array($caseSet, ['all', 'tail'], true)) {
    throw new RuntimeException('Unknown health read case set');
}
$stage = 'insert_column_readonly_preflight';
$requiredInsertColumns = [
    [$ai, 'yoshop_meal',
        'STAFF_ID,STORE_ID,MEAL_DATE,MEAL_TIMES,MEAL_TIME,CREATE_BY,'
        . 'ENERGY,CARBOHYDRATE,PROTEIN,FAT,IS_DELETE'],
    [$ai, 'yoshop_meal_infos',
        'MEAL_ID,STAFF_ID,STORE_ID,MEAL_DATE,MEAL_TIMES,MEAL_TIME,'
        . 'DISHES_ID,DISHES_WEIGHT,DISHES_NUMBER,CREATE_BY,IS_DELETE'],
    [$store, 'ydy_measurement_session',
        'AI_USER_ID,EVENT_TYPE,START_TIME,END_TIME,SOURCE_PLATFORM,VENDOR,'
        . 'DEVICE_TYPE,RAW_HASH,BUSINESS_CONTEXT,IS_VALID,CREATED_AT'],
    [$store, 'ydy_health_record',
        'SESSION_ID,AI_USER_ID,METRIC_CODE,VALUE,UNIT,SEGMENT,'
        . 'DATA_SOURCE_TYPE,SOURCE_PLATFORM,START_TIME,END_TIME,CREATED_AT'],
];
foreach ($requiredInsertColumns as [$pdo, $table, $columnList]) {
    $pdo->query('SELECT ' . $columnList . ' FROM ' . $table . ' WHERE 1=0');
}
$stage = 'positive_mapped_dish_readonly_preflight';
$positiveDishCount = (int)$ai->query(
    'SELECT COUNT(*) FROM yoshop_dishes d INNER JOIN yoshop_dishes_foods df'
    . ' ON d.ID=df.DISHES_ID INNER JOIN yoshop_foods f ON f.ID=df.FOODS_ID'
    . ' WHERE d.IS_DELETE=0 AND d.WEIGHT>0 AND d.ENERGY>0'
)->fetchColumn();
if (!hash_equals(CDX_HEALTH_AB_WRITE_TOKEN,
    (string)getenv('CDX_HEALTH_AB_WRITE_APPROVAL'))) {
    echo json_encode(['status' => 'health-read-ab-default-readonly',
        'target' => $target, 'case_set' => $caseSet,
        'write_phase_entered' => false, 'business_http_count' => 0,
        'candidate_date_exclusive' => $counts['ai_meal_week'] === 0
            && $counts['ai_meal_infos_week'] === 0
            && $counts['store_body_scale_week'] === 0,
        'insert_column_groups_queryable' => count($requiredInsertColumns),
        'positive_mapped_dish_exists' => $positiveDishCount > 0,
    ], JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(0);
}

$stage = 'approved_write_boundary';
if ($counts['ai_meal_week'] !== 0 || $counts['ai_meal_infos_week'] !== 0
    || $counts['store_body_scale_week'] !== 0
    || $counts['positive_mapped_dishes'] < 1 || $positiveDishCount < 1) {
    throw new RuntimeException('Candidate date or dish precondition changed');
}
foreach ($config as $key => $value) {
    if (strpos($key, 'POC_') === 0) putenv($key . '=' . $value);
}
putenv('POC_DIALECT=mysql');
putenv('POC_EXTERNAL_STUBS=1');
define('TP_ENV', 'poc');
define('BUSINESS', 'aizhct');
define('ENTERPRISE_NO', '10001');
require $root . '/vendor/autoload.php';
(new \think\App($root))->setEnvName('poc')->initialize();
$ai->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$store->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);

$marker = 'CDXPARHEALTHAB' . strtoupper(bin2hex(random_bytes(5)));
$token = $marker . 'T' . strtoupper(bin2hex(random_bytes(10)));
$day = '2027-12-13';
$end = '2027-12-19';
$measurementTime = $day . ' 12:00:00';
$now = time();
$ids = [];
$hashes = [];
$cases = [];
$cleanup = [];
$error = null;
$dishId = 0;
$dishHash = '';
$referenceStable = true;
$globalWeekIsolated = true;
echo json_encode(['stage' => 'before_synthetic_write', 'marker' => $marker],
    JSON_UNESCAPED_SLASHES), PHP_EOL;
flush();

$all = static function (PDO $pdo, string $sql, array $bind = []): array {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($bind);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
};
$one = static function (PDO $pdo, string $sql, array $bind = []): array {
    $statement = $pdo->prepare($sql);
    $statement->execute($bind);
    $row = $statement->fetch(PDO::FETCH_ASSOC);
    return is_array($row) ? $row : [];
};
$num = static function (PDO $pdo, string $sql, array $bind = []): int {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($bind);
    return (int)$stmt->fetchColumn();
};
$globalWeek = static function () use ($ai, $store, $num, $day, $end): array {
    return [
        'meal' => $num($ai, 'SELECT COUNT(*) FROM yoshop_meal WHERE MEAL_DATE>=?'
            . ' AND MEAL_DATE<=? AND IS_DELETE=0', [$day, $end]),
        'meal_infos' => $num($ai, 'SELECT COUNT(*) FROM yoshop_meal_infos'
            . ' WHERE MEAL_DATE>=? AND MEAL_DATE<=? AND IS_DELETE=0', [$day, $end]),
        'body_scale' => $num($store, 'SELECT COUNT(*) FROM ydy_measurement_session'
            . " WHERE DEVICE_TYPE='body_scale' AND START_TIME>=? AND START_TIME<?",
            [$day . ' 00:00:00', '2027-12-20 00:00:00']),
    ];
};
$rowHash = static function (PDO $pdo, string $table, string $key, int $id)
    use ($all): string {
    $rows = $all($pdo, 'SELECT * FROM ' . $table . ' WHERE ' . $key . '=?', [$id]);
    if (count($rows) !== 1) throw new RuntimeException('Synthetic row not unique');
    return hash('sha256', json_encode($rows[0],
        JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
};
$takeId = static function (PDO $pdo, string $sql, array $bind) use ($all): int {
    $rows = $all($pdo, $sql, $bind);
    if (count($rows) !== 1) throw new RuntimeException('Synthetic ID not unique');
    $id = (int)array_values($rows[0])[0];
    if ($id <= 0) throw new RuntimeException('Synthetic ID invalid');
    return $id;
};
$columns = static function (PDO $pdo, string $table) use ($all, $config): array {
    $names = [];
    foreach ($all($pdo,
        'SELECT COLUMN_NAME FROM information_schema.COLUMNS'
        . ' WHERE TABLE_SCHEMA=? AND TABLE_NAME=?',
        [$config['POC_SCHEMA'], $table]) as $row) {
        $names[] = strtoupper((string)array_values($row)[0]);
    }
    return $names;
};
$request = static function (string $method, string $path, array $params)
    use ($token, $port): array {
    $url = 'http://127.0.0.1:' . $port . $path . '?storeId=10001';
    if ($method === 'GET') $url .= '&' . http_build_query($params);
    $options = ['method' => $method, 'timeout' => 25, 'ignore_errors' => true,
        'header' => 'Access-Token: ' . $token . "\r\nplatform: POC\r\n"];
    if ($method === 'POST') {
        $options['header'] .= "Content-Type: application/json;charset=utf-8\r\n";
        $options['content'] = json_encode($params,
            JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }
    $text = file_get_contents($url, false, stream_context_create(['http' => $options]));
    $line = $http_response_header[0] ?? '';
    return [
        'http' => preg_match('/HTTP\/\S+\s+(\d+)/', $line, $match)
            ? (int)$match[1] : 0,
        'body' => is_string($text) ? json_decode($text, true) : null,
    ];
};
$shape = null;
$shape = static function ($value, int $depth = 0) use (&$shape) {
    if (!is_array($value)) return gettype($value);
    // Deep maps may use dish/enum names as keys, which are data values.
    if ($depth >= 2) return ['array_count' => count($value)];
    if ($value === []) return ['list_count' => 0];
    if (array_keys($value) === range(0, count($value) - 1)) {
        return ['list_count' => count($value),
            'first' => $shape($value[0], $depth + 1)];
    }
    $out = [];
    foreach ($value as $key => $item) $out[$key] = $shape($item, $depth + 1);
    return $out;
};
$sensitive = null;
$sensitive = static function ($value) use (&$sensitive): bool {
    if (!is_array($value)) return false;
    foreach ($value as $key => $item) {
        if (is_string($key) && in_array(strtolower($key), [
            'api_key', 'password', 'secret', 'access_token', 'refresh_token',
            'authorization', 'mobile', 'phone', 'nick_name',
        ], true)) return true;
        if ($sensitive($item)) return true;
    }
    return false;
};

try {
    $stage = 'candidate_week_recheck';
    if ($globalWeek() !== ['meal' => 0, 'meal_infos' => 0, 'body_scale' => 0]) {
        $globalWeekIsolated = false;
        throw new RuntimeException('Candidate week no longer exclusive');
    }
    $dish = $one($ai, 'SELECT d.ID,d.WEIGHT,d.ENERGY,d.CARBOHYDRATE,d.PROTEIN,d.FAT'
        . ' FROM yoshop_dishes d INNER JOIN yoshop_dishes_foods df'
        . ' ON d.ID=df.DISHES_ID INNER JOIN yoshop_foods f ON f.ID=df.FOODS_ID'
        . ' WHERE d.IS_DELETE=0 AND d.WEIGHT>0 AND d.ENERGY>0 ORDER BY d.ID');
    $dishId = (int)($dish['id'] ?? 0);
    if ($dishId <= 0) throw new RuntimeException('Positive mapped dish unavailable');
    $dishHash = $rowHash($ai, 'yoshop_dishes', 'ID', $dishId);
    $mealEnergy = (string)$dish['energy'];
    $dishWeight = (string)$dish['weight'];
    if ((float)$mealEnergy <= 0 || (float)$dishWeight <= 0) {
        throw new RuntimeException('Positive dish nutrients unavailable');
    }
    $stage = 'insert_ai_user';
    if ($num($ai, 'SELECT COUNT(*) FROM yoshop_user WHERE NICK_NAME=? AND STORE_ID=10001',
        [$marker]) !== 0) throw new RuntimeException('Marker collision');
    $ai->prepare('INSERT INTO yoshop_user'
        . ' (STORE_ID,MOBILE,NICK_NAME,BALANCE,GIFT_BALANCE,IS_DELETE,CREATE_TIME)'
        . ' VALUES (10001,?,?,?,?,0,?)')
        ->execute(['', $marker, '0.00', '0.00', $now]);
    $ids['user'] = $takeId($ai,
        'SELECT USER_ID FROM yoshop_user WHERE NICK_NAME=? AND STORE_ID=10001',
        [$marker]);
    $hashes['user'] = $rowHash($ai, 'yoshop_user', 'USER_ID', $ids['user']);

    $stage = 'insert_ai_staff';
    $ai->prepare('INSERT INTO yoshop_staff'
        . ' (NAME,USER_ID,STORE_ID,HEIGHT,WEIGHT,GENDER,BIRTHDAY,PHONE,'
        . ' CREATE_TIME,IS_DELETE)'
        . " VALUES (?,?,10001,170,60,1,'1990-01-01','',?,0)")
        ->execute([$marker, $ids['user'], $day . ' 00:00:00']);
    $ids['staff'] = $takeId($ai,
        'SELECT ID FROM yoshop_staff WHERE NAME=? AND USER_ID=? AND STORE_ID=10001',
        [$marker, $ids['user']]);
    $hashes['staff'] = $rowHash($ai, 'yoshop_staff', 'ID', $ids['staff']);

    $stage = 'insert_ai_meal';
    $ai->prepare('INSERT INTO yoshop_meal'
        . ' (STAFF_ID,STORE_ID,MEAL_DATE,MEAL_TIMES,MEAL_TIME,CREATE_BY,'
        . ' ENERGY,CARBOHYDRATE,PROTEIN,FAT,IS_DELETE)'
        . ' VALUES (?,10001,?,1,?,?,?,?,?,?,0)')
        ->execute([$ids['staff'], $day, $measurementTime, $marker,
            $mealEnergy, (string)$dish['carbohydrate'],
            (string)$dish['protein'], (string)$dish['fat']]);
    $ids['meal'] = $takeId($ai,
        'SELECT ID FROM yoshop_meal WHERE STAFF_ID=? AND MEAL_DATE=?'
        . ' AND MEAL_TIMES=1 AND CREATE_BY=?',
        [$ids['staff'], $day, $marker]);
    $hashes['meal'] = $rowHash($ai, 'yoshop_meal', 'ID', $ids['meal']);

    $stage = 'insert_ai_meal_infos';
    $ai->prepare('INSERT INTO yoshop_meal_infos'
        . ' (MEAL_ID,STAFF_ID,STORE_ID,MEAL_DATE,MEAL_TIMES,MEAL_TIME,'
        . ' DISHES_ID,DISHES_WEIGHT,DISHES_NUMBER,CREATE_BY,IS_DELETE)'
        . ' VALUES (?,?,10001,?,1,?,?,?,?,?,0)')
        ->execute([$ids['meal'], $ids['staff'], $day,
            $measurementTime, $dishId, $dishWeight, '1', $marker]);
    $ids['meal_infos'] = $takeId($ai,
        'SELECT ID FROM yoshop_meal_infos WHERE MEAL_ID=? AND STAFF_ID=?'
        . ' AND CREATE_BY=?', [$ids['meal'], $ids['staff'], $marker]);
    $hashes['meal_infos'] = $rowHash($ai, 'yoshop_meal_infos', 'ID', $ids['meal_infos']);

    $stage = 'insert_store_measurement_session';
    $store->prepare('INSERT INTO ydy_measurement_session'
        . ' (AI_USER_ID,EVENT_TYPE,START_TIME,END_TIME,SOURCE_PLATFORM,VENDOR,'
        . ' DEVICE_TYPE,RAW_HASH,BUSINESS_CONTEXT,IS_VALID,CREATED_AT)'
        . " VALUES (?,'measurement',?,?,'direct_device','welland',"
        . " 'body_scale',?,'health',1,?)")
        ->execute([$ids['user'], $measurementTime, $measurementTime,
            $marker, $measurementTime]);
    $ids['measurement_session'] = $takeId($store,
        'SELECT SESSION_ID FROM ydy_measurement_session'
        . ' WHERE RAW_HASH=? AND AI_USER_ID=?', [$marker, $ids['user']]);
    $hashes['measurement_session'] = $rowHash($store,
        'ydy_measurement_session', 'SESSION_ID', $ids['measurement_session']);

    $stage = 'insert_store_health_record';
    $healthColumns = $columns($store, 'ydy_health_record');
    $hasSegmentKey = in_array('SEGMENT_KEY', $healthColumns, true);
    $store->prepare('INSERT INTO ydy_health_record'
        . ' (SESSION_ID,AI_USER_ID,METRIC_CODE,VALUE,UNIT,SEGMENT,'
        . ($hasSegmentKey ? 'SEGMENT_KEY,' : '')
        . ' DATA_SOURCE_TYPE,SOURCE_PLATFORM,START_TIME,END_TIME,CREATED_AT)'
        . ' VALUES (?,?,\'weight\',\'60.25\',\'kg\',NULL,'
        . ($hasSegmentKey ? "''," : '')
        . " 'raw','direct_device',?,?,?)")
        ->execute([$ids['measurement_session'], $ids['user'],
            $measurementTime, $measurementTime, $measurementTime]);
    $ids['health_record'] = $takeId($store,
        "SELECT RECORD_ID FROM ydy_health_record WHERE SESSION_ID=?"
        . " AND AI_USER_ID=? AND METRIC_CODE='weight'",
        [$ids['measurement_session'], $ids['user']]);
    $hashes['health_record'] = $rowHash($store,
        'ydy_health_record', 'RECORD_ID', $ids['health_record']);

    $stage = 'synthetic_fixture_readback';
    if ($globalWeek() !== ['meal' => 1, 'meal_infos' => 1, 'body_scale' => 1]) {
        $globalWeekIsolated = false;
        throw new RuntimeException('Synthetic week overlapped another writer');
    }
    if ($num($store, 'SELECT COUNT(*) FROM ydy_health_record'
            . ' WHERE SESSION_ID=? AND AI_USER_ID=?',
            [$ids['measurement_session'], $ids['user']]) !== 1) {
        throw new RuntimeException('Synthetic fixture count or isolation mismatch');
    }
    if (!\think\facade\Cache::set($token, [
        'user' => ['user_id' => $ids['user']],
        'password_version' => 0, 'login_type' => 'thirdparty',
    ], 300)) throw new RuntimeException('Synthetic login token cache unavailable');

    $calls = [
        'daily' => ['POST', '/api/analysis.Analysis/daily', ['date' => $day]],
        'week' => ['POST', '/api/analysis.weekNew/weekNew',
            ['start_date' => $day, 'end_date' => $end]],
        'scale_by_date' => ['GET', '/api/wellandScale/byDate', ['date' => $day]],
    ];
    if ($caseSet === 'tail') {
        $calls = array_intersect_key($calls, array_flip(['week', 'scale_by_date']));
    }
    foreach ($calls as $name => [$method, $path, $params]) {
        $stage = 'global_week_before_' . $name;
        if ($globalWeek() !== ['meal' => 1, 'meal_infos' => 1,
            'body_scale' => 1]) {
            $globalWeekIsolated = false;
            $cases[$name] = ['method' => $method, 'path' => $path,
                'http' => 0, 'business_status' => null,
                'data_shape' => 'not_called_global_week_overlap',
                'sensitive_key_present' => false,
                'inconclusive_global_week_overlap' => true, 'pass' => false];
            break;
        }
        $stage = 'business_case_' . $name;
        $response = $request($method, $path, $params);
        $body = $response['body'];
        $data = is_array($body) ? ($body['data'] ?? null) : null;
        $forbidden = $sensitive($data);
        $ok = $response['http'] === 200 && is_array($body)
            && (int)($body['status'] ?? -1) === 200
            && is_array($data) && !$forbidden;
        if ($name === 'daily') {
            $first = $data['meal_data'][0] ?? null;
            $ok = $ok && is_array($first)
                && count($data['meal_data'] ?? []) === 1
                && (int)($first['dishes_id'] ?? 0) === $dishId
                && (float)($first['dishes_weight'] ?? 0) === (float)$dishWeight
                && is_array($data['supply_data'] ?? null)
                && is_array($data['ratio_data'] ?? null);
        } elseif ($name === 'week') {
            $repast = $data['repast']['repast'] ?? null;
            $ok = $ok && is_array($repast)
                && (int)($repast['morning'] ?? 0) === 1
                && is_array($data['meal_construction'] ?? null)
                && (int)($data['meal_construction']['ingredient_num'] ?? 0) >= 1;
        } else {
            $summary = $data['summary']['weight'] ?? null;
            $ok = $ok && (int)($data['session_id'] ?? 0) === $ids['measurement_session']
                && ($data['device_type'] ?? null) === 'body_scale'
                && is_array($summary)
                && abs((float)($summary['value'] ?? 0) - 60.25) < 0.000001
                && ($summary['unit'] ?? null) === 'kg';
        }
        $selectedTypes = [];
        if ($name === 'daily') {
            if (is_array($data['meal_data'][0] ?? null)) {
                foreach (['dishes_id', 'dishes_weight', 'meal_times', 'energy'] as $key) {
                    if (array_key_exists($key, $data['meal_data'][0])) {
                        $selectedTypes['meal_data_first_' . $key] =
                            gettype($data['meal_data'][0][$key]);
                    }
                }
            }
        } elseif ($name === 'week') {
            $selectedTypes['repast_morning'] =
                gettype($data['repast']['repast']['morning'] ?? null);
            $selectedTypes['meal_construction_ingredient_num'] =
                gettype($data['meal_construction']['ingredient_num'] ?? null);
        } else {
            $selectedTypes['session_id'] = gettype($data['session_id'] ?? null);
            $selectedTypes['summary_weight_value'] =
                gettype($data['summary']['weight']['value'] ?? null);
            $selectedTypes['summary_weight_unit'] =
                gettype($data['summary']['weight']['unit'] ?? null);
        }
        $stage = 'global_week_after_' . $name;
        $afterCounts = $globalWeek();
        $overlap = $afterCounts !== ['meal' => 1, 'meal_infos' => 1,
            'body_scale' => 1];
        if ($overlap) $globalWeekIsolated = false;
        $ok = $ok && !$overlap;
        $cases[$name] = ['method' => $method, 'path' => $path,
            'http' => $response['http'],
            'business_status' => is_array($body) ? ($body['status'] ?? null) : null,
            'data_shape' => $forbidden ? 'blocked_sensitive_key' : $shape($data),
            'selected_nested_types' => $selectedTypes,
            'sensitive_key_present' => $forbidden,
            'inconclusive_global_week_overlap' => $overlap, 'pass' => $ok];
        if (!$ok) break;
    }
    $stage = 'post_request_original_table_readback';
    foreach ([
        'user' => [$ai, 'yoshop_user', 'USER_ID'],
        'staff' => [$ai, 'yoshop_staff', 'ID'],
        'meal' => [$ai, 'yoshop_meal', 'ID'],
        'meal_infos' => [$ai, 'yoshop_meal_infos', 'ID'],
        'measurement_session' => [$store, 'ydy_measurement_session', 'SESSION_ID'],
        'health_record' => [$store, 'ydy_health_record', 'RECORD_ID'],
    ] as $name => [$pdo, $table, $key]) {
        if (isset($ids[$name]) && $rowHash($pdo, $table, $key, $ids[$name])
            !== $hashes[$name]) {
            throw new RuntimeException('Read endpoint changed synthetic original row');
        }
    }
} catch (Throwable $failure) {
    $error = ['class' => get_class($failure),
        'code' => (string)$failure->getCode(), 'stage' => $stage];
} finally {
    $stage = 'finally_cache_cleanup';
    try {
        \think\facade\Cache::delete($token);
        $cleanup['cache_absent'] = \think\facade\Cache::get($token) === null;
    } catch (Throwable $ignored) {
        $cleanup['cache_absent'] = false;
    }
    $stage = 'finally_ownership_gate';
    try {
        $expectedGlobal = [
            'meal' => isset($ids['meal']) ? 1 : 0,
            'meal_infos' => isset($ids['meal_infos']) ? 1 : 0,
            'body_scale' => isset($ids['measurement_session']) ? 1 : 0,
        ];
        $cleanup['global_week_overlap'] = $globalWeek() !== $expectedGlobal;
        if ($cleanup['global_week_overlap']) $globalWeekIsolated = false;
    } catch (Throwable $ignored) {
        $cleanup['global_week_overlap'] = true;
        $globalWeekIsolated = false;
    }
    $safe = isset($ids['user'], $hashes['user']);
    try {
        if ($safe) {
            $uid = $ids['user'];
            $checks = [
                'user' => [$ai, 'yoshop_user', 'USER_ID', $uid,
                    'SELECT COUNT(*) FROM yoshop_user WHERE NICK_NAME=? AND STORE_ID=10001',
                    [$marker]],
                'staff' => [$ai, 'yoshop_staff', 'ID', $ids['staff'] ?? 0,
                    'SELECT COUNT(*) FROM yoshop_staff WHERE USER_ID=? AND STORE_ID=10001',
                    [$uid]],
                'meal' => [$ai, 'yoshop_meal', 'ID', $ids['meal'] ?? 0,
                    'SELECT COUNT(*) FROM yoshop_meal WHERE STAFF_ID=? AND CREATE_BY=?',
                    [$ids['staff'] ?? -1, $marker]],
                'meal_infos' => [$ai, 'yoshop_meal_infos', 'ID', $ids['meal_infos'] ?? 0,
                    'SELECT COUNT(*) FROM yoshop_meal_infos WHERE STAFF_ID=? AND CREATE_BY=?',
                    [$ids['staff'] ?? -1, $marker]],
                'measurement_session' => [$store, 'ydy_measurement_session',
                    'SESSION_ID', $ids['measurement_session'] ?? 0,
                    'SELECT COUNT(*) FROM ydy_measurement_session WHERE RAW_HASH=? AND AI_USER_ID=?',
                    [$marker, $uid]],
                'health_record' => [$store, 'ydy_health_record',
                    'RECORD_ID', $ids['health_record'] ?? 0,
                    'SELECT COUNT(*) FROM ydy_health_record WHERE SESSION_ID=? AND AI_USER_ID=?',
                    [$ids['measurement_session'] ?? -1, $uid]],
            ];
            foreach ($checks as $name => [$pdo, $table, $key, $id, $sql, $bind]) {
                $expected = isset($ids[$name]) ? 1 : 0;
                if ($num($pdo, $sql, $bind) !== $expected) $safe = false;
                if ($expected === 1 && (!isset($hashes[$name]) || $id <= 0
                    || $rowHash($pdo, $table, $key, $id) !== $hashes[$name])) {
                    $safe = false;
                }
            }
            if ($dishId > 0 && $rowHash($ai, 'yoshop_dishes', 'ID', $dishId)
                !== $dishHash) $referenceStable = false;
        }
    } catch (Throwable $ignored) {
        $safe = false;
    }
    $cleanup['ownership_gate'] = $safe;
    $deleteOrder = [
        'health_record' => [$store, 'ydy_health_record', 'RECORD_ID'],
        'measurement_session' => [$store, 'ydy_measurement_session', 'SESSION_ID'],
        'meal_infos' => [$ai, 'yoshop_meal_infos', 'ID'],
        'meal' => [$ai, 'yoshop_meal', 'ID'],
        'staff' => [$ai, 'yoshop_staff', 'ID'],
        'user' => [$ai, 'yoshop_user', 'USER_ID'],
    ];
    foreach ($deleteOrder as $name => [$pdo, $table, $key]) {
        if (!isset($ids[$name])) {
            $cleanup[$name] = 0;
            continue;
        }
        if (!$safe) {
            $cleanup[$name] = -1;
            continue;
        }
        $stage = 'finally_delete_' . $name;
        try {
            if ($name === 'user') {
                $extra = ' AND NICK_NAME=? AND STORE_ID=10001';
            } elseif ($name === 'staff') {
                $extra = ' AND USER_ID=? AND STORE_ID=10001';
            } elseif ($name === 'meal' || $name === 'meal_infos') {
                $extra = ' AND STAFF_ID=? AND CREATE_BY=?';
            } elseif ($name === 'measurement_session') {
                $extra = ' AND RAW_HASH=? AND AI_USER_ID=?';
            } else {
                $extra = ' AND SESSION_ID=? AND AI_USER_ID=?';
            }
            $bind = [$ids[$name]];
            if ($name === 'user') {
                $bind[] = $marker;
            } elseif ($name === 'meal' || $name === 'meal_infos') {
                $bind[] = $ids['staff'];
                $bind[] = $marker;
            } elseif ($name === 'staff' || $name === 'health_record') {
                $bind[] = $name === 'staff' ? $ids['user'] : $ids['measurement_session'];
                if ($name === 'health_record') $bind[] = $ids['user'];
            } else {
                $bind[] = $marker;
                $bind[] = $ids['user'];
            }
            $pdo->prepare('DELETE FROM ' . $table . ' WHERE ' . $key . '=?' . $extra)
                ->execute($bind);
            $cleanup[$name] = $num($pdo,
                'SELECT COUNT(*) FROM ' . $table . ' WHERE ' . $key . '=?',
                [$ids[$name]]);
        } catch (Throwable $ignored) {
            $cleanup[$name] = -1;
            $safe = false;
        }
    }
}
$clean = ($cleanup['cache_absent'] ?? false) === true
    && ($cleanup['ownership_gate'] ?? false) === true;
foreach (['health_record', 'measurement_session', 'meal_infos', 'meal',
    'staff', 'user'] as $name) {
    $clean = $clean && isset($cleanup[$name]) && $cleanup[$name] === 0;
}
$pass = $error === null && $referenceStable && $globalWeekIsolated
    && count($cases) === ($caseSet === 'tail' ? 2 : 3)
    && !in_array(false, array_column($cases, 'pass'), true) && $clean;
echo json_encode(['status' => $pass ? 'health-read-ab-pass' : 'health-read-ab-not-closed',
    'target' => $target, 'case_set' => $caseSet,
    'marker' => $marker, 'synthetic_ids' => $ids,
    'cases' => $cases, 'error' => $error,
    'cleanup' => $cleanup, 'reference_dish_stable' => $referenceStable,
    'global_week_isolated' => $globalWeekIsolated],
    JSON_UNESCAPED_SLASHES), PHP_EOL;
exit($pass ? 0 : 3);
