<?php

declare(strict_types=1);

// Draft only. Without POC_APPROVED_SPORT_DISPLAY_WRITE=1 this performs read-only preflight.
set_exception_handler(static function (Throwable $error): void {
    fwrite(STDERR, 'SPORT_DISPLAY_TEST_FAILED ' . get_class($error)
        . ' code=' . (string)$error->getCode() . PHP_EOL);
    exit(2);
});
$preflightStage = 'bootstrap';
if ((string)getenv('POC_DIAGNOSTIC_STAGE') === '1') {
    register_shutdown_function(static function () use (&$preflightStage): void {
        echo json_encode(['mode' => 'redacted-preflight-stage',
            'last_stage' => $preflightStage], JSON_UNESCAPED_SLASHES) . PHP_EOL;
    });
}
$root = (string)getenv('POC_TARGET_ROOT');
$base = rtrim((string)getenv('POC_BASE_URL'), '/');
$dialect = (string)getenv('POC_DIALECT');
$variant = (string)getenv('POC_VARIANT');
$approved = [
    'A' => ['/tmp/zhct-http-ai-macos.zjaU8h', 'http://127.0.0.1:18105', 'mysql'],
    'B' => ['/tmp/zhct-http-ai-macos.x2CCZX', 'http://127.0.0.1:18101', 'mysql'],
    'C' => ['/tmp/zhct-ai-http-20260929.3XDj3w', 'http://127.0.0.1:18102', 'dm'],
];
if (!isset($approved[$variant]) || [$root, $base, $dialect] !== $approved[$variant]
    || !is_file($root . '/vendor/autoload.php')) {
    throw new RuntimeException('Unapproved isolated AI runtime');
}
if ($dialect === 'dm') {
    $pid = (string)getenv('POC_RUNTIME_PID');
    if (!ctype_digit($pid) || (int)$pid <= 1) throw new RuntimeException('AI PID missing');
    $processEnv = [];
    foreach (explode("\0", (string)@file_get_contents('/proc/' . $pid . '/environ')) as $item) {
        $parts = explode('=', $item, 2);
        if (count($parts) === 2) $processEnv[$parts[0]] = $parts[1];
    }
    if (($processEnv['POC_TARGET_ROOT'] ?? '') !== $root
        || ($processEnv['POC_BASE_URL'] ?? '') !== $base
        || ($processEnv['POC_DIALECT'] ?? '') !== 'dm') {
        throw new RuntimeException('C AI process identity mismatch');
    }
    foreach (['POC_AI_HOST', 'POC_AI_PORT', 'POC_AI_SCHEMA', 'POC_AI_USER',
        'POC_AI_PASSWORD', 'POC_HOST', 'POC_PORT', 'POC_SCHEMA', 'POC_USER',
        'POC_PASSWORD'] as $key) {
        if (empty($processEnv[$key])) throw new RuntimeException('C two-business-DB context missing');
        putenv($key . '=' . $processEnv[$key]);
    }
    if ((string)getenv('POC_AI_HOST') !== '127.0.0.1'
        || (string)getenv('POC_AI_PORT') !== '5238'
        || (string)getenv('POC_AI_SCHEMA') !== 'AIZHCT_APP'
        || (string)getenv('POC_AI_USER') !== 'AIZHCT_APP'
        || (string)getenv('POC_HOST') !== '127.0.0.1'
        || (string)getenv('POC_PORT') !== '5237'
        || (string)getenv('POC_SCHEMA') !== 'ZHCT_APP'
        || (string)getenv('POC_USER') !== 'ZHCT_APP') {
        throw new RuntimeException('C non-production dual-schema boundary failed');
    }
} else {
    $path = '/Users/wiscourper/Documents/workspace/zhct/zhctproject/ai_api/.env.local';
    if (realpath((string)getenv('POC_MYSQL_LOCAL_ENV')) !== realpath($path)) {
        throw new RuntimeException('Only AI code local configuration allowed');
    }
    $local = parse_ini_file($path, true, INI_SCANNER_RAW);
    if (!is_array($local) || !isset($local['DATABASE'], $local['DATABASE_ZHCT'])) {
        throw new RuntimeException('AI local two-business-DB configuration absent');
    }
    $pid = (string)getenv('POC_RUNTIME_PID');
    if (!ctype_digit($pid) || (int)$pid <= 1) {
        throw new RuntimeException('A/B HTTP PID missing');
    }
    $port = $variant === 'A' ? 18105 : 18101;
    $listener = trim((string)shell_exec('lsof -nP -iTCP:' . $port
        . ' -sTCP:LISTEN -t 2>/dev/null'));
    $process = (string)shell_exec('ps eww -p ' . (int)$pid . ' -o command=');
    if ($listener !== $pid
        || strpos($process, 'php -S 127.0.0.1:' . $port) === false
        || strpos($process, $root . '/public') === false) {
        throw new RuntimeException('A/B HTTP listener identity mismatch');
    }
    $processValue = static function (string $key) use ($process): ?string {
        $pattern = '/(?:^|\\s)' . preg_quote($key, '/') . '=([^\\s]*)/';
        return preg_match($pattern, $process, $match) ? $match[1] : null;
    };
    $expectedProcess = [
        'POC_TARGET_ROOT' => $root,
        'POC_BASE_URL' => $base,
        'POC_DIALECT' => 'mysql',
    ];
    foreach (['DATABASE' => 'POC_AI_', 'DATABASE_ZHCT' => 'POC_'] as $section => $prefix) {
        foreach (['HOSTNAME' => 'HOST', 'HOSTPORT' => 'PORT',
            'DATABASE' => 'SCHEMA', 'USERNAME' => 'USER',
            'PASSWORD' => 'PASSWORD'] as $from => $to) {
            $expectedProcess[$prefix . $to] = (string)$local[$section][$from];
        }
    }
    foreach ($expectedProcess as $key => $expectedValue) {
        if ($processValue($key) !== $expectedValue) {
            throw new RuntimeException('A/B HTTP process/local DB boundary mismatch');
        }
    }
    foreach (['DATABASE' => 'POC_AI_', 'DATABASE_ZHCT' => 'POC_'] as $section => $prefix) {
        foreach (['HOSTNAME' => 'HOST', 'HOSTPORT' => 'PORT', 'DATABASE' => 'SCHEMA',
            'USERNAME' => 'USER', 'PASSWORD' => 'PASSWORD'] as $from => $to) {
            putenv($prefix . $to . '=' . (string)$local[$section][$from]);
        }
    }
}
$boundaryRaw = @file_get_contents($base . '/__poc_boundary', false,
    stream_context_create(['http' => ['timeout' => 5]]));
