<?php
declare(strict_types=1);

// Read-only, default-deny preview check. No token, cache mutation, or DML.
if (getenv('CDX_READ8_EXECUTE') !== 'APPROVED_PREVIEW_READONLY_V1') {
    echo json_encode(['status' => 'default_deny', 'http' => 0, 'dml' => 0]), PHP_EOL;
    exit(78);
}
$target = (string)getenv('CDX_READ8_TARGET');
if (!in_array($target, ['A', 'B', 'C'], true)) {
    throw new RuntimeException('Target must be A, B, or C');
}
$expectedSha = (string)getenv('CDX_READ8_SHA');
if (strlen($expectedSha) !== 64 || !hash_equals($expectedSha, (string)hash_file('sha256', __FILE__))) {
    throw new RuntimeException('Script SHA mismatch');
}

putenv('CDX_READ2_TARGET=' . $target);
putenv('CDX_READ2_SCHEMA_PREFLIGHT=1');
$preflight = $target === 'C'
    ? '/tmp/zhct-ai-read2-VgKO4CDY/read2_schema_preflight.php'
    : __DIR__ . '/../parallel-ai-next-read-safe4/read2_schema_preflight.php';
require $preflight;

$ai->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$table = $dialect === 'dm' ? 'YOSHOP_RECHARGE_GIFT_RULE' : 'yoshop_recharge_gift_rule';
$before = $ai->query('SELECT COUNT(*) FROM ' . $table . ' WHERE STORE_ID=10001')->fetchColumn();
$valid = $ai->query('SELECT COUNT(*) FROM ' . $table
    . ' WHERE STORE_ID=10001 AND STATUS=1 AND IS_DELETE=0')->fetchColumn();
$rules = $ai->query('SELECT RULE_ID,MIN_MONEY,GIFT_MONEY,PAY_METHODS FROM ' . $table
    . ' WHERE STORE_ID=10001 AND STATUS=1 AND IS_DELETE=0')->fetchAll(PDO::FETCH_ASSOC);
$onlineRules = array_values(array_filter($rules, static function (array $row): bool {
    $methods = json_decode((string)$row['pay_methods'], true);
    return is_array($methods) && in_array('online_scan', $methods, true)
        && preg_match('/^\d+(?:\.\d{1,2})?$/', (string)$row['min_money']) === 1
        && preg_match('/^\d+(?:\.\d{1,2})?$/', (string)$row['gift_money']) === 1;
}));
usort($onlineRules, static function (array $left, array $right): int {
    return ((float)$right['min_money'] <=> (float)$left['min_money'])
        ?: ((float)$right['gift_money'] <=> (float)$left['gift_money'])
        ?: ((int)$right['rule_id'] <=> (int)$left['rule_id']);
});
$port = ['A' => 18105, 'B' => 18101, 'C' => 18102][$target];
$cases = [
    ['money' => '10.01', 'method' => 'wechat', 'expect' => 200],
    ['money' => '0.00', 'method' => 'wechat', 'expect' => 500],
    ['money' => '10.001', 'method' => 'wechat', 'expect' => 500],
];
if ($onlineRules && (float)$onlineRules[0]['min_money'] > 0
    && (float)$onlineRules[0]['min_money'] <= 1000) {
    $cases[] = [
        'money' => number_format((float)$onlineRules[0]['min_money'], 2, '.', ''),
        'method' => 'wechat', 'expect' => 200, 'matched_rule' => $onlineRules[0],
    ];
}
$results = [];
foreach ($cases as $case) {
    $query = http_build_query(['storeId' => 10001, 'money' => $case['money'], 'method' => $case['method']]);
    $context = stream_context_create(['http' => [
        'method' => 'GET', 'timeout' => 15, 'ignore_errors' => true,
        'header' => "platform: MP-WEIXIN\r\n",
    ]]);
    $raw = file_get_contents('http://127.0.0.1:' . $port
        . '/api/Recharge/preview?' . $query, false, $context);
    $http = isset($http_response_header[0]) && preg_match('/HTTP\/\S+\s+(\d+)/', $http_response_header[0], $match)
        ? (int)$match[1] : 0;
    $body = is_string($raw) ? json_decode($raw, true) : null;
    if ($http !== 200 || !is_array($body) || (int)($body['status'] ?? -1) !== $case['expect']) {
        throw new RuntimeException('HTTP/business status mismatch for one preview case');
    }
    $data = $body['data'] ?? null;
    if ($case['expect'] === 200) {
        if (!is_array($data) || (string)($data['pay_price'] ?? '') !== $case['money']
            || !isset($data['gift_money'], $data['actual_money'], $data['refundable_money'], $data['rule_id'])
            || !is_int($data['rule_id'])) {
            throw new RuntimeException('Preview output contract mismatch');
        }
        if (isset($case['matched_rule'])) {
            $rule = $case['matched_rule'];
            $expectedActual = number_format((float)$case['money'] + (float)$rule['gift_money'], 2, '.', '');
            if ($data['rule_id'] !== (int)$rule['rule_id']
                || $data['gift_money'] !== number_format((float)$rule['gift_money'], 2, '.', '')
                || $data['actual_money'] !== $expectedActual
                || $data['refundable_money'] !== '0.00') {
                throw new RuntimeException('Matched gift rule differs from source row');
            }
        }
    }
    $results[] = [
        'input_class' => isset($case['matched_rule']) ? 'matched_active_rule'
            : ($case['expect'] === 200 ? 'positive_unmatched_rule' : 'invalid_boundary'),
        'http' => $http, 'business_status' => (int)$body['status'],
        'data_type_map' => is_array($data) ? array_map('gettype', $data) : gettype($data),
        'amounts' => $case['expect'] === 200 ? array_intersect_key($data, array_fill_keys([
            'pay_price', 'gift_money', 'actual_money', 'refundable_money', 'rule_id'], true)) : null,
    ];
}
$after = $ai->query('SELECT COUNT(*) FROM ' . $table . ' WHERE STORE_ID=10001')->fetchColumn();
if ((int)$before !== (int)$after) {
    throw new RuntimeException('Rule count changed after read-only preview');
}
echo json_encode(['status' => 'preview_readonly_pass', 'target' => $target,
    'dialect' => $dialect, 'rule_count' => (int)$before,
    'active_rule_count' => (int)$valid, 'cases' => $results,
    'rule_count_unchanged' => true, 'dml' => 0], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
