<?php

declare(strict_types=1);

$root = getenv('POC_APP_ROOT');
$dialect = getenv('POC_DIALECT');
$mainHost = getenv('POC_HOST');
$mainPort = (int)getenv('POC_PORT');
$mainSchema = getenv('POC_SCHEMA');
$mainUser = getenv('POC_USER');
$mainPassword = getenv('POC_PASSWORD');
$storeHost = getenv('POC_STORE_HOST');
$storePort = (int)getenv('POC_STORE_PORT');
$storeSchema = getenv('POC_STORE_SCHEMA');
$storeUser = getenv('POC_STORE_USER');
$storePassword = getenv('POC_STORE_PASSWORD');
if (!$root || !in_array($dialect, ['mysql', 'dm'], true) || !$mainHost || $mainPort < 1 || !$mainSchema || !$mainUser || !$mainPassword
    || !$storeHost || $storePort < 1 || !$storeSchema || !$storeUser || !$storePassword) exit(2);
require $root . '/vendor/autoload.php';
if (!function_exists('app_name')) {
    function app_name(): string { return 'api'; }
}
if (!function_exists('getStoreId')) {
    function getStoreId(): int { return (int)($GLOBALS['POC_SYNTHETIC_STORE_ID'] ?? 0); }
}
set_exception_handler(static function (\Throwable $e): void {
    fwrite(STDERR, 'AI_ACCOUNT_PROBE_FAIL ' . get_class($e) . ': ' . substr($e->getMessage(), 0, 250) . PHP_EOL);
    exit(1);
});

$type = $dialect === 'dm' ? \app\common\database\Dm::class : 'mysql';
\think\facade\Db::setConfig([
    'default' => 'mysql',
    'connections' => [
        'mysql' => [
            'type' => $type, 'hostname' => $mainHost, 'hostport' => $mainPort,
            'database' => $mainSchema, 'username' => $mainUser, 'password' => $mainPassword,
            'prefix' => 'yoshop_', 'debug' => false,
        ],
        'mysql_zhct' => [
            'type' => $type, 'hostname' => $storeHost, 'hostport' => $storePort,
            'database' => $storeSchema, 'username' => $storeUser, 'password' => $storePassword,
            'prefix' => 'ydy_', 'debug' => false,
        ],
    ],
]);
$db = \think\facade\Db::connect('mysql');
$storeId = 900000000 + random_int(10000, 99999);
$GLOBALS['POC_SYNTHETIC_STORE_ID'] = $storeId;
$orderId = random_int(800000000, 899999999);
$orderNo = 'CDX' . strtoupper(bin2hex(random_bytes(6)));
if ((int)$db->name('user')->where('store_id', $storeId)->count() !== 0) throw new RuntimeException('Synthetic store ID already exists');
echo json_encode(['dialect' => $dialect, 'status' => 'starting', 'store_id' => $storeId, 'order_no' => $orderNo]) . PHP_EOL;