$boundary = is_string($boundaryRaw) ? json_decode($boundaryRaw, true) : null;
if (!is_array($boundary) || empty($boundary['external_stubs'])) {
    throw new RuntimeException('AI external isolation absent');
}
$preflightStage = 'http_boundary_verified';

define('TP_ENV', 'poc');
define('BUSINESS', 'aizhct');
define('ENTERPRISE_NO', '10001');
require $root . '/vendor/autoload.php';
(new \think\App($root))->setEnvName('poc')->initialize();
$connect = static function (string $prefix) use ($dialect): PDO {
    $dsn = $dialect === 'dm'
        ? 'dm:host=' . getenv($prefix . 'HOST') . ';port=' . getenv($prefix . 'PORT')
            . ';schema=' . getenv($prefix . 'SCHEMA')
        : 'mysql:host=' . getenv($prefix . 'HOST') . ';port=' . getenv($prefix . 'PORT')
            . ';dbname=' . getenv($prefix . 'SCHEMA') . ';charset=utf8mb4';
    return new PDO($dsn, getenv($prefix . 'USER'), getenv($prefix . 'PASSWORD'),
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_TIMEOUT => 5]);
};
$preflightStage = 'ai_handshake';
$ai = $connect('POC_AI_');
$preflightStage = 'store_handshake';
$store = $connect('POC_');
$preflightStage = 'both_handshakes_ok';
if ($dialect === 'dm') {
    if ((string)$ai->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")
        ->fetchColumn() !== 'AIZHCT_APP'
        || (string)$store->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")
            ->fetchColumn() !== 'ZHCT_APP') {
        throw new RuntimeException('C actual schema mismatch');
    }
}
$table = static function (string $name) use ($dialect): string {
    return $dialect === 'dm' ? strtoupper($name) : $name;
};
$aiTables = [];
foreach (['user', 'staff', 'user_motion', 'sport_cate', 'store'] as $name) {
    $aiTables[$name] = $table('yoshop_' . $name);
}
$storeTables = [];
foreach (['measurement_session', 'measurement_session_raw', 'health_record', 'sports_equipment',
    'health_metric'] as $name) {
    $storeTables[$name] = $table('ydy_' . $name);
}
$count = static function (PDO $db, string $sql, array $args = []): int {
    $stmt = $db->prepare($sql);
    $stmt->execute($args);
    return (int)$stmt->fetchColumn();
};
$rows = static function (PDO $db, string $sql, array $args = []): array {
    $stmt = $db->prepare($sql);
    $stmt->execute($args);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
};
$assert = static function (bool $ok, string $message): void {
    if (!$ok) throw new RuntimeException($message);
};
$preflightStage = 'ai_empty_table_selects';
foreach ($aiTables as $name) $ai->query('SELECT 1 FROM ' . $name . ' WHERE 1=0');
$preflightStage = 'store_empty_table_selects';
foreach ($storeTables as $name) $store->query('SELECT 1 FROM ' . $name . ' WHERE 1=0');
$columns = static function (PDO $db, string $name) use ($dialect): array {
    $stmt = $dialect === 'dm'
        ? $db->prepare('SELECT COLUMN_NAME,NULLABLE FROM USER_TAB_COLUMNS WHERE TABLE_NAME=?')
        : $db->prepare('SELECT COLUMN_NAME,IS_NULLABLE AS NULLABLE FROM information_schema.COLUMNS'
            . ' WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=?');
    $stmt->execute([$name]);
    $result = [];
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $result[strtoupper($row['column_name'])] = strtoupper((string)$row['nullable']);
    }
    return $result;
};
$required = [
    [$ai, $aiTables['user'], ['USER_ID', 'NICK_NAME', 'STORE_ID']],
    [$ai, $aiTables['staff'], ['ID', 'USER_ID', 'WEIGHT']],
    [$ai, $aiTables['user_motion'], ['ID', 'USER_ID', 'DATE', 'MOVEMENT_STEPS']],
    [$ai, $aiTables['sport_cate'], ['ID', 'STORE_ID', 'IS_DELETE']],
    [$store, $storeTables['measurement_session'], ['SESSION_ID', 'AI_USER_ID',
        'START_TIME', 'VENDOR', 'DEVICE_TYPE', 'SPORTS_EQUIPMENT_ID', 'RAW_HASH']],
    [$store, $storeTables['measurement_session_raw'], ['ID', 'SESSION_ID']],
    [$store, $storeTables['health_record'], ['RECORD_ID', 'SESSION_ID', 'AI_USER_ID',
        'METRIC_CODE', 'VALUE', 'DATA_SOURCE_TYPE', 'SOURCE_PLATFORM', 'START_TIME']],
    [$store, $storeTables['sports_equipment'], ['ID']],
];
$metadata = [];
foreach ($required as [$db, $name, $fields]) {
    $preflightStage = $db === $ai ? 'ai_column_metadata' : 'store_column_metadata';
    $actual = $columns($db, $name);
    $assert(count(array_diff($fields, array_keys($actual))) === 0,
        'Sport display required columns missing');
    $metadata[$name] = $actual;
}
$assert(in_array($metadata[$storeTables['measurement_session']]['SPORTS_EQUIPMENT_ID'],
    ['Y', 'YES'], true), 'Synthetic session equipment FK must allow NULL');
