<?php
declare(strict_types=1);

// Default path is read-only preflight. The write/HTTP phase needs separate root approval.
const CDX_PROFILE_WRITE_TOKEN = 'CDX_PROFILE_WRITE_APPROVED_20261002_V1';
$GLOBALS['cdx_stage'] = 'bootstrap';
set_exception_handler(static function (Throwable $error): void {
    echo json_encode(['status' => 'redacted-error',
        'stage' => $GLOBALS['cdx_stage'] ?? 'unknown',
        'class' => get_class($error), 'code' => (string)$error->getCode()],
        JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(2);
});
set_error_handler(static function (int $severity): bool {
    if (!(error_reporting() & $severity)) return false;
    throw new ErrorException('redacted warning', 0, $severity);
});

$target = (string)getenv('POC_PROFILE_TARGET');
$dialect = $target === 'C' ? 'dm' : 'mysql';
$caseSet = (string)getenv('CDX_PROFILE_CASE_SET');
if ($caseSet === '') $caseSet = 'all';
if (!in_array($caseSet, ['all', 'tail'], true)
    || ($caseSet === 'tail' && $target !== 'B')) {
    throw new RuntimeException('Approved case set/target mismatch');
}
$GLOBALS['cdx_stage'] = 'runtime_identity';
$roots = [
    'A' => ['/private/tmp/zhct-http-ai-macos.zjaU8h', 'http://127.0.0.1:18105'],
    'B' => ['/private/tmp/zhct-http-ai-macos.x2CCZX', 'http://127.0.0.1:18101'],
    'C' => ['/tmp/zhct-ai-http-20260929.3XDj3w', 'http://127.0.0.1:18102'],
];
if (!isset($roots[$target])) throw new RuntimeException('Explicit A/B/C target required');
[$root, $baseUrl] = $roots[$target];
putenv('POC_TARGET_ROOT=' . $root);
putenv('POC_BASE_URL=' . $baseUrl);
$settings = [];
if ($target === 'C') {
    $raw = file_get_contents('/proc/53772/environ');
    if ($raw === false) throw new RuntimeException('Approved C POC unavailable');
    foreach (explode("\0", $raw) as $part) {
        if (strpos($part, 'POC_') !== 0) continue;
        $position = strpos($part, '=');
        if ($position !== false) {
            $settings[substr($part, 0, $position)] = substr($part, $position + 1);
        }
    }
    if (($settings['POC_DIALECT'] ?? '') !== 'dm'
        || ($settings['POC_EXTERNAL_STUBS'] ?? '') !== '1'
        || ($settings['POC_AI_HOST'] ?? '') !== '127.0.0.1'
        || ($settings['POC_AI_PORT'] ?? '') !== '5238'
        || ($settings['POC_AI_SCHEMA'] ?? '') !== 'AIZHCT_APP'
        || ($settings['POC_HOST'] ?? '') !== '127.0.0.1'
        || ($settings['POC_PORT'] ?? '') !== '5237'
        || ($settings['POC_SCHEMA'] ?? '') !== 'ZHCT_APP') {
        throw new RuntimeException('C AI database boundary mismatch');
    }
    $cmdline = file_get_contents('/proc/53772/cmdline');
    if ($cmdline === false
        || strpos($cmdline, '/tmp/zhct-ai-http-20260929.3XDj3w/public') === false
        || strpos($cmdline, '127.0.0.1:18102') === false) {
        throw new RuntimeException('C isolated process mismatch');
    }
    foreach ($settings as $key => $value) {
        if (strpos($key, 'POC_') === 0) putenv($key . '=' . $value);
    }
} else {
    $local = realpath((string)getenv('POC_MYSQL_LOCAL_ENV'));
    if ($local !== '/Users/wiscourper/Documents/workspace/zhct/zhctproject/ai_api/.env.local') {
        throw new RuntimeException('Approved local development config required');
    }
    $ini = parse_ini_file($local, true, INI_SCANNER_RAW);
    if (!is_array($ini) || !isset($ini['DATABASE'], $ini['DATABASE_ZHCT'])) {
        throw new RuntimeException('Local development database config unavailable');
    }
    foreach (['DATABASE' => 'POC_AI_', 'DATABASE_ZHCT' => 'POC_'] as $section => $prefix) {
        foreach (['HOSTNAME' => 'HOST', 'HOSTPORT' => 'PORT', 'DATABASE' => 'SCHEMA',
            'USERNAME' => 'USER', 'PASSWORD' => 'PASSWORD'] as $from => $to) {
            $settings[$prefix . $to] = (string)($ini[$section][$from] ?? '');
        }
    }
    $httpPid = (int)getenv('CDX_PROFILE_HTTP_PID');
    $httpCommand = $httpPid > 1
        ? shell_exec('/bin/ps eww -p ' . $httpPid . ' -o command=') : null;
    $port = $target === 'A' ? 18105 : 18101;
    $displayRoot = str_replace('/private/tmp/', '/tmp/', $root);
    if (!is_string($httpCommand) || $httpCommand === ''
        || strpos($httpCommand, '-S 127.0.0.1:' . $port) === false
        || (strpos($httpCommand, $root . '/public') === false
            && strpos($httpCommand, $displayRoot . '/public') === false)) {
        throw new RuntimeException('A/B isolated HTTP process mismatch');
    }
    foreach ($settings as $key => $value) {
        if ($value === '' || preg_match('/\s/', $value)
            || preg_match('/(?:^|\s)' . preg_quote($key . '=' . $value, '/')
                . '(?=\s|$)/', $httpCommand) !== 1) {
            throw new RuntimeException('A/B HTTP database config differs from local development');
        }
        putenv($key . '=' . $value);
    }
    putenv('POC_DIALECT=mysql');
    putenv('POC_EXTERNAL_STUBS=1');
}
foreach (['POC_AI_HOST', 'POC_AI_PORT', 'POC_AI_SCHEMA',
    'POC_AI_USER', 'POC_AI_PASSWORD'] as $key) {
    if (empty($settings[$key])) throw new RuntimeException('AI test DB config incomplete');
}
$GLOBALS['cdx_stage'] = 'external_stub_boundary';
$boundary = json_decode((string)file_get_contents($baseUrl . '/__poc_boundary'), true);
if (empty($boundary['external_stubs']) || !is_file($root . '/vendor/autoload.php')) {
    throw new RuntimeException('Isolated HTTP/stub/runtime unavailable');
}
$GLOBALS['cdx_stage'] = 'ai_database_identity';
$dsn = $dialect === 'dm'
    ? 'dm:host=' . $settings['POC_AI_HOST'] . ';port=' . $settings['POC_AI_PORT']
        . ';schema=' . $settings['POC_AI_SCHEMA']
    : 'mysql:host=' . $settings['POC_AI_HOST'] . ';port=' . $settings['POC_AI_PORT']
        . ';dbname=' . $settings['POC_AI_SCHEMA'] . ';charset=utf8';
$pdo = new PDO($dsn, $settings['POC_AI_USER'], $settings['POC_AI_PASSWORD'], [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_CASE => PDO::CASE_LOWER,
]);
if ($dialect === 'dm') {
    $owner = strtoupper((string)$pdo->query('SELECT USER FROM DUAL')->fetchColumn());
    $schema = strtoupper((string)$pdo->query(
        "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL"
    )->fetchColumn());
    if ($owner !== 'AIZHCT_APP' || $schema !== 'AIZHCT_APP') {
        throw new RuntimeException('C AI owner/schema mismatch');
    }
} elseif ((string)$pdo->query('SELECT DATABASE()')->fetchColumn()
    !== $settings['POC_AI_SCHEMA']) {
    throw new RuntimeException('Local AI schema mismatch');
}
$GLOBALS['cdx_stage'] = 'store_database_identity';
foreach (['POC_HOST', 'POC_PORT', 'POC_SCHEMA', 'POC_USER', 'POC_PASSWORD'] as $key) {
    if (empty($settings[$key])) throw new RuntimeException('Store named DB config incomplete');
}
$storeDsn = $dialect === 'dm'
    ? 'dm:host=' . $settings['POC_HOST'] . ';port=' . $settings['POC_PORT']
        . ';schema=' . $settings['POC_SCHEMA']
    : 'mysql:host=' . $settings['POC_HOST'] . ';port=' . $settings['POC_PORT']
        . ';dbname=' . $settings['POC_SCHEMA'] . ';charset=utf8';
$storePdo = new PDO($storeDsn, $settings['POC_USER'], $settings['POC_PASSWORD'], [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
if ($dialect === 'dm') {
    $storeUser = strtoupper((string)$storePdo->query('SELECT USER FROM DUAL')->fetchColumn());
    $storeSchema = strtoupper((string)$storePdo->query(
        "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL"
    )->fetchColumn());
    if ($storeUser !== 'ZHCT_APP' || $storeSchema !== 'ZHCT_APP') {
        throw new RuntimeException('C Store owner/schema mismatch');
    }
} elseif ((string)$storePdo->query('SELECT DATABASE()')->fetchColumn()
    !== $settings['POC_SCHEMA']) {
    throw new RuntimeException('Local Store schema mismatch');
}
$storePdo = null;
$GLOBALS['cdx_stage'] = 'required_ai_table_columns';
$tables = [];
foreach (['user', 'staff', 'user_weight', 'user_weight_status',
    'user_disease', 'user_score_log', 'habit',
    'config_enum', 'user_other_info'] as $name) {
    $table = 'yoshop_' . $name;
    $tables[$name] = $dialect === 'dm' ? strtoupper($table) : $table;
}
$required = [
    'user' => 'USER_ID,STORE_ID,NICK_NAME,IS_DELETE,CREATE_TIME',
    'staff' => 'ID,USER_ID,STORE_ID,NAME,GENDER,BIRTHDAY,HEIGHT,WEIGHT,PHONE,IS_DELETE',
    'user_weight' => 'ID,USER_ID,STORE_ID,DATE,WEIGHT,HEIGHT,BMI,CREATE_TIME,UPDATE_TIME',
    'user_weight_status' => 'ID,USER_ID,STORE_ID,START_DATE,INITIAL_WEIGHT,END_DATE,TARGET_WEIGHT,STATUS,ADJUST_SPEED,DELETE_FLAG,CREATE_TIME,UPDATE_TIME',
    'user_disease' => 'ID,USER_ID,STORE_ID,DISEASE_TYPE,IS_DELETE,CREATE_TIME,UPDATE_TIME',
    'user_score_log' => 'ID,USER_ID,STORE_ID,TYPE,MEAL_TIMES,DATE,CREATE_TIME,UPDATE_TIME',
    'habit' => 'ID,STAFF_ID,STORE_ID,IS_DELETE',
    'config_enum' => 'ID,ENUM_TYPE,IS_DELETE',
    'user_other_info' => 'ID,USER_ID,STORE_ID,IS_DELETE',
];
foreach ($required as $name => $columns) {
    $GLOBALS['cdx_stage'] = 'required_ai_table_' . $name;
    $pdo->query('SELECT ' . $columns . ' FROM ' . $tables[$name] . ' WHERE 1=0');
}
if (!hash_equals(CDX_PROFILE_WRITE_TOKEN,
    (string)getenv('CDX_PROFILE_WRITE_APPROVAL'))) {
    echo json_encode([
        'status' => 'profile-readonly-preflight-pass',
        'target' => $target, 'dialect' => $dialect, 'case_set' => $caseSet,
        'runtime_process_match' => true,
        'ai_and_store_schema_match' => true,
        'external_stubs' => true,
        'required_ai_table_count' => count($required),
        'required_columns_queryable' => true,
        'write_phase_entered' => false,
    ], JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(0);
}
$GLOBALS['cdx_stage'] = 'approved_fixture_bootstrap';
define('TP_ENV', 'poc');
define('BUSINESS', 'aizhct');
define('ENTERPRISE_NO', '10001');
require $root . '/vendor/autoload.php';
(new \think\App($root))->setEnvName('poc')->initialize();
$marker = 'CDXPARPROFILE' . strtoupper(bin2hex(random_bytes(5)));
$token = $marker . 'T' . strtoupper(bin2hex(random_bytes(10)));
$today = date('Y-m-d');
$dayEpoch = strtotime($today . ' 00:00:00');
$now = time();
$userId = 0;
$staffId = 0;
$ids = [];
$rows = [];
$snapshots = [];
$evidence = [];
$error = null;
$cleanup = [];
echo json_encode(['stage' => 'fixture_before_write', 'target' => $target,
    'marker' => $marker], JSON_UNESCAPED_SLASHES), PHP_EOL;
flush();
$readOne = static function (string $sql, array $bind = []) use ($pdo): array {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($bind);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    return is_array($row) ? $row : [];
};
$count = static function (string $sql, array $bind = []) use ($pdo): int {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($bind);
    return (int)$stmt->fetchColumn();
};
$snapshot = static function (string $name, int $id) use ($pdo, $tables): string {
    $primary = $name === 'user' ? 'USER_ID' : 'ID';
    $statement = $pdo->prepare('SELECT * FROM ' . $tables[$name]
        . ' WHERE USER_ID=? AND STORE_ID=10001 ORDER BY ' . $primary);
    $statement->execute([$id]);
    return hash('sha256', json_encode($statement->fetchAll(PDO::FETCH_ASSOC),
        JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
};
$captureId = static function (string $name, int $id) use ($pdo, $tables): int {
    $statement = $pdo->prepare('SELECT ID,USER_ID,STORE_ID FROM ' . $tables[$name]
        . ' WHERE USER_ID=?');
    $statement->execute([$id]);
    $found = $statement->fetchAll(PDO::FETCH_ASSOC);
    if (count($found) !== 1 || (int)$found[0]['user_id'] !== $id
        || (int)$found[0]['store_id'] !== 10001
        || (int)$found[0]['id'] <= 0) {
        throw new RuntimeException('Fixture ID attribution unavailable');
    }
    return (int)$found[0]['id'];
};
$request = static function (string $method, string $path, array $params)
    use ($baseUrl, $token): array {
    $query = ['storeId' => 10001];
    if ($method === 'GET') $query += $params;
    $url = $baseUrl . $path . '?' . http_build_query($query);
    $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 === [] ? (object)[] : $params,
            JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }
    $text = file_get_contents($url, false, stream_context_create(['http' => $options]));
    $line = $http_response_header[0] ?? '';
    $body = is_string($text) ? json_decode($text, true) : null;
    return ['http' => preg_match('/HTTP\/\S+\s+(\d+)/', $line, $match)
            ? (int)$match[1] : 0,
        'body' => $body];
};
$shape = null;
$shape = static function ($value, int $depth = 0) use (&$shape) {
    if (!is_array($value)) return gettype($value);
    if ($depth >= 3) 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)];
    }
    $result = [];
    foreach ($value as $key => $item) $result[$key] = $shape($item, $depth + 1);
    return $result;
};
$hasSensitiveKey = null;
$hasSensitiveKey = static function ($value) use (&$hasSensitiveKey): bool {
    if (!is_array($value)) return false;
    $forbidden = ['api_key', 'secret', 'password', 'access_token',
        'refresh_token', 'authorization'];
    foreach ($value as $key => $item) {
        if (is_string($key) && in_array(strtolower($key), $forbidden, true)) {
            return true;
        }
        if ($hasSensitiveKey($item)) return true;
    }
    return false;
};
try {
    if ($count('SELECT COUNT(*) FROM ' . $tables['user']
        . ' WHERE NICK_NAME=? AND STORE_ID=10001', [$marker]) !== 0) {
        throw new RuntimeException('Synthetic marker already exists');
    }
    $pdo->prepare('INSERT INTO ' . $tables['user']
        . ' (STORE_ID,MOBILE,NICK_NAME,BALANCE,GIFT_BALANCE,IS_DELETE,CREATE_TIME)'
        . ' VALUES (10001,?,?,?,?,0,?)')
        ->execute(['', $marker, '0.00', '0.00', $now]);
    $userId = (int)($readOne('SELECT USER_ID FROM ' . $tables['user']
        . ' WHERE NICK_NAME=? AND STORE_ID=10001', [$marker])['user_id'] ?? 0);
    if ($userId < 1) throw new RuntimeException('Synthetic user not found');
    $ids['user'] = $userId;
    $snapshots['user'] = $snapshot('user', $userId);
    $pdo->prepare('INSERT INTO ' . $tables['staff']
        . ' (NAME,USER_ID,STORE_ID,HEIGHT,WEIGHT,GENDER,BIRTHDAY,PHONE,IS_DELETE)'
        . " VALUES (?,?,10001,170,60,1,'1990-01-01','',0)")
        ->execute([$marker, $userId]);
    $staffId = (int)($readOne('SELECT ID FROM ' . $tables['staff']
        . ' WHERE USER_ID=? AND STORE_ID=10001 AND NAME=?', [$userId, $marker])['id'] ?? 0);
    if ($staffId < 1) throw new RuntimeException('Synthetic staff not found');
    $ids['staff'] = $captureId('staff', $userId);
    $snapshots['staff'] = $snapshot('staff', $userId);
    $pdo->prepare('INSERT INTO ' . $tables['user_weight']
        . ' (USER_ID,STORE_ID,DATE,WEIGHT,HEIGHT,BMI,CREATE_TIME,UPDATE_TIME)'
        . ' VALUES (?,10001,?,?,?,?,?,?)')
        ->execute([$userId, $dayEpoch, '60.00', '170.00', '20.76', $now, $now]);
    $ids['user_weight'] = $captureId('user_weight', $userId);
    $snapshots['user_weight'] = $snapshot('user_weight', $userId);
    $pdo->prepare('INSERT INTO ' . $tables['user_weight_status']
        . ' (USER_ID,STORE_ID,START_DATE,INITIAL_WEIGHT,END_DATE,TARGET_WEIGHT,'
        . 'STATUS,ADJUST_SPEED,DELETE_FLAG,CREATE_TIME,UPDATE_TIME)'
        . ' VALUES (?,10001,?,?,0,?,1,1,0,?,?)')
        ->execute([$userId, $dayEpoch, '60.00', '60.00', $now, $now]);
    $ids['user_weight_status'] = $captureId('user_weight_status', $userId);
    $snapshots['user_weight_status'] = $snapshot('user_weight_status', $userId);
    $pdo->prepare('INSERT INTO ' . $tables['user_disease']
        . ' (USER_ID,STORE_ID,DISEASE_TYPE,IS_DELETE,CREATE_TIME,UPDATE_TIME)'
        . ' VALUES (?,10001,1,0,?,?)')
        ->execute([$userId, $now, $now]);
    $ids['user_disease'] = $captureId('user_disease', $userId);
    $snapshots['user_disease'] = $snapshot('user_disease', $userId);
    $pdo->prepare('INSERT INTO ' . $tables['user_score_log']
        . ' (USER_ID,STORE_ID,TYPE,MEAL_TIMES,DATE,SCORE,CREATE_TIME,UPDATE_TIME)'
        . ' VALUES (?,10001,2,1,?,1,?,?)')
        ->execute([$userId, $today, $now, $now]);
    $ids['user_score_log'] = $captureId('user_score_log', $userId);
    $snapshots['user_score_log'] = $snapshot('user_score_log', $userId);
    foreach (['staff', 'user_weight', 'user_weight_status',
        'user_disease', 'user_score_log'] as $name) {
        $rows[$name] = $count('SELECT COUNT(*) FROM ' . $tables[$name]
            . ' WHERE USER_ID=? AND STORE_ID=10001', [$userId]);
        if ($rows[$name] !== 1) throw new RuntimeException('Fixture readback count mismatch');
    }
    $cacheSaved = \think\facade\Cache::set($token, [
        'user' => ['user_id' => $userId],
        'password_version' => 0, 'login_type' => 'thirdparty',
    ], 300);
    if (!$cacheSaved) throw new RuntimeException('Synthetic token cache unavailable');

    $calls = [
        'weight_info' => ['POST', '/api/user.userWeight/info', []],
        'weight_goal_info' => ['POST', '/api/user.userWeight/weightManageInfo', []],
        'weight_list' => ['POST', '/api/user.userWeight/weightList', []],
        'weight_dates' => ['GET', '/api/user.userWeight/dates', []],
        'weight_by_date' => ['GET', '/api/user.UserWeight/byDateDetail', ['date' => $today]],
        'score_diet' => ['POST', '/api/user.score/diet',
            ['form' => ['meal_times' => 1, 'meal_date' => $today]]],
        'weight_status' => ['GET', '/api/user.UserWeight/status', []],
        'disease_info' => ['POST', '/api/user.disease/info', []],
    ];
    if ($caseSet === 'tail') {
        $calls = array_intersect_key($calls, array_flip([
            'score_diet', 'weight_status', 'disease_info',
        ]));
    }
    // Exact key/type maps observed independently in A-original and C-DM.
    // Values, names and other user data are deliberately absent.
    $tailShapes = [
        'score_diet' => ['exists' => 'boolean'],
        'weight_status' => [
            'id' => 'integer', 'user_id' => 'integer', 'store_id' => 'integer',
            'start_date' => 'integer', 'initial_weight' => 'string',
            'end_date' => 'integer', 'target_weight' => 'string',
            'status' => 'integer', 'adjust_speed' => 'integer',
            'delete_flag' => 'integer', 'shanghe_session_id' => 'NULL',
            'start_date_fmt' => 'string', 'end_date_fmt' => 'string',
            'current_status' => 'integer', 'latest_weight' => 'string',
            'latest_date' => 'string', 'finish_status' => 'integer',
            'total_days' => 'integer', 'huashu' => 'string',
        ],
        'disease_info' => [
            'disease' => ['list_count' => 5, 'first' => [
                'name' => 'string', 'value' => 'integer', 'is_checked' => 'integer']],
            'habit' => ['list_count' => 5, 'first' => [
                'enum_key' => 'string', 'enum_name' => 'string',
                'people' => 'string', 'ratio' => 'string', 'checked' => 'integer']],
            'sport' => ['id' => 'integer', 'name' => 'string'],
            'foodAllergy' => ['list_count' => 8, 'first' => [
                'enum_key' => 'string', 'enum_name' => 'string',
                'is_checked' => 'integer']],
            'foodAvoidance' => ['list_count' => 4, 'first' => [
                'enum_key' => 'string', 'enum_name' => 'string',
                'is_checked' => 'integer']],
            'dietaryPreference' => ['list_count' => 7, 'first' => [
                'enum_key' => 'string', 'enum_name' => 'string',
                'is_checked' => 'integer']],
            'otherConcerns' => ['list_count' => 3, 'first' => [
                'enum_key' => 'string', 'enum_name' => 'string',
                'is_checked' => 'integer']],
        ],
    ];
    foreach ($calls as $name => [$method, $path, $params]) {
        $GLOBALS['cdx_stage'] = 'business_case_' . $name;
        $response = $request($method, $path, $params);
        $body = $response['body'];
        $data = is_array($body) ? ($body['data'] ?? null) : null;
        $sensitiveKey = $hasSensitiveKey($data);
        $ok = $response['http'] === 200
            && is_array($body) && (int)($body['status'] ?? -1) === 200
            && is_array($data) && !$sensitiveKey;
        if ($name === 'weight_info') $ok = $ok
            && is_array($data['weight_echarts'] ?? null)
            && count($data['weight_echarts']) === 1;
        if ($name === 'weight_goal_info') $ok = $ok
            && (float)($data['initial_weight'] ?? -1) === 60.0;
        if ($name === 'weight_list') $ok = $ok && count($data) === 1;
        if ($name === 'weight_dates') $ok = $ok
            && is_array($data['list'] ?? null) && in_array($today, $data['list'], true);
        if ($name === 'weight_by_date') $ok = $ok
            && is_array($data['data'] ?? null)
            && is_array($data['list'] ?? null)
            && count($data['list']) === 1;
        if ($name === 'weight_status') $ok = $ok
            && (int)($data['status'] ?? -1) === 1
            && (float)($data['initial_weight'] ?? -1) === 60.0;
        if ($name === 'disease_info') {
            $checked = false;
            foreach (($data['disease'] ?? []) as $disease) {
                if (is_array($disease) && (int)($disease['value'] ?? 0) === 1
                    && (int)($disease['is_checked'] ?? 0) === 1) $checked = true;
            }
            $ok = $ok && $checked;
        }
        if ($name === 'score_diet') $ok = $ok
            && ($data['exists'] ?? null) === true;
        $shapeMatch = $caseSet !== 'tail' || !$sensitiveKey
            && $shape($data) === $tailShapes[$name];
        $ok = $ok && $shapeMatch;
        $evidence[$name] = [
            'method' => $method, 'path' => $path,
            'http' => $response['http'],
            'business_status' => is_array($body) ? ($body['status'] ?? null) : null,
            'data_shape' => $sensitiveKey ? 'blocked_sensitive_key' : $shape($data),
            'contract_matches_a_c' => $caseSet === 'tail' ? $shapeMatch : null,
            'sensitive_key_present' => $sensitiveKey,
            'pass' => $ok,
        ];
        if (!$ok) break;
    }
    foreach ($snapshots as $name => $before) {
        if ($snapshot($name, $userId) !== $before) {
            throw new RuntimeException('Read endpoint changed synthetic row');
        }
    }
} catch (Throwable $failure) {
    $error = ['class' => get_class($failure),
        'code' => (string)$failure->getCode(),
        'stage' => $GLOBALS['cdx_stage'] ?? 'unknown'];
} finally {
    try {
        \think\facade\Cache::delete($token);
        $cleanup['cache_absent'] = \think\facade\Cache::get($token) === null;
    } catch (Throwable $cacheError) {
        $cleanup['cache_absent'] = false;
    }
    if ($userId <= 0) {
        try {
            $userId = (int)($readOne('SELECT USER_ID FROM ' . $tables['user']
                . ' WHERE NICK_NAME=? AND STORE_ID=10001', [$marker])['user_id'] ?? 0);
        } catch (Throwable $lookupError) {
            $userId = 0;
        }
    }
    if ($userId > 0) {
        $childTables = ['user_score_log', 'user_disease',
            'user_weight_status', 'user_weight', 'staff'];
        $ownershipVerified = isset($ids['user']) && $ids['user'] === $userId
            && isset($snapshots['user']);
        try {
            $ownerRows = $pdo->prepare('SELECT USER_ID,STORE_ID,NICK_NAME FROM '
                . $tables['user'] . ' WHERE USER_ID=?');
            $ownerRows->execute([$userId]);
            $owners = $ownerRows->fetchAll(PDO::FETCH_ASSOC);
            $ownershipVerified = $ownershipVerified && count($owners) === 1
                && (int)$owners[0]['user_id'] === $userId
                && (int)$owners[0]['store_id'] === 10001
                && (string)$owners[0]['nick_name'] === $marker;
            foreach ($childTables as $name) {
                $statement = $pdo->prepare('SELECT ID,USER_ID,STORE_ID FROM '
                    . $tables[$name] . ' WHERE USER_ID=?');
                $statement->execute([$userId]);
                $ownedRows = $statement->fetchAll(PDO::FETCH_ASSOC);
                if (isset($ids[$name])) {
                    $ownershipVerified = $ownershipVerified
                        && isset($snapshots[$name]) && count($ownedRows) === 1
                        && (int)$ownedRows[0]['id'] === $ids[$name]
                        && (int)$ownedRows[0]['user_id'] === $userId
                        && (int)$ownedRows[0]['store_id'] === 10001;
                } else {
                    // A failed partial INSERT may leave no registered child.
                    // Any unregistered row is unknown and forbids all deletion.
                    $ownershipVerified = $ownershipVerified
                        && count($ownedRows) === 0;
                }
            }
            foreach ($snapshots as $name => $beforeHash) {
                $ownershipVerified = $ownershipVerified
                    && $snapshot($name, $userId) === $beforeHash;
            }
        } catch (Throwable $checkError) {
            $ownershipVerified = false;
        }
        $cleanup['ownership_gate'] = $ownershipVerified;
        if ($ownershipVerified) {
            foreach ($childTables as $name) {
                if (!isset($ids[$name])) {
                    $cleanup[$name] = 0;
                    continue;
                }
                try {
                    $pdo->prepare('DELETE FROM ' . $tables[$name]
                        . ' WHERE ID=? AND USER_ID=? AND STORE_ID=10001')
                        ->execute([$ids[$name], $userId]);
                    $cleanup[$name] = $count('SELECT COUNT(*) FROM ' . $tables[$name]
                        . ' WHERE USER_ID=?', [$userId]);
                } catch (Throwable $cleanupError) {
                    $cleanup[$name] = -1;
                }
            }
            $childrenClean = true;
            foreach ($childTables as $name) {
                $childrenClean = $childrenClean && $cleanup[$name] === 0;
            }
            if ($childrenClean) {
                try {
                    $pdo->prepare('DELETE FROM ' . $tables['user']
                        . ' WHERE USER_ID=? AND STORE_ID=10001 AND NICK_NAME=?')
                        ->execute([$userId, $marker]);
                    $cleanup['user'] = $count('SELECT COUNT(*) FROM ' . $tables['user']
                        . ' WHERE USER_ID=?', [$userId]);
                } catch (Throwable $cleanupError) {
                    $cleanup['user'] = -1;
                }
            } else {
                $cleanup['user'] = -1;
            }
        } else {
            foreach ($childTables as $name) $cleanup[$name] = -1;
            $cleanup['user'] = -1;
        }
    }
}
$clean = ($cleanup['cache_absent'] ?? false) === true;
$clean = $clean && ($cleanup['ownership_gate'] ?? false) === true;
foreach (['user', 'staff', 'user_weight', 'user_weight_status',
    'user_disease', 'user_score_log'] as $name) {
    $clean = $clean && isset($cleanup[$name]) && $cleanup[$name] === 0;
}
$pass = $error === null && count($evidence) === ($caseSet === 'tail' ? 3 : 8)
    && !in_array(false, array_column($evidence, 'pass'), true)
    && $clean;
echo json_encode([
    'status' => $pass ? 'profile-weight-motion-pass' : 'profile-weight-motion-not-closed',
    'target' => $target, 'case_set' => $caseSet,
    'marker' => $marker, 'user_id' => $userId,
    'fixture_ids' => $ids,
    'fixture_tables' => $rows,
    'cases' => $evidence, 'error' => $error, 'cleanup_counts' => $cleanup,
], JSON_UNESCAPED_SLASHES), PHP_EOL;
exit($pass ? 0 : 3);
