<?php

declare(strict_types=1);

$root = getenv('POC_APP_ROOT');
$dialect = getenv('POC_DIALECT');
$host = getenv('POC_HOST');
$port = (int)getenv('POC_PORT');
$schema = getenv('POC_SCHEMA');
$user = getenv('POC_USER');
$password = getenv('POC_PASSWORD');
if (!$root || !in_array($dialect, ['mysql', 'dm'], true) || !$host || $port < 1 || !$schema || !$user || !$password) exit(2);
define('APP_PATH', $root . '/application/');
require $root . '/thinkphp/base.php';
require $root . '/application/common.php';
set_exception_handler(static function (\Throwable $e): void {
    fwrite(STDERR, 'MOCATCH_PROBE_FAIL ' . get_class($e) . ': ' . substr($e->getMessage(), 0, 250) . PHP_EOL);
    exit(1);
});
if (!function_exists('config')) {
    function config($name = '', $value = null, $range = '')
    {
        return $value === null ? \think\Config::get($name) : \think\Config::set($name, $value, $range);
    }
}

$config = [
    'type' => $dialect === 'dm' ? \app\cores\database\Dm::class : 'mysql',
    'hostname' => $host,
    'hostport' => $port,
    'database' => $schema,
    'username' => $user,
    'password' => $password,
    'prefix' => 'yoshop_',
    'debug' => false,
    'resultset_type' => 'array',
    'fields_strict' => true,
    'auto_timestamp' => false,
];
$config['ai_zhct'] = $config;
\think\Config::set($config, 'database');
\think\Db::clear();
$db = get_ai_db();
$storeId = (int)getStoreId();
$marker = 'CODEXDM8_MOCATCH_' . strtoupper(bin2hex(random_bytes(4)));
echo json_encode(['dialect' => $dialect, 'status' => 'starting', 'marker' => $marker]) . PHP_EOL;

$outerStarted = false;
try {
    $db->startTrans();
    $outerStarted = true;
    $userId = (int)$db->name('user')->insertGetId([
        'store_id' => $storeId,
        'mobile' => '',
        'nick_name' => $marker,
        'balance' => '0.00',
        'is_delete' => 0,
        'create_time' => time(),
    ]);
    $staffId = (int)$db->name('staff')->insertGetId([
        'user_id' => $userId,
        'store_id' => $storeId,
        'name' => $marker,
        'height' => '175.00',
        'weight' => '68.00',
        'is_delete' => 0,
    ]);
    if ($userId <= 0 || $staffId <= 0) throw new RuntimeException('Synthetic Mocatch fixture insert failed');
    $service = new \app\api\service\MocatchWeightSyncService($db);
    $staff = ['ai_user_id' => $userId];
    $measuredAt = date('Y-m-d H:i:s');
    $first = $service->sync($staff, ['Weight' => '70.5', 'Height' => '175', 'BMI' => '23.02'], $measuredAt);
    $second = $service->sync($staff, ['Weight' => '71', 'Height' => '175', 'BMI' => '23.18'], $measuredAt);
    if (!$first['success'] || !$second['success'] || $first['weight_action'] !== 'inserted'
        || $second['weight_action'] !== 'updated' || !$first['score_added'] || $second['score_added']) {
        throw new RuntimeException('Mocatch insert/update/day-score behavior mismatch: ' . json_encode([$first, $second]));
    }
    $weight = $db->name('user_weight')->where('user_id', $userId)->where('store_id', $storeId)->find();
    $staffRow = $db->name('staff')->where('id', $staffId)->find();
    if ((int)$db->name('user_weight')->where('user_id', $userId)->where('store_id', $storeId)->count() !== 1
        || (int)$db->name('user_score_log')->where('user_id', $userId)->where('store_id', $storeId)->count() !== 1
        || (int)$db->name('user_score')->where('user_id', $userId)->where('store_id', $storeId)->count() !== 1
        || number_format((float)$weight['weight'], 1, '.', '') !== '71.0'
        || number_format((float)$staffRow['weight'], 1, '.', '') !== '71.0') {
        throw new RuntimeException('Mocatch weight/score/staff readback mismatch');
    }
    $db->rollback();
    $outerStarted = false;
    $dsn = $dialect === 'dm' ? "dm:host=$host;port=$port;schema=$schema" : "mysql:host=$host;port=$port;dbname=$schema;charset=utf8mb4";
    $fresh = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
    foreach (['user', 'staff', 'user_weight', 'user_score_log', 'user_score'] as $table) {
        $name = ($dialect === 'dm' ? 'YOSHOP_' . strtoupper($table) : 'yoshop_' . $table);
        $stmt = $fresh->prepare('SELECT COUNT(*) FROM ' . $name . ' WHERE USER_ID=?');
        $stmt->execute([$userId]);
        if ((int)$stmt->fetchColumn() !== 0) throw new RuntimeException('Rollback left synthetic rows in ' . $table);
    }
    echo json_encode(['dialect' => $dialect, 'status' => 'passed', 'marker' => $marker,
        'first_action' => 'inserted', 'second_action' => 'updated', 'daily_score_once' => true,
        'staff_weight_readback' => '71.0', 'rollback_clean' => true]) . PHP_EOL;
} finally {
    if ($outerStarted) $db->rollback();
}
