<?php

declare(strict_types=1);

$lane = $argv[1] ?? '';
if (!in_array($lane, ['B', 'C'], true)) exit(2);
$root = '/tmp/cdx-prepay-code-scan-20261012-' . $lane . '-store';
$marker = $lane === 'B' ? 'CDXPPREF12B01' : 'CDXPPREF12C01';
$staffUuid = $marker . '-ST';
$aiUserId = $lane === 'B' ? 46921 : 1936;
$actorId = $lane === 'B' ? 97260 : 2791;
$dialect = $lane === 'B' ? 'mysql' : 'dm';
$pid = (int)file_get_contents($root . '/private-http.pid');
if (strpos((string)file_get_contents('/proc/' . $pid . '/cmdline'), $root . '/public') === false) {
    throw new RuntimeException('Wrong private Store process');
}
foreach (explode("\0", (string)file_get_contents('/proc/' . $pid . '/environ')) as $pair) {
    $parts = explode('=', $pair, 2);
    if (count($parts) === 2 && strpos($parts[0], 'POC_') === 0) putenv($pair);
}
if (getenv('POC_DIALECT') !== $dialect) throw new RuntimeException('Wrong DB dialect');
$boundary = json_decode((string)file_get_contents('http://127.0.0.1:'
    . ($lane === 'B' ? 19131 : 19132) . '/__poc_boundary'), true);
if (empty($boundary['external_stubs']) || empty($boundary['redis_isolated'])
    || !empty($boundary['real_queue'])) throw new RuntimeException('External boundary unsafe');
