<?php
declare(strict_types=1);

$lane = (string)($argv[1] ?? '');
if (!in_array($lane, ['B', 'C'], true)) {
    fwrite(STDERR, "DENIED business_http=0 business_dml=0\n"); exit(78);
}
if ($lane === 'B') {
    $config = include '/tmp/zhct-http-store-mysql.dQTTBP/application/config/local/database.php';
    if (!is_array($config) || ($config['database'] ?? '') !== 'zhct'
        || hash('sha256', (string)($config['hostname'] ?? ''))
            !== '47e8be48b0cfd56dcdb9d9d426e6637b245f340b4efad4cd2f084ec5851ecc8e') {
        throw new RuntimeException('B code-local MySQL identity drift');
    }
    $db = new PDO('mysql:host=' . $config['hostname'] . ';port=3306;dbname=zhct;charset=utf8',
        $config['username'], $config['password'],
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_CASE => PDO::CASE_LOWER]);
    $port = 18081;
} else {
    if (getenv('POC_DIALECT') !== 'dm' || getenv('POC_HOST') !== '127.0.0.1'
        || getenv('POC_PORT') !== '5237' || getenv('POC_SCHEMA') !== 'ZHCT_APP'
        || getenv('POC_USER') !== 'ZHCT_APP') {
        throw new RuntimeException('C isolated DM identity drift');
    }
    $db = new PDO('dm:host=127.0.0.1;port=5237;schema=ZHCT_APP',
        getenv('POC_USER'), getenv('POC_PASSWORD'),
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_CASE => PDO::CASE_LOWER]);
    if ($db->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn() !== 'ZHCT_APP') {
        throw new RuntimeException('C schema drift');
    }
    $port = 18080;
}
$candidateSql = 'SELECT a.staff_uuid,a.menu_date,a.meal_times,COUNT(*) AS n'
    . ' FROM ydy_date_menu a JOIN ydy_dishes d ON a.dishes_uuid=d.uuid'
    . ' JOIN ydy_staff s ON a.staff_uuid=s.uuid'
    . ' WHERE a.meal_type IN (1,2) AND a.meal_times IN (1,2,3)'
    . ' AND d.is_del=1 AND d.status=1 AND s.is_show=1'
    . ' GROUP BY a.staff_uuid,a.menu_date,a.meal_times'
    . ' ORDER BY a.menu_date DESC,a.staff_uuid ASC'
    . ($lane === 'B' ? ' LIMIT 1' : ' FETCH FIRST 1 ROWS ONLY');
$candidate = $db->query($candidateSql)->fetch(PDO::FETCH_ASSOC);
if (!is_array($candidate)) {
    echo json_encode(['lane' => $lane, 'source_positive_candidate' => false,
        'business_http' => 0, 'business_dml' => 0]), PHP_EOL;
    exit(4);
}
$candidate = array_change_key_case($candidate, CASE_LOWER);
$staffUuid = (string)$candidate['staff_uuid'];
$date = substr((string)$candidate['menu_date'], 0, 10);
$mealTimes = (int)$candidate['meal_times'];
$sourceQuery = $db->prepare('SELECT a.dishes_uuid FROM ydy_date_menu a'
    . ' JOIN ydy_dishes d ON a.dishes_uuid=d.uuid'
    . ' WHERE a.staff_uuid=? AND a.menu_date=? AND a.meal_times=?'
    . ' AND a.meal_type IN (1,2) AND d.is_del=1 AND d.status=1');
