<?php
declare(strict_types=1);

// One read-only mobile request in isolated C; DM8 Store source. No DML.
set_exception_handler(static function (Throwable $error): void {
    echo json_encode(['status' => 'order-list-c-error', 'class' => get_class($error),
        'code' => (string)$error->getCode()], JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(2);
});
if (getenv('CDX_READ_APPROVED') !== 'ORDER_LIST_READ_V1'
    || (string)getenv('CDX_READ_SCRIPT_SHA') === ''
    || hash_file('sha256', __FILE__) !== (string)getenv('CDX_READ_SCRIPT_SHA')) {
    throw new RuntimeException('Read execution gate missing');
}
$pid = 53772;
$root = '/tmp/zhct-ai-http-20260929.3XDj3w';
$sourceSha = '7d91cc13b226732a3f53293b97a18384136826a3aab27e7dc8715e29cf28d9fc';
$rawEnv = file_get_contents('/proc/' . $pid . '/environ');
$cmd = file_get_contents('/proc/' . $pid . '/cmdline');
if ($rawEnv === false || $cmd === false || strpos($cmd, '127.0.0.1:18102') === false
    || strpos($cmd, $root . '/public') === false
    || hash_file('sha256', $root . '/app/api/model/Restaurant.php') !== $sourceSha) {
    throw new RuntimeException('C isolated process or source drift');
}
$env = [];
foreach (explode("\0", $rawEnv) as $part) {
    if (strpos($part, 'POC_') !== 0) continue;
    $at = strpos($part, '=');
    if ($at !== false) $env[substr($part, 0, $at)] = substr($part, $at + 1);
}
foreach (['POC_DIALECT' => 'dm', 'POC_EXTERNAL_STUBS' => '1',
    'POC_HOST' => '127.0.0.1', 'POC_PORT' => '5237',
    'POC_SCHEMA' => 'ZHCT_APP', 'POC_AI_PORT' => '5238',
    'POC_AI_SCHEMA' => 'AIZHCT_APP'] as $key => $expected) {
    if (($env[$key] ?? null) !== $expected) throw new RuntimeException('C DB boundary mismatch');
}
if (empty($env['POC_USER']) || empty($env['POC_PASSWORD'])) {
    throw new RuntimeException('C private DB config unavailable');
}
$base = 'http://127.0.0.1:18102';
$boundary = json_decode((string)file_get_contents($base . '/__poc_boundary'), true);
if (!is_array($boundary) || ($boundary['external_stubs'] ?? false) !== true) {
    throw new RuntimeException('C external stub boundary missing');
}
$pdo = new PDO('dm:host=127.0.0.1;port=5237;schema=ZHCT_APP',
    $env['POC_USER'], $env['POC_PASSWORD'], [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_CASE => PDO::CASE_LOWER,
    ]);
$owner = strtoupper((string)$pdo->query('SELECT USER FROM DUAL')->fetchColumn());
$schema = strtoupper((string)$pdo->query(
    "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn());
$identity = $owner . '|5237|' . $schema;
if (hash('sha256', $identity) !==
    'bc98485aed26beab348770a82ae38dbf922b04ab88a210cd7282c4caf0156194') {
    throw new RuntimeException('Not the approved nonprod DM Store');
}
$today = date('Y-m-d');
$until = date('Y-m-d', strtotime('+30 days'));
$candidate = $pdo->prepare('SELECT q.RESTAURANT_ID,q.MENU_DATE,q.MEAL_TIMES FROM ('
    . 'SELECT r.RESTAURANT_ID,r.MENU_DATE,r.MEAL_TIMES '
    . 'FROM YDY_RECIPES r JOIN YDY_DISHES d ON d.UUID=r.DISHES_UUID '
    . 'JOIN YDY_RESTAURANTS s ON s.ID=r.RESTAURANT_ID '
    . 'WHERE r.MENU_DATE BETWEEN ? AND ? AND d.IS_DELETE=0 AND d.AI_DISHES_ID>0 '
    . 'AND s.IS_DELETE=2 AND s.STATUS=1 AND s.STALL_TYPE IN (1,2,3) '
    . 'ORDER BY r.MENU_DATE,r.RESTAURANT_ID) q WHERE ROWNUM=1');
$candidate->execute([$today, $until]);
$row = $candidate->fetch(PDO::FETCH_ASSOC);
if (!is_array($row)) throw new RuntimeException('No natural future DM recipe');
$restaurantId = (int)$row['restaurant_id'];
$menuDate = substr((string)$row['menu_date'], 0, 10);
$mealTimes = (int)$row['meal_times'];
$restaurant = $pdo->prepare('SELECT ID,STATUS,IS_DELETE,STALL_TYPE,BOOK_RULES '
    . 'FROM YDY_RESTAURANTS WHERE ID=?');
$recipes = $pdo->prepare('SELECT r.ID,r.DISHES_UUID,r.MEAL_TIMES,r.MENU_DATE,'
    . 'd.ID AS DISH_ID,d.AI_DISHES_ID,d.IS_DELETE AS DISH_DELETED '
    . 'FROM YDY_RECIPES r JOIN YDY_DISHES d ON d.UUID=r.DISHES_UUID '
    . 'WHERE r.RESTAURANT_ID=? AND r.MENU_DATE=? AND r.MEAL_TIMES=? ORDER BY r.ID');
$snapshot = static function () use ($restaurant, $recipes, $restaurantId, $menuDate, $mealTimes): array {
    $restaurant->execute([$restaurantId]);
    $restaurantRow = $restaurant->fetch(PDO::FETCH_ASSOC);
    $recipes->execute([$restaurantId, $menuDate, $mealTimes]);
    $recipeRows = $recipes->fetchAll(PDO::FETCH_ASSOC);
    $activeCount = 0;
    foreach ($recipeRows as $recipe) {
        if ((int)$recipe['dish_deleted'] === 0 && (int)$recipe['ai_dishes_id'] > 0) ++$activeCount;
    }
    return ['restaurant' => hash('sha256', json_encode($restaurantRow)),
        'recipe_dishes' => hash('sha256', json_encode($recipeRows)),
        'active_dish_count' => $activeCount];
};
$before = $snapshot();
if ($before['active_dish_count'] < 1) throw new RuntimeException('Selected DM recipe has no active dish');
$restaurant->execute([$restaurantId]);
$businessRow = $restaurant->fetch(PDO::FETCH_ASSOC);
$bookRules = json_decode((string)($businessRow['book_rules'] ?? ''), true);
$stallType = (int)($businessRow['stall_type'] ?? 0);
$bookRuleType = is_array($bookRules) ? ($bookRules['rule'] ?? null) : null;
$url = $base . '/api/restaurant/orderList?storeId=10001';
$request = stream_context_create(['http' => ['method' => 'POST', 'ignore_errors' => true,
    'timeout' => 30,
    'header' => "platform: POC\r\nContent-Type: application/x-www-form-urlencoded\r\n",
    'content' => http_build_query(['restaurant_id' => $restaurantId])]]);
$started = microtime(true);
$raw = file_get_contents($url, false, $request);
$elapsedMs = (int)round((microtime(true) - $started) * 1000);
$line = $http_response_header[0] ?? '';
$http = preg_match('/HTTP\/\S+\s+(\d+)/', $line, $match) ? (int)$match[1] : 0;
$body = is_string($raw) && strlen($raw) <= 1000000 ? json_decode($raw, true) : null;
$dates = is_array($body) ? ($body['data']['list'] ?? null) : null;
$matched = null;
if (is_array($dates)) {
    foreach ($dates as $date) {
        if (!is_array($date) || substr((string)($date['date'] ?? ''), 0, 10) !== $menuDate) continue;
        foreach (($date['meal'] ?? []) as $meal) {
            if (is_array($meal) && (int)($meal['value'] ?? 0) === $mealTimes) {
                $matched = ['date' => (string)$date['date'],
                    'weekday_type' => gettype($date['weekday'] ?? null),
                    'meal_value_type' => gettype($meal['value'] ?? null),
                    'dishes_num_type' => gettype($meal['dishes_num'] ?? null),
                    'dishes_num' => (int)($meal['dishes_num'] ?? -1),
                    'meal_keys' => array_keys($meal)];
            }
        }
    }
}
$after = $snapshot();
$normalized = is_array($body) ? $body : null;
if (is_array($normalized)) unset($normalized['trace_id']);
$pass = $http === 200 && is_array($body) && (int)($body['status'] ?? 0) === 200
    && is_array($dates) && count($dates) > 0 && is_array($matched)
    && $matched['dishes_num'] === $before['active_dish_count']
    && $before === $after;
echo json_encode(['status' => $pass ? 'order-list-c-pass' : 'order-list-c-fail',
    'lane' => 'C', 'http' => $http, 'business_status' => $body['status'] ?? null,
    'elapsed_ms' => $elapsedMs, 'restaurant_id' => $restaurantId,
    'source_stall_type' => $stallType, 'source_book_rule_type' => $bookRuleType,
    'menu_date' => $menuDate, 'meal_times' => $mealTimes,
    'source_active_dishes' => $before['active_dish_count'],
    'response_dates' => is_array($dates) ? count($dates) : null,
    'selected' => $matched, 'original_table_hashes_unchanged' => $before === $after,
    'response_contract_sha256' => is_array($normalized)
        ? hash('sha256', json_encode($normalized, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) : null,
    'db_fingerprint' => hash('sha256', $identity),
    'source_sha256' => $sourceSha], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
exit($pass ? 0 : 3);