$preflightStage = 'ai_store_and_category_counts';
$assert($count($ai, 'SELECT COUNT(*) FROM ' . $aiTables['store']
    . ' WHERE STORE_ID=? AND IS_DELETE=0', [10001]) === 1,
    'Approved AI store missing/ambiguous');
$assert($count($ai, 'SELECT COUNT(*) FROM ' . $aiTables['sport_cate']
    . ' WHERE STORE_ID=10001 AND IS_DELETE=0') > 0,
    'Active sport category fixture absent');
foreach (['activity_duration', 'calories_burned', 'distance'] as $metricCode) {
    $preflightStage = 'store_metric_dictionary';
    $assert($count($store, 'SELECT COUNT(*) FROM ' . $storeTables['health_metric']
        . ' WHERE METRIC_CODE=?', [$metricCode]) === 1,
        'Required Store metric dictionary missing/ambiguous');
}
if ((string)getenv('POC_APPROVED_SPORT_DISPLAY_WRITE') !== '1') {
    $preflightStage = 'preflight_success';
    echo json_encode(['suite' => 'sport-display-' . $variant,
        'mode' => 'read-only-preflight', 'tables_and_columns' => true,
        'nullable_equipment_id' => true, 'active_category' => true,
        'metric_dictionary' => true, 'external_stubs' => true],
        JSON_UNESCAPED_SLASHES) . PHP_EOL;
    exit(0);
}

