<?php
declare(strict_types=1);

// One owned, non-payment meal order. No payment, refund, queue, device, or cron call.
$lane = (string)($argv[1] ?? '');
$mode = (string)($argv[2] ?? '');
if (!in_array($lane, ['B', 'C'], true)
    || !in_array($mode, ['--run', '--audit'], true)
    || ($mode === '--run'
        && (string)getenv('CDX_MEAL_WIDE_RUN') !== 'ONE_NONPAYMENT_ORDER_V1')) {
    fwrite(STDERR, "DENIED: fixed lane/mode/guard required\n");
    exit(78);
}
$root = $lane === 'B' ? '/tmp/zhct-http-store-mysql.dQTTBP'
    : '/tmp/zhct-dm-poc-20260928.fcpiiN/store';
$base = $lane === 'B' ? 'http://127.0.0.1:18082' : 'http://127.0.0.1:18083';
$marker = $lane === 'B' ? 'CDXWIDEB1009' : 'CDXWIDEC1009';
$high = '9007199254740993';
$table = $lane === 'B' ? 'ydy_' : 'YDY_';
$result = ['lane' => $lane, 'mode' => $mode, 'marker' => $marker,
    'expected' => $high, 'cleaned' => false];
$committed = false;
$granted = false;
$source = null;
$orderId = 0;
$db = null;
try {
    $body = @file_get_contents($base . '/__poc_boundary', false,
        stream_context_create(['http' => ['timeout' => 4]]));
    $boundary = is_string($body) ? json_decode($body, true) : null;
    if (!is_array($boundary) || empty($boundary['external_stubs'])
        || empty($boundary['redis_isolated']) || !empty($boundary['real_queue'])) {
        throw new RuntimeException('Isolated HTTP boundary unavailable');
    }
    $config = require $root . '/application/database.php';
    if (($config['database'] ?? '') !== ($lane === 'B' ? 'zhct' : 'ZHCT_APP')
        || ($config['prefix'] ?? '') !== 'ydy_') {
        throw new RuntimeException('Unexpected Store database');
    }
    if ($lane === 'B') {
        $local = require '/workspace/zhct/zhctproject/store/application/config/local/database.php';
        foreach (['hostname', 'database', 'username', 'password'] as $key) {
            if (($local[$key] ?? null) !== ($config[$key] ?? null)) {
                throw new RuntimeException('B is not code-local development database');
            }
        }
    } elseif (($config['hostname'] ?? '') !== '127.0.0.1'
        || (int)($config['hostport'] ?? 0) !== 5237) {
        throw new RuntimeException('C is not the isolated Store DM instance');
    }
    $dsn = $lane === 'B'
        ? 'mysql:host=' . $config['hostname'] . ';port=' . ($config['hostport'] ?? 3306)
            . ';dbname=' . $config['database'] . ';charset=utf8'
        : 'dm:host=' . $config['hostname'] . ';port=' . $config['hostport']
            . ';schema=' . $config['database'];
    $db = new PDO($dsn, $config['username'], $config['password'], [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_CASE => PDO::CASE_LOWER,
    ]);
    $one = static function (PDO $pdo, string $sql, array $params = []): array {
        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        return array_change_key_case($stmt->fetch(PDO::FETCH_ASSOC) ?: [], CASE_LOWER);
    };
    $count = static function (PDO $pdo, string $sql, array $params = []) use ($one): int {
        $row = $one($pdo, $sql, $params);
        return (int)($row['n'] ?? -1);
    };
    $findSource = static function (PDO $pdo) use ($table): array {
        $stmt = $pdo->query('SELECT u.ID AS USER_ID,u.TYPE AS USER_TYPE,u.ACCOUNT,'
            . 'u.UUID AS USER_UUID,m.ID AS ORDER_ID,m.RESTAURANT_ID,m.MSGID'
            . ' FROM ' . $table . 'user u JOIN ' . $table . 'meal_order m'
            . ' ON m.USER_ID=u.ID AND m.MSGID=u.ACCOUNT'
            . " WHERE u.ACCOUNT LIKE 'CDXPAY%' AND u.UUID LIKE 'CDXUSER-%'"
            . ' AND m.IS_DELETE=0 AND m.RESTAURANT_ID>0 ORDER BY m.ID');
        foreach ($stmt->fetchAll() as $row) {
            $row = array_change_key_case($row, CASE_LOWER);
            if (preg_match('/^CDXPAY[A-F0-9]{8}$/D', (string)$row['account'])
                && (string)$row['msgid'] === (string)$row['account']) return $row;
        }
        throw new RuntimeException('No synthetic source user/order');
    };
    $source = $findSource($db);
    $result['source_user_id'] = (int)$source['user_id'];
    $result['source_type_before'] = (int)$source['user_type'];
    if ((int)$source['user_type'] !== 1) {
        throw new RuntimeException('Synthetic source type changed; no type mutation allowed');
    }
    $ownCount = $count($db, 'SELECT COUNT(*) AS N FROM ' . $table
        . 'meal_order WHERE ORDER_NO=? OR MSGID=?', [$marker, $marker]);
    if ($mode === '--audit') {
        $result['own_order_count'] = $ownCount;
        $result['source_type_after'] = (int)$source['user_type'];
        $result['cleaned'] = $ownCount === 0 && (int)$source['user_type'] === 1;
        echo json_encode($result, JSON_UNESCAPED_SLASHES), PHP_EOL;
        exit($result['cleaned'] ? 0 : 1);
    }
    if ($ownCount !== 0) throw new RuntimeException('Own marker not empty');
    $readCast = $lane === 'B'
        ? 'CAST(ACCOUNT_SETTLEMENT_ID AS CHAR(40))'
        : 'CAST(ACCOUNT_SETTLEMENT_ID AS VARCHAR(40))';
    $constantCast = $lane === 'B'
        ? "SELECT CAST(CAST('9007199254740993' AS UNSIGNED) AS CHAR(40)) AS V"
        : "SELECT CAST(CAST('9007199254740993' AS DECIMAL(20,0)) AS VARCHAR(40)) AS V";
    $probe = $one($db, $constantCast);
    if ((string)($probe['v'] ?? '') !== $high) {
        throw new RuntimeException('SQL-side text projection not exact');
    }
    // Source=virtual, pay=pending, order=completed, print=not requested:
    // no ordinary unpaid/printing/settlement queue candidate.
    $fields = [
        'ORDER_NO' => $marker, 'MSGID' => $marker,
        'USER_ID' => (int)$source['user_id'],
        'RESTAURANT_ID' => (int)$source['restaurant_id'],
        'USER_NAME' => $marker, 'USER_MOBILE' => '',
        'SOURCE' => 3, 'PAY_STATUS' => 10, 'ORDER_STATUS' => 30,
        'PRINT_STATUS' => 0, 'IS_DELETE' => 0,
        'ACCOUNT_SETTLEMENT_ID' => $high,
        'TOTAL_PRICE' => '0.00', 'ORDER_PRICE' => '0.00',
        'ORI_TOTAL_PRICE' => '0.00', 'PAY_PRICE' => '0.00',
        'CREATE_TIME' => '2099-01-01 00:00:00',
        'UPDATE_TIME' => '2099-01-01 00:00:00',
        'BIND_TIME' => '2099-01-01 00:00:00',
        'MEAL_DATE' => '2099-01-01', 'MEAL_TIMES' => 4,
    ];
    $db->beginTransaction();
    $insert = $db->prepare('INSERT INTO ' . $table . 'meal_order ('
        . implode(',', array_keys($fields)) . ') VALUES ('
        . implode(',', array_fill(0, count($fields), '?')) . ')');
    foreach (array_values($fields) as $index => $value) {
        $insert->bindValue($index + 1, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
    }
    $insert->execute();
    if ($insert->rowCount() !== 1) throw new RuntimeException('Expected one own order insert');
    $new = $one($db, 'SELECT ID,USER_ID,RESTAURANT_ID,ORDER_NO,MSGID,'
        . $readCast . ' AS EXACT_ID,PAY_STATUS,PRINT_STATUS,IS_DELETE'
        . ' FROM ' . $table . 'meal_order WHERE ORDER_NO=? AND MSGID=?',
        [$marker, $marker]);
    $orderId = (int)($new['id'] ?? 0);
    if ($orderId <= 0 || (int)$new['user_id'] !== (int)$source['user_id']
        || (int)$new['restaurant_id'] !== (int)$source['restaurant_id']
        || (string)$new['exact_id'] !== $high
        || (int)$new['pay_status'] !== 10 || (int)$new['print_status'] !== 0
        || (int)$new['is_delete'] !== 0) {
        throw new RuntimeException('Own order SQL-side text readback mismatch');
    }
    $grant = $db->prepare('UPDATE ' . $table . 'user SET TYPE=0'
        . ' WHERE ID=? AND UUID=? AND ACCOUNT=? AND TYPE=1');
    $grant->execute([(int)$source['user_id'], (string)$source['user_uuid'],
        (string)$source['account']]);
    if ($grant->rowCount() !== 1) throw new RuntimeException('Synthetic admin grant failed');
    $granted = true;
    $db->commit();
    $committed = true;
    $result['own_order_id'] = $orderId;
    $result['sql_cast_exact'] = (string)$new['exact_id'];
    require_once $root . '/application/base/Security.php';
    $token = \app\base\Security::encrypt(implode("\t", [
        (string)$source['user_id'], (string)$source['user_uuid'],
        (string)$source['account'], '0', '', '', (string)$source['account'],
    ]));
    $form = http_build_query(['orderId' => $orderId], '', '&', PHP_QUERY_RFC3986);
    $context = stream_context_create(['http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\ntoken: " . $token . "\r\n",
        'content' => $form, 'timeout' => 30, 'ignore_errors' => true,
    ]]);
    $httpBody = @file_get_contents($base . '/p/mealOrder/detail', false, $context);
    if (!is_string($httpBody)) throw new RuntimeException('Detail HTTP body unavailable');
    $headers = $http_response_header ?? [];
    $result['http_status'] = preg_match('/^HTTP\/\S+\s+(\d+)/', (string)($headers[0] ?? ''), $m)
        ? (int)$m[1] : 0;
    $response = json_decode($httpBody, true);
    if (!is_array($response)) throw new RuntimeException('Detail did not return JSON');
    $result['http_code'] = $response['code'] ?? null;
    $data = $response['data'] ?? null;
    $result['matched_own_order'] = is_array($data)
        && (string)($data['order_no'] ?? '') === $marker;
    $result['field_present'] = is_array($data)
        && array_key_exists('account_settlement_id', $data);
    $value = $result['field_present'] ? $data['account_settlement_id'] : null;
    $result['field_json_type'] = $result['field_present'] ? gettype($value) : 'missing';
    $result['field_json_value'] = $result['field_present'] ? (string)$value : null;
    $result['field_exact'] = $result['field_present']
        && (string)$value === $high;
    $result['http_body_sha256'] = hash('sha256', $httpBody);
    $result['own_goods'] = $count($db, 'SELECT COUNT(*) AS N FROM ' . $table
        . 'initial_menu WHERE MEAL_ORDER_ID=?', [$orderId]);
    $result['own_pickup'] = $count($db, 'SELECT COUNT(*) AS N FROM ' . $table
        . 'meal_order_pickup WHERE MEAL_ORDER_ID=?', [$orderId]);
} catch (Throwable $error) {
    $result['error_class'] = get_class($error);
    $result['error_message_sha256'] = hash('sha256', $error->getMessage());
} finally {
    if ($db instanceof PDO) {
        try {
            if ($db->inTransaction()) $db->rollBack();
            if ($committed && $orderId > 0 && is_array($source)) {
                $db->beginTransaction();
                $delete = $db->prepare('DELETE FROM ' . $table . 'meal_order'
                    . ' WHERE ID=? AND ORDER_NO=? AND MSGID=? AND USER_ID=?'
                    . ' AND PAY_STATUS=10 AND PRINT_STATUS=0');
                $delete->execute([$orderId, $marker, $marker, (int)$source['user_id']]);
                if ($delete->rowCount() !== 1) throw new RuntimeException('Own order cleanup mismatch');
                if ($granted) {
                    $restore = $db->prepare('UPDATE ' . $table . 'user SET TYPE=1'
                        . ' WHERE ID=? AND UUID=? AND ACCOUNT=? AND TYPE=0');
                    $restore->execute([(int)$source['user_id'], (string)$source['user_uuid'],
                        (string)$source['account']]);
                    if ($restore->rowCount() !== 1) throw new RuntimeException('Synthetic type restore mismatch');
                }
                $db->commit();
            }
            $result['remaining_marker_rows'] = $count($db,
                'SELECT COUNT(*) AS N FROM ' . $table . 'meal_order'
                    . ' WHERE ORDER_NO=? OR MSGID=?', [$marker, $marker]);
            $after = $findSource($db);
            $result['source_type_after'] = (int)$after['user_type'];
            $result['cleaned'] = $result['remaining_marker_rows'] === 0
                && (int)$after['user_type'] === 1;
        } catch (Throwable $cleanupError) {
            $result['cleanup_error_class'] = get_class($cleanupError);
            $result['cleanup_message_sha256'] = hash('sha256', $cleanupError->getMessage());
            if ($db->inTransaction()) $db->rollBack();
        }
    }
}
echo json_encode($result, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), PHP_EOL;
exit(empty($result['cleaned']) || isset($result['error_class'])
    || ($result['http_code'] ?? null) !== 0 ? 1 : 0);