$started = false;
try {
    $db->startTrans();
    $started = true;
    $userId = (int)$db->name('user')->insertGetId([
        'store_id' => $storeId, 'mobile' => '', 'nick_name' => 'CODEXDM8_AI_ACCOUNT',
        'balance' => '90.00', 'gift_balance' => '20.00', 'is_delete' => 0,
        'create_time' => time(),
    ]);
    if ($userId <= 0) throw new RuntimeException('Synthetic AI user insert failed');
    $params = [
        'user_id' => $userId, 'order_id' => $orderId, 'order_no' => $orderNo,
        'amount' => '100.00', 'store_id' => $storeId,
        'deduction_order' => ['subsidy', 'cash', 'gift'],
    ];
    $service = new \app\common\service\account\AccountSettlementService();
    $first = $service->deduct($params);
    $repeat = $service->deduct($params);
    $account = $db->name('user')->where('user_id', $userId)->field('balance,gift_balance')->find();
    $cashLogs = (int)$db->name('user_balance_log')->where('user_id', $userId)->where('order_id', $orderId)->count();
    $giftLogs = (int)$db->name('user_gift_log')->where('user_id', $userId)->where('biz_order_no', $orderNo)->count();
    if ($first['cash'] !== '90.00' || $first['gift'] !== '10.00'
        || (int)$first['settlement_id'] !== (int)$repeat['settlement_id']
        || number_format((float)$account['balance'], 2, '.', '') !== '0.00'
        || number_format((float)$account['gift_balance'], 2, '.', '') !== '10.00'
        || $cashLogs !== 1 || $giftLogs !== 1) {
        throw new RuntimeException('AI account cash/gift deduction or idempotency mismatch');
    }

    $oneCardUserId = (int)$db->name('user')->insertGetId([
        'store_id' => $storeId, 'mobile' => '', 'nick_name' => 'CODEXDM8_AI_ONECARD',
        'balance' => '20.00', 'subsidy_balance' => '3.00', 'gift_balance' => '7.00',
        'is_delete' => 0, 'create_time' => time(),
    ]);
    $oneCardOrderNo = 'OCS' . strtoupper(bin2hex(random_bytes(6)));
    $refundNo = 'OCR' . strtoupper(bin2hex(random_bytes(6)));
    $oneCardParams = [
        'user_id' => $oneCardUserId, 'order_id' => $orderId + 1,
        'order_no' => $oneCardOrderNo, 'store_id' => $storeId,
        'one_card_trade_id' => 880001, 'cash_amount' => '7.00',
        'subsidy_amount' => '3.00', 'cash_balance_after' => '13.00',
        'subsidy_balance_after' => '0.00',
    ];
    $oneCardConsume = $service->recordOneCardConsume($oneCardParams);
    $oneCardRepeat = $service->recordOneCardConsume($oneCardParams);
    $oneCardRefundParams = [
        'user_id' => $oneCardUserId, 'order_id' => $orderId + 1,
        'order_no' => $oneCardOrderNo, 'refund_no' => $refundNo,
        'store_id' => $storeId, 'one_card_trade_id' => 880002,
        'amount' => '3.00', 'cash_amount' => '2.00', 'subsidy_amount' => '1.00',
        'cash_balance_after' => '15.00', 'subsidy_balance_after' => '1.00',
    ];
    $oneCardRefund = $service->recordOneCardRefund($oneCardRefundParams);
    $oneCardRefundRepeat = $service->recordOneCardRefund($oneCardRefundParams);
    $oneCardAccount = $db->name('user')->where('user_id', $oneCardUserId)->field('balance,subsidy_balance,gift_balance')->find();
    if ((int)$oneCardConsume['settlement_id'] !== (int)$oneCardRepeat['settlement_id']
        || (int)$oneCardRefund['settlement_id'] !== (int)$oneCardRefundRepeat['settlement_id']
        || number_format((float)$oneCardAccount['balance'], 2, '.', '') !== '15.00'
        || number_format((float)$oneCardAccount['subsidy_balance'], 2, '.', '') !== '1.00'
        || number_format((float)$oneCardAccount['gift_balance'], 2, '.', '') !== '7.00'
        || (int)$db->name('user_balance_log')->where('user_id', $oneCardUserId)->count() !== 2
        || (int)$db->name('user_subsidy_log')->where('user_id', $oneCardUserId)->count() !== 2) {
        throw new RuntimeException('AI one-card consume/refund or idempotency mismatch');
    }
    $db->rollback();
    $started = false;
    $dsn = $dialect === 'dm' ? "dm:host=$mainHost;port=$mainPort;schema=$mainSchema" : "mysql:host=$mainHost;port=$mainPort;dbname=$mainSchema;charset=utf8mb4";
    $fresh = new PDO($dsn, $mainUser, $mainPassword, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
    foreach (['user', 'account_settlement', 'user_balance_log', 'user_subsidy_log', 'user_gift_log'] as $table) {
        $name = ($dialect === 'dm' ? 'YOSHOP_' . strtoupper($table) : 'yoshop_' . $table);
        $stmt = $fresh->prepare('SELECT COUNT(*) FROM ' . $name . ' WHERE STORE_ID=?');
        $stmt->execute([$storeId]);
        if ((int)$stmt->fetchColumn() !== 0) throw new RuntimeException('Rollback left synthetic rows in ' . $table);
    }
    echo json_encode(['dialect' => $dialect, 'status' => 'passed', 'store_id' => $storeId,
        'settlement_id' => (int)$first['settlement_id'], 'cash' => '90.00', 'gift' => '10.00',
        'duplicate_idempotent' => true, 'onecard_consume_refund_idempotent' => true, 'rollback_clean' => true]) . PHP_EOL;
} finally {
    if ($started) $db->rollback();
}