$marker = 'CDXPARSPORT' . strtoupper(bin2hex(random_bytes(4)));
$token = $marker . 'TOKEN' . strtoupper(bin2hex(random_bytes(8)));
$today = date('Y-m-d');
$yesterday = date('Y-m-d', strtotime('-1 day'));
$start = $today . ' 10:00:00';
$end = $today . ' 10:02:00';
$userId = 0;
$sessionId = 0;
$results = [];
$cleanup = [];
$failure = '';
$request = static function (string $method, string $path, ?array $body = null,
    ?string $auth = null) use ($base): array {
    $headers = "platform: POC\r\nContent-Type: application/json;charset=utf-8\r\n";
    if ($auth !== null) $headers .= 'Access-Token: ' . $auth . "\r\n";
    $opts = ['method' => $method, 'header' => $headers, 'timeout' => 30,
        'ignore_errors' => true];
    if ($body !== null) {
        $opts['content'] = json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }
    $started = microtime(true);
    $raw = @file_get_contents($base . $path, false,
        stream_context_create(['http' => $opts]));
    $elapsed = (int)round((microtime(true) - $started) * 1000);
    $json = is_string($raw) ? json_decode($raw, true) : null;
    preg_match('/HTTP\/\S+\s+(\d+)/', $http_response_header[0] ?? '', $match);
    return ['http' => isset($match[1]) ? (int)$match[1] : 0,
        'status' => is_array($json) ? (int)($json['status'] ?? -1) : -1,
        'data' => is_array($json) ? ($json['data'] ?? null) : null,
        'complete' => is_array($json), 'elapsed_ms' => $elapsed];
};
$url = static function (string $path, array $query = []): string {
    return '/api/' . $path . '?' . http_build_query(array_merge(['storeId' => 10001], $query));
};
try {
    $assert($count($ai, 'SELECT COUNT(*) FROM ' . $aiTables['user']
        . ' WHERE NICK_NAME=?', [$marker]) === 0
        && $count($store, 'SELECT COUNT(*) FROM ' . $storeTables['measurement_session']
            . ' WHERE RAW_HASH=?', [$marker]) === 0,
        'Sport synthetic marker preexists');
    $ai->prepare('INSERT INTO ' . $aiTables['user']
        . ' (STORE_ID,MOBILE,NICK_NAME,BALANCE,GIFT_BALANCE,IS_DELETE,CREATE_TIME)'
        . ' VALUES (10001,?,?,?,?,0,?)')
        ->execute(['', $marker, '0.00', '0.00', time()]);
    $userRows = $rows($ai, 'SELECT USER_ID FROM ' . $aiTables['user']
        . ' WHERE NICK_NAME=?', [$marker]);
    $assert(count($userRows) === 1, 'Synthetic AI user missing/ambiguous');
    $userId = (int)$userRows[0]['user_id'];
    $assert($userId > 0 && $count($ai, 'SELECT COUNT(*) FROM ' . $aiTables['staff']
        . ' WHERE USER_ID=?', [$userId]) === 0,
        'Synthetic staff preexisting');
    $ai->prepare('INSERT INTO ' . $aiTables['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]);
    foreach ([[$yesterday, 1000], [$today, 2000]] as [$day, $steps]) {
        $ai->prepare('INSERT INTO ' . $aiTables['user_motion']
            . ' (USER_ID,STORE_ID,DATE,MOVEMENT_STEPS,CREATE_TIME,UPDATE_TIME)'
            . ' VALUES (?,10001,?,?,?,?)')
            ->execute([$userId, strtotime($day), $steps, time(), time()]);
    }
    \think\facade\Cache::set($token, ['user' => ['user_id' => $userId],
        'password_version' => 0, 'login_type' => 'thirdparty'], 300);

    $store->prepare('INSERT INTO ' . $storeTables['measurement_session']
        . ' (AI_USER_ID,EVENT_TYPE,START_TIME,END_TIME,SOURCE_PLATFORM,VENDOR,'
        . 'DEVICE_TYPE,SPORTS_EQUIPMENT_ID,RAW_HASH,BUSINESS_CONTEXT,IS_VALID,CREATED_AT)'
        . " VALUES (?,'activity',?,?,'vendor_api','yingjiduo','treadmill',NULL,?,'activity',1,?)")
        ->execute([$userId, $start, $end, $marker, $end]);
    $sessionRows = $rows($store, 'SELECT SESSION_ID FROM '
        . $storeTables['measurement_session'] . ' WHERE RAW_HASH=? AND AI_USER_ID=?',
        [$marker, $userId]);
    $assert(count($sessionRows) === 1, 'Synthetic Store session missing/ambiguous');
    $sessionId = (int)$sessionRows[0]['session_id'];
    $assert($sessionId > 0, 'Synthetic Store session ID invalid');
    $hasSegmentKey = isset($metadata[$storeTables['health_record']]['SEGMENT_KEY']);
    foreach ([['activity_duration', '120', 'sec'], ['calories_burned', '12', 'kcal'],
        ['distance', '345', 'm']] as [$code, $value, $unit]) {
        $sql = 'INSERT INTO ' . $storeTables['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 (?,?,?,?,?,NULL,' . ($hasSegmentKey ? "''," : '')
            . "'raw','vendor_api',?,?,?)";
        $store->prepare($sql)->execute([$sessionId, $userId, $code, $value,
            $unit, $start, $end, $end]);
    }
    $assert($count($ai, 'SELECT COUNT(*) FROM ' . $aiTables['user_motion']
        . ' WHERE USER_ID=? AND DATE IN (?,?)',
        [$userId, strtotime($yesterday), strtotime($today)]) === 2
        && $count($store, 'SELECT COUNT(*) FROM ' . $storeTables['health_record']
            . ' WHERE SESSION_ID=? AND AI_USER_ID=?', [$sessionId, $userId]) === 3,
        'Synthetic sport fixture original-table mismatch');

    $cate = $request('GET', $url('sport.Cate/all'), null, $token);
    $categoryList = $cate['data']['list'] ?? null;
    $categoryCount = $count($ai, 'SELECT COUNT(*) FROM ' . $aiTables['sport_cate']
        . ' WHERE STORE_ID=10001 AND IS_DELETE=0');
    $assert($cate['http'] === 200 && $cate['status'] === 200
        && $cate['elapsed_ms'] <= 15000 && is_array($categoryList)
        && count($categoryList) === $categoryCount && $categoryCount > 0,
        'Sport category response/source mismatch');
    $results['category_nonempty_count_match'] = true;

    $day = $request('POST', $url('UserMotion/userDaySteps'),
        ['date' => $today], $token);
    $dayData = $day['data']['todaySteps'] ?? [];
    $assert($day['http'] === 200 && $day['status'] === 200
        && $day['elapsed_ms'] <= 15000 && (int)($dayData['totalSteps'] ?? -1) === 2000
        && (float)($dayData['totalConsume'] ?? -1) === 60.0,
        'Daily steps response/source mismatch');
    $results['daily_nonempty_total_and_consume'] = true;

    $week = $request('POST', $url('UserMotion/userWeekSteps'),
        ['date' => $today], $token);
    $weekData = $week['data']['userStepList'] ?? [];
    $assert($week['http'] === 200 && $week['status'] === 200
        && $week['elapsed_ms'] <= 15000
        && (int)($weekData['totalSteps'] ?? -1) === 3000
        && (int)($weekData['dayTotalSteps'] ?? -1) === 2000
        && is_array($weekData['details'] ?? null)
        && count($weekData['details']) === 2,
        'Weekly steps response/source mismatch');
    $results['weekly_two_days_aggregate'] = true;

    $indoorList = $request('GET', $url('yingjiduo.Indoor/listData',
        ['type' => 1, 'date' => $today]), null, $token);
    $listData = $indoorList['data'] ?? [];
    $list = $listData['list'] ?? [];
    $assert($indoorList['http'] === 200 && $indoorList['status'] === 200
        && $indoorList['elapsed_ms'] <= 15000 && is_array($list)
        && count($list) === 1
        && (int)($list[0]['sessionId'] ?? 0) === $sessionId
        && (int)($listData['summary']['duration'] ?? -1) === 120
        && (int)($listData['summary']['calorie'] ?? -1) === 12
        && (int)($listData['summary']['distance'] ?? -1) === 345,
        'Indoor list response/source mismatch');
    $results['indoor_nonempty_summary'] = true;
    $results['list_start_time_seconds'] = is_string($list[0]['startTime'] ?? null)
        && preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/D',
            $list[0]['startTime']) === 1;
    $assert($results['list_start_time_seconds'],
        'Indoor list startTime precision differs from MySQL contract');

    $detail = $request('GET', $url('yingjiduo.Indoor/detailData',
        ['sessionId' => $sessionId]), null, $token);
    $detailData = $detail['data'] ?? [];
    $assert($detail['http'] === 200 && $detail['status'] === 200
        && $detail['elapsed_ms'] <= 15000
        && (int)($detailData['sessionId'] ?? 0) === $sessionId
        && (int)($detailData['duration'] ?? -1) === 120
        && (int)($detailData['calorie'] ?? -1) === 12
        && (int)($detailData['distance'] ?? -1) === 345,
        'Indoor detail response/source mismatch');
    $results['indoor_detail_flat_metrics'] = true;
    $results['detail_start_time_seconds'] = is_string($detailData['startTime'] ?? null)
        && preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/D',
            $detailData['startTime']) === 1;
    $assert($results['detail_start_time_seconds'],
        'Indoor detail startTime precision differs from MySQL contract');
    $results['response_types'] = [
        'category_id' => gettype($categoryList[0]['id'] ?? null),
        'day_steps' => gettype($dayData['totalSteps'] ?? null),
        'week_steps' => gettype($weekData['totalSteps'] ?? null),
        'session_id' => gettype($list[0]['sessionId'] ?? null),
        'indoor_start_time' => gettype($detailData['startTime'] ?? null),
        'indoor_duration' => gettype($detailData['duration'] ?? null),
    ];
} catch (Throwable $error) {
    $failure = get_class($error) . ':' . hash('sha256', $error->getMessage());
} finally {
    try {
        \think\facade\Cache::delete($token);
        if ($userId <= 0) {
            $ownedUsers = $rows($ai, 'SELECT USER_ID FROM ' . $aiTables['user']
                . ' WHERE NICK_NAME=?', [$marker]);
            $assert(count($ownedUsers) <= 1,
                'Synthetic user ambiguous; refusing cleanup');
            if ($ownedUsers) $userId = (int)$ownedUsers[0]['user_id'];
        }
        if ($userId > 0) {
            $ownedSessions = $rows($store, 'SELECT SESSION_ID,AI_USER_ID,RAW_HASH FROM '
                . $storeTables['measurement_session'] . ' WHERE RAW_HASH=?', [$marker]);
            $assert(count($ownedSessions) <= 1, 'Synthetic session ambiguous; refusing cleanup');
            if ($ownedSessions) {
                $assert((int)$ownedSessions[0]['ai_user_id'] === $userId,
                    'Synthetic session user mismatch; refusing cleanup');
                $sessionId = (int)$ownedSessions[0]['session_id'];
            }
            if ($sessionId > 0) {
                $metricRows = $rows($store, 'SELECT RECORD_ID,AI_USER_ID,METRIC_CODE,'
                    . 'DATA_SOURCE_TYPE,SOURCE_PLATFORM FROM '
                    . $storeTables['health_record'] . ' WHERE SESSION_ID=?', [$sessionId]);
                $assert(count($metricRows) <= 3 && $count($store,
                    'SELECT COUNT(*) FROM ' . $storeTables['measurement_session_raw']
                    . ' WHERE SESSION_ID=?', [$sessionId]) === 0,
                    'Unexpected raw or extra metrics on synthetic session; refusing cleanup');
                $seenMetricCodes = [];
                foreach ($metricRows as $row) {
                    $assert((int)$row['ai_user_id'] === $userId
                        && in_array((string)$row['metric_code'],
                            ['activity_duration', 'calories_burned', 'distance'], true)
                        && !isset($seenMetricCodes[(string)$row['metric_code']])
                        && (string)$row['data_source_type'] === 'raw'
                        && (string)$row['source_platform'] === 'vendor_api',
                        'Unexpected metric on synthetic session; refusing cleanup');
                    $seenMetricCodes[(string)$row['metric_code']] = true;
                }
                $store->beginTransaction();
                try {
                    $store->prepare('DELETE FROM ' . $storeTables['health_record']
                        . ' WHERE SESSION_ID=? AND AI_USER_ID=?')
                        ->execute([$sessionId, $userId]);
                    $store->prepare('DELETE FROM ' . $storeTables['measurement_session']
                        . ' WHERE SESSION_ID=? AND AI_USER_ID=? AND RAW_HASH=?')
                        ->execute([$sessionId, $userId, $marker]);
                    $store->commit();
                } catch (Throwable $error) {
                    $store->rollBack();
                    throw $error;
                }
            }
            $ownedMotion = $rows($ai, 'SELECT DATE,MOVEMENT_STEPS FROM '
                . $aiTables['user_motion'] . ' WHERE USER_ID=?', [$userId]);
            $assert(count($ownedMotion) <= 2,
                'Unexpected synthetic motion count; refusing cleanup');
            $expectedMotion = [(string)strtotime($yesterday) => 1000,
                (string)strtotime($today) => 2000];
            foreach ($ownedMotion as $row) {
                $dateKey = (string)$row['date'];
                $assert(isset($expectedMotion[$dateKey])
                    && (int)$row['movement_steps'] === $expectedMotion[$dateKey],
                    'Unexpected synthetic motion row; refusing cleanup');
            }
            $ai->prepare('DELETE FROM ' . $aiTables['user_motion']
                . ' WHERE USER_ID=? AND STORE_ID=10001 AND DATE IN (?,?)')
                ->execute([$userId, strtotime($yesterday), strtotime($today)]);
            $ownedStaff = $rows($ai, 'SELECT ID,USER_ID,NAME,WEIGHT FROM '
                . $aiTables['staff'] . ' WHERE USER_ID=?', [$userId]);
            $assert(count($ownedStaff) <= 1 && (!$ownedStaff
                || ((string)$ownedStaff[0]['name'] === $marker
                    && (float)$ownedStaff[0]['weight'] === 60.0)),
                'Unexpected synthetic staff row; refusing cleanup');
            $ai->prepare('DELETE FROM ' . $aiTables['staff']
                . ' WHERE USER_ID=? AND NAME=?')->execute([$userId, $marker]);
            $ai->prepare('DELETE FROM ' . $aiTables['user']
                . ' WHERE USER_ID=? AND NICK_NAME=?')->execute([$userId, $marker]);
        }
        $cleanup = ['user_zero' => $count($ai, 'SELECT COUNT(*) FROM '
                . $aiTables['user'] . ' WHERE NICK_NAME=?', [$marker]) === 0,
            'staff_zero' => $count($ai, 'SELECT COUNT(*) FROM '
                . $aiTables['staff'] . ' WHERE NAME=?', [$marker]) === 0,
            'motion_zero' => $userId <= 0 || $count($ai, 'SELECT COUNT(*) FROM '
                . $aiTables['user_motion'] . ' WHERE USER_ID=?', [$userId]) === 0,
            'session_zero' => $count($store, 'SELECT COUNT(*) FROM '
                . $storeTables['measurement_session'] . ' WHERE RAW_HASH=?', [$marker]) === 0,
            'metrics_zero' => $sessionId <= 0 || $count($store, 'SELECT COUNT(*) FROM '
                . $storeTables['health_record'] . ' WHERE SESSION_ID=?', [$sessionId]) === 0];
    } catch (Throwable $error) {
        $cleanup['error_class'] = get_class($error);
        $cleanup['error_sha256'] = hash('sha256', $error->getMessage());
    }
}
$clean = !in_array(false, $cleanup, true) && !isset($cleanup['error_class']);
echo json_encode(['suite' => 'sport-display-' . $variant, 'marker' => $marker,
    'results' => $results, 'failure' => $failure, 'cleanup' => $cleanup],
    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
exit($failure === '' && $clean ? 0 : 1);