$config = require $root . '/application/database.php';
$connect = static function (array $c) use ($dialect): PDO {
    $dsn = $dialect === 'dm'
        ? 'dm:host=' . $c['hostname'] . ';port=' . $c['hostport'] . ';schema=' . $c['database']
        : 'mysql:host=' . $c['hostname'] . ';port=' . ($c['hostport'] ?? 3306)
            . ';dbname=' . $c['database'] . ';charset=utf8mb4';
    return new PDO($dsn, $c['username'], $c['password'],
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
};
$store = $connect($config);
$ai = $connect($config['ai_zhct']);
$table = static function (string $name, bool $isAi = false) use ($dialect): string {
    $prefix = $isAi ? 'yoshop_' : 'ydy_';
    return $dialect === 'dm' ? strtoupper($prefix . $name) : $prefix . $name;
};
$all = static function (PDO $db, string $sql, array $params = []): array {
    $stmt = $db->prepare($sql);
    $stmt->execute($params);
    return array_map(static function (array $row): array {
        return array_change_key_case($row, CASE_LOWER);
    }, $stmt->fetchAll(PDO::FETCH_ASSOC));
};
$actorRows = $all($store, 'SELECT ID,UUID,ACCOUNT,NAME,TYPE,STAFF_UUID FROM '
    . $table('user') . ' WHERE ID=?', [$actorId]);
$actor = count($actorRows) === 1 ? $actorRows[0] : [];
$staffRows = $all($store, 'SELECT UUID,AI_USER_ID,JOB_STATUS,IS_SHOW FROM '
    . $table('staff') . ' WHERE UUID=?', [$staffUuid]);
$staff = count($staffRows) === 1 ? $staffRows[0] : [];
$userRows = $all($ai, 'SELECT USER_ID,STORE_ID,BALANCE,GIFT_BALANCE,IS_DELETE FROM '
    . $table('user', true) . ' WHERE USER_ID=?', [$aiUserId]);
$user = count($userRows) === 1 ? $userRows[0] : [];
$rechargeBefore = $all($ai, 'SELECT ORDER_ID FROM ' . $table('recharge_order', true)
    . ' WHERE USER_ID=? AND STORE_ID=?', [$aiUserId, 10001]);
$logsBefore = $all($ai, 'SELECT LOG_ID FROM ' . $table('user_balance_log', true)
    . ' WHERE USER_ID=? AND STORE_ID=?', [$aiUserId, 10001]);
if (!$actor || !$staff || !$user
    || strpos((string)$actor['account'], 'CDX') !== 0
    || (int)$actor['type'] !== 0
    || (int)$staff['ai_user_id'] !== $aiUserId
    || (int)$staff['job_status'] !== 1 || (int)$staff['is_show'] !== 1
    || (int)$user['store_id'] !== 10001 || (int)$user['is_delete'] !== 0
    || bccomp((string)$user['balance'], '0.00', 2) !== 0
    || $rechargeBefore || $logsBefore) {
    throw new RuntimeException('Only new owned zero-cash 10001 staff/user may recharge');
}
if (getenv('POC_DRY_RUN') === '1') {
    echo json_encode(['lane' => $lane, 'marker' => $marker,
        'ai_user_id' => $aiUserId, 'cash_before' => '0.00',
        'recharge_rows_before' => 0, 'cash_logs_before' => 0,
        'actor_synthetic_type0' => true, 'external_method' => 'cash-offline',
        'HTTP' => 0, 'DML' => 0]) . PHP_EOL;
    exit(0);
}
$attemptPath = $root . '/fixture10001-recharge-attempt.json';
$rawPath = $root . '/fixture10001-recharge-response.raw';
$receiptPath = $root . '/fixture10001-recharge-receipt.json';
if (is_file($attemptPath) || is_file($rawPath) || is_file($receiptPath)) {
    throw new RuntimeException('Owned recharge already attempted');
}
require_once $root . '/application/base/Security.php';
$token = \app\base\Security::encrypt(implode("\t", [
    (string)$actor['id'], (string)$actor['uuid'], (string)$actor['name'],
    '0', '', (string)$actor['staff_uuid'], (string)$actor['name'],
]));
$form = ['department_uuid' => '', 'staff_uuids' => $staffUuid,
    'money' => '0.05', 'pay_method' => 'cash', 'note' => $marker];
$body = http_build_query($form, '', '&', PHP_QUERY_RFC3986);
$attempt = ['lane' => $lane, 'marker' => $marker,
    'method' => 'POST', 'path' => '/p/rechargeOrder/add',
    'body_sha256' => hash('sha256', $body),
    'token_sha256' => hash('sha256', $token),
    'before_wallet_cash' => '0.00', 'before_recharge_rows' => 0,
    'before_cash_log_rows' => 0, 'at' => date('c')];
$handle = fopen($attemptPath, 'xb');
if (!$handle) throw new RuntimeException('Could not lock recharge attempt');
fwrite($handle, json_encode($attempt, JSON_UNESCAPED_SLASHES));
fclose($handle);
chmod($attemptPath, 0600);
$context = stream_context_create(['http' => [
    'method' => 'POST', 'ignore_errors' => true, 'timeout' => 45,
    'header' => "Content-Type: application/x-www-form-urlencoded\r\n"
        . 'token: ' . $token . "\r\n",
    'content' => $body,
]]);
$wire = file_get_contents('http://127.0.0.1:' . ($lane === 'B' ? 19131 : 19132)
    . '/p/rechargeOrder/add', false, $context);
$raw = is_string($wire) ? $wire : '';
$handle = fopen($rawPath, 'xb');
if (!$handle) throw new RuntimeException('Cannot preserve recharge raw response');
fwrite($handle, $raw);
fclose($handle);
chmod($rawPath, 0600);
$http = 0;
foreach (($http_response_header ?? []) as $header) {
    if (preg_match('/^HTTP\/\S+ (\d{3})/', $header, $match)) $http = (int)$match[1];
}
$response = json_decode($raw, true);
$userAfterRows = $all($ai, 'SELECT USER_ID,STORE_ID,BALANCE,GIFT_BALANCE,IS_DELETE FROM '
    . $table('user', true) . ' WHERE USER_ID=?', [$aiUserId]);
$after = count($userAfterRows) === 1 ? $userAfterRows[0] : [];
$rechargeAfter = $all($ai, 'SELECT ORDER_ID,ORDER_NO,USER_ID,STORE_ID,PAY_STATUS,'
    . 'PAY_PRICE,GIFT_MONEY,ACTUAL_MONEY,REFUNDABLE_MONEY FROM '
    . $table('recharge_order', true) . ' WHERE USER_ID=? AND STORE_ID=?',
    [$aiUserId, 10001]);
$logsAfter = $all($ai, 'SELECT LOG_ID,MONEY FROM '
    . $table('user_balance_log', true)
    . ' WHERE USER_ID=? AND STORE_ID=?', [$aiUserId, 10001]);
$order = count($rechargeAfter) === 1 ? $rechargeAfter[0] : [];
$receipt = ['lane' => $lane, 'marker' => $marker,
    'http_status' => $http, 'response_json' => is_array($response),
    'response_code' => $response['code'] ?? null,
    'response_keys' => is_array($response) ? array_keys($response) : [],
    'response_body_sha256' => hash('sha256', $raw),
    'response_raw_file' => basename($rawPath),
    'ai_user_id' => $aiUserId,
    'wallet_cash_before' => '0.00',
    'wallet_cash_after' => (string)($after['balance'] ?? ''),
    'wallet_gift_after' => (string)($after['gift_balance'] ?? ''),
    'recharge_rows_before' => 0,
    'recharge_rows_after' => count($rechargeAfter),
    'recharge_id' => (int)($order['order_id'] ?? 0),
    'recharge_pay_status' => (int)($order['pay_status'] ?? -1),
    'recharge_pay_price' => (string)($order['pay_price'] ?? ''),
    'recharge_gift_money' => (string)($order['gift_money'] ?? ''),
    'recharge_refundable_money' => (string)($order['refundable_money'] ?? ''),
    'cash_logs_before' => 0,
    'cash_logs_after' => count($logsAfter),
    'cash_log_money' => count($logsAfter) === 1 ? (string)$logsAfter[0]['money'] : ''];
$receipt['passed'] = $http === 200 && $receipt['response_json']
    && (int)$receipt['response_code'] === 0
    && bccomp($receipt['wallet_cash_after'], '0.05', 2) === 0
    && $receipt['recharge_rows_after'] === 1
    && $receipt['recharge_id'] > 0
    && $receipt['recharge_pay_status'] === 20
    && bccomp($receipt['recharge_pay_price'], '0.05', 2) === 0
    && bccomp($receipt['recharge_refundable_money'], '0.05', 2) === 0
    && $receipt['cash_logs_after'] === 1
    && bccomp($receipt['cash_log_money'], '0.05', 2) === 0;
file_put_contents($receiptPath, json_encode($receipt,
    JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), LOCK_EX);
chmod($receiptPath, 0600);
echo json_encode($receipt, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
exit($receipt['passed'] ? 0 : 1);