$sourceQuery->execute([$staffUuid, $date, $mealTimes]);
$dishUuids = $sourceQuery->fetchAll(PDO::FETCH_COLUMN);
if (!$dishUuids) throw new RuntimeException('chosen print menu has no active dish');
$sourceSet = array_fill_keys(array_map('strval', $dishUuids), true);
$http = static function (string $path, array $form) use ($port): array {
    $ctx = stream_context_create(['http' => [
        'method' => 'POST', 'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
        'content' => http_build_query($form, '', '&', PHP_QUERY_RFC3986),
        'ignore_errors' => true, 'timeout' => 20, 'follow_location' => 0,
    ]]);
    $handle = @fopen('http://127.0.0.1:' . $port . $path, 'rb', false, $ctx);
    if (!is_resource($handle)) throw new RuntimeException('isolated print HTTP unavailable');
    $raw = stream_get_contents($handle, 4194305);
    fclose($handle);
    if (!is_string($raw) || strlen($raw) > 4194304) throw new RuntimeException('print HTTP response cap');
    $body = json_decode($raw, true);
    if (!is_array($body) || (int)($body['code'] ?? -1) !== 0) {
        throw new RuntimeException('business print response failed at ' . $path
            . ' code=' . (string)($body['code'] ?? 'nonjson')
            . ' message=' . substr((string)($body['message'] ?? ''), 0, 120));
    }
    return $body;
};
$form = ['meuns_date' => $date, 'meal_times' => $mealTimes, 'staff_uuid' => $staffUuid];
$printList = $http('/p/api/getPrintList', $form)['data'] ?? null;
if (!is_array($printList) || empty($printList['menu_count'])) {
    throw new RuntimeException('print list lacks nonempty chosen menu');
}
$categorized = 0;
$firstItem = null;
foreach (['staple_food', 'meat_dishes', 'vegetable', 'custard', 'fruit', 'soup'] as $key) {
    foreach (($printList[$key] ?? []) as $item) {
        if (!isset($sourceSet[(string)($item['dishes_uuid'] ?? '')])) {
            throw new RuntimeException('print list dish lacks original date menu row');
        }
        if ($firstItem === null) $firstItem = $item;
        $categorized++;
    }
}
if ($categorized === 0 || $firstItem === null) {
    throw new RuntimeException('print list has no categorized source dish');
}
$content = $http('/p/api/print_content', $form)['data'] ?? null;
if (!is_array($content) || (string)($content['date'] ?? '') !== $date
    || !is_array($content['list'] ?? null) || !$content['list']) {
    throw new RuntimeException('print content lacks nonempty chosen menu');
}
$contentItems = 0;
$contentFirst = null;
foreach ($content['list'] as $staff) {
    foreach (($staff['list'] ?? []) as $item) {
        if (!isset($sourceSet[(string)($item['dishes_uuid'] ?? '')])) {
            throw new RuntimeException('print content dish lacks original date menu row');
        }
        if ($contentFirst === null) $contentFirst = $item;
        $contentItems++;
    }
}
if ($contentItems === 0 || $contentFirst === null) throw new RuntimeException('print content items empty');
$roundSource = $db->prepare('SELECT ROUND(energy,0) AS val,ROUND(weight,1) AS weight'
    . ' FROM ydy_dishes WHERE uuid=?');
foreach ([$firstItem, $contentFirst] as $item) {
    $roundSource->execute([(string)$item['dishes_uuid']]);
    $sourceRound = $roundSource->fetch(PDO::FETCH_ASSOC);
    if (!is_array($sourceRound)) throw new RuntimeException('print dish source missing');
    $sourceRound = array_change_key_case($sourceRound, CASE_LOWER);
    if ((string)$item['val'] !== bcadd((string)$sourceRound['val'], '0', 0)
        || (string)$item['weight'] !== bcadd((string)$sourceRound['weight'], '0', 1)) {
        throw new RuntimeException('print rounded value differs from original dish');
    }
}
$sourceQuery->execute([$staffUuid, $date, $mealTimes]);
if ($dishUuids !== $sourceQuery->fetchAll(PDO::FETCH_COLUMN)) {
    throw new RuntimeException('original date menu rows changed during read');
}
$types = static function (array $row): array {
    $map = [];
    foreach ($row as $key => $value) $map[$key] = gettype($value);
    ksort($map);
    return $map;
};
$listTypes = $types($firstItem);
$contentTypes = $types($contentFirst);
echo json_encode(['lane' => $lane, 'http_business_ok' => 2,
    'source_dish_rows' => count($dishUuids),
    'print_list_dish_rows' => $categorized,
    'print_content_dish_rows' => $contentItems,
    'print_list_item_type_sha256' => hash('sha256', json_encode($listTypes)),
    'print_content_item_type_sha256' => hash('sha256', json_encode($contentTypes)),
    'print_list_top_type_sha256' => hash('sha256', json_encode($types($printList))),
    'print_content_top_type_sha256' => hash('sha256', json_encode($types($content))),
    'sampled_round_values_own_source_equal' => true,
    'business_dml' => 0, 'physical_print' => 0], JSON_UNESCAPED_SLASHES), PHP_EOL;
