<?php

declare(strict_types=1);

// REVIEW DRAFT ONLY. No DB/HTTP work without separate approval of this SHA.
if ((string)getenv('CDX_ARTICLE_INFO_EXECUTE') !== 'ROOT_APPROVED_EXACT_SHA'
    || ($argv[1] ?? '') !== '--execute-article-info') {
    fwrite(STDERR, "Review draft; Article info disabled\n");
    exit(2);
}

$phase = 'runtime';
set_exception_handler(static function (Throwable $error) use (&$phase): void {
    $safe = in_array($phase, [
        'runtime', 'base-init', 'snapshot-before', 'candidate',
        'http-info', 'snapshot-after',
    ], true) ? $phase : 'unknown';
    fwrite(STDERR, 'ARTICLE_INFO_GATE_FAILED phase=' . $safe . ' '
        . get_class($error) . ' code=' . (string)$error->getCode() . PHP_EOL);
    exit(2);
});

$baseFile = __DIR__ . '/StoreReadOnlyBatchBase.php';
if (!is_file($baseFile) || is_link($baseFile)
    || hash_file('sha256', $baseFile)
        !== '2c0d9b245c89a206d097d7ca061957d1603b14c7462802fc37392339afb408e7') {
    throw new RuntimeException('Reviewed read-only base missing');
}
require_once $baseFile;

$lane = (string)getenv('CDX_ARTICLE_INFO_LANE');
$runtime = [
    'A' => ['/tmp/zhct-http-store-a.l5omH8', 'http://127.0.0.1:18097', '21023'],
    'B' => ['/tmp/zhct-http-store-mysql.dQTTBP', 'http://127.0.0.1:18081', '10001'],
    'C' => ['/tmp/zhct-dm-poc-20260928.fcpiiN/store', 'http://127.0.0.1:18080', '112175'],
];
if (!isset($runtime[$lane])) {
    throw new RuntimeException('Unreviewed Store lane');
}
if ($lane === 'A' || $lane === 'B') {
    $load = static function (string $file): array {
        $value = require $file;
        if (!is_array($value)) {
            throw new RuntimeException('Invalid code-local configuration');
        }
        return $value;
    };
    $local = $load('/workspace/zhct/zhctproject/store/application/config/local/database.php');
    foreach ([
        'POC_HOST' => 'hostname',
        'POC_SCHEMA' => 'database',
        'POC_USER' => 'username',
        'POC_PASSWORD' => 'password',
    ] as $env => $field) {
        if (!isset($local[$field]) || (string)$local[$field] === '') {
            throw new RuntimeException('Incomplete code-local configuration');
        }
        putenv($env . '=' . (string)$local[$field]);
    }
    putenv('POC_PORT=' . (string)(int)($local['hostport'] ?? 3306));
    putenv('POC_DIALECT=mysql');
} else {
    // Read only this nonproduction Store worker's DB context into memory.
    $workerEnv = (string)file_get_contents('/proc/112175/environ');
    $approved = array_fill_keys([
        'POC_HOST', 'POC_PORT', 'POC_SCHEMA', 'POC_USER', 'POC_PASSWORD',
    ], null);
    foreach (explode("\0", $workerEnv) as $entry) {
        $parts = explode('=', $entry, 2);
        if (count($parts) === 2 && array_key_exists($parts[0], $approved)) {
            $approved[$parts[0]] = $parts[1];
        }
    }
    if ($approved['POC_HOST'] !== '127.0.0.1'
        || $approved['POC_PORT'] !== '5237'
        || strtoupper((string)$approved['POC_SCHEMA']) !== 'ZHCT_APP'
        || strtoupper((string)$approved['POC_USER']) !== 'ZHCT_APP'
        || empty($approved['POC_PASSWORD'])) {
        throw new RuntimeException('Wrong nonproduction Store database context');
    }
    foreach ($approved as $name => $value) {
        putenv($name . '=' . $value);
    }
    putenv('POC_DIALECT=dm');
}
putenv('POC_APP_ROOT=' . $runtime[$lane][0]);
putenv('POC_BASE_URL=' . $runtime[$lane][1]);
putenv('POC_RUNTIME_PID=' . $runtime[$lane][2]);
putenv('CDX_STORE_READ_BATCH_EXECUTE=ROOT_APPROVED_EXACT_SHA');
putenv('CDX_STORE_READ_TOKEN');
putenv('HTTP_COOKIE');
$_COOKIE = [];

$phase = 'base-init';
$batch = new StoreReadOnlyBatchBase(
    $lane,
    ['/p/article/info'],
    [
        'application/route.php',
        'application/base/AdminController.php',
        'application/p/controller/Article.php',
        'application/p/logic/Article.php',
        'application/model/Article.php',
        'application/model/ArticleCate.php',
    ],
    '5b83511bc18baaea05976b83f797e2fedb32114ac62e3a76812283a975d000e1'
);
$queries = [
    'article_cate' => 'SELECT UUID,PUUID,LEVEL FROM '
        . $batch->table('article_cate') . ' ORDER BY ID',
    'article' => 'SELECT UUID,ARTICLE_CATE_UUID,STATUS FROM '
        . $batch->table('article') . ' ORDER BY ID',
];
$phase = 'snapshot-before';
$before = $batch->snapshot($queries);
if ($before['article_cate']['count'] < 1
    || $before['article']['count'] < 1) {
    throw new RuntimeException('Nonempty source required');
}
$phase = 'candidate';
$candidateSql = 'SELECT a.UUID FROM ' . $batch->table('article')
    . ' a JOIN ' . $batch->table('article_cate')
    . ' c ON c.UUID=a.ARTICLE_CATE_UUID'
    . ' WHERE a.STATUS=1 ORDER BY a.ID';
$candidates = $batch->selectRows($candidateSql);
if (!$candidates || !isset($candidates[0]['uuid'])
    || !preg_match('/^[A-Fa-f0-9-]{36}$/', (string)$candidates[0]['uuid'])) {
    throw new RuntimeException('No safe existing article/category relation');
}
$uuid = (string)$candidates[0]['uuid'];
$phase = 'http-info';
$response = $batch->post('/p/article/info', ['uuid' => $uuid]);
$data = $response['data'] ?? null;
if (!array_key_exists('code', $response)
    || (int)$response['code'] !== 0
    || !is_array($data) || !$data
    || strtoupper((string)($data['uuid'] ?? '')) !== strtoupper($uuid)) {
    throw new RuntimeException('Article info positive contract failed');
}
$phase = 'snapshot-after';
$after = $batch->snapshot($queries);
if ($before !== $after) {
    throw new RuntimeException('Article source changed');
}
echo json_encode([
    'lane' => $lane,
    'path' => '/p/article/info',
    'auth' => 'anonymous-no-cookie-no-token',
    'source_counts' => [
        'article_cate' => $before['article_cate']['count'],
        'article' => $before['article']['count'],
        'active_related' => count($candidates),
    ],
    'source_unchanged' => true,
    'candidate_uuid_sha12' => substr(hash('sha256', $uuid), 0, 12),
    'response' => StoreReadOnlyBatchBase::safeResponse($response),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
