<?php
declare(strict_types=1);

// SELECT-only B/C user + export-log physical structure gate.
$lane = (string)($argv[1] ?? '');
if (!in_array($lane, ['B', 'C'], true)) exit(78);
$root = $lane === 'B' ? '/tmp/zhct-http-store-mysql.dQTTBP'
    : '/tmp/zhct-dm-poc-20260928.fcpiiN/store';
$cfg = require $root . '/application/database.php';
if ($lane === 'B') {
    $local = require '/workspace/zhct/zhctproject/store/application/config/local/database.php';
    foreach (['hostname', 'database', 'username', 'password'] as $key) {
        if (($cfg[$key] ?? null) !== ($local[$key] ?? null)) {
            throw new RuntimeException('not local MySQL');
        }
    }
    $dsn = 'mysql:host=' . $cfg['hostname'] . ';port=' . ($cfg['hostport'] ?? 3306)
        . ';dbname=' . $cfg['database'] . ';charset=utf8mb4';
} else {
    foreach (['hostname' => 'POC_HOST', 'hostport' => 'POC_PORT',
        'database' => 'POC_SCHEMA', 'username' => 'POC_USER',
        'password' => 'POC_PASSWORD'] as $key => $env) {
        if ((string)($cfg[$key] ?? '') !== (string)getenv($env)) {
            throw new RuntimeException('not Store worker DM');
        }
    }
    if ((string)getenv('POC_HOST') !== '127.0.0.1'
        || (string)getenv('POC_PORT') !== '5237'
        || strtoupper((string)getenv('POC_SCHEMA')) !== 'ZHCT_APP') {
        throw new RuntimeException('not approved DM');
    }
    $dsn = 'dm:host=127.0.0.1;port=5237;schema=ZHCT_APP';
}
$db = new PDO($dsn, (string)$cfg['username'], (string)$cfg['password'], [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_TIMEOUT => 5]);
$identity = $lane === 'B'
    ? (string)$db->query("SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")->fetchColumn()
    : 'ZHCT_APP|5237|' . (string)$db->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn();
if (hash('sha256', $identity) !== ($lane === 'B'
        ? '003eb5aecf1cd4595b609c1f7f20b9ee325b578309fb9fe14fedaf77584fa401'
        : 'bc98485aed26beab348770a82ae38dbf922b04ab88a210cd7282c4caf0156194')) {
    throw new RuntimeException('DB identity');
}
$p = $lane === 'B' ? 'ydy_' : 'YDY_';
$result = [];
foreach (['user', 'export_log'] as $suffix) {
    $table = $lane === 'B' ? $p . $suffix : strtoupper($p . $suffix);
    if ($lane === 'B') {
        $sql = 'SELECT COLUMN_NAME,DATA_TYPE,IS_NULLABLE,COLUMN_DEFAULT,EXTRA'
            . ' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=? AND TABLE_NAME=?'
            . ' ORDER BY ORDINAL_POSITION';
        $args = [(string)$cfg['database'], $table];
    } else {
        $sql = 'SELECT COLUMN_NAME,DATA_TYPE,NULLABLE,DATA_DEFAULT'
            . ' FROM ALL_TAB_COLUMNS WHERE OWNER=? AND TABLE_NAME=? ORDER BY COLUMN_ID';
        $args = ['ZHCT_APP', $table];
    }
    $stmt = $db->prepare($sql);
    $stmt->execute($args);
    $names = [];
    $required = [];
    $types = [];
    while (($row = $stmt->fetch(PDO::FETCH_ASSOC)) !== false) {
        $row = array_change_key_case($row, CASE_LOWER);
        foreach ($row as $key => $value) {
            if (is_resource($value)) $row[$key] = stream_get_contents($value);
        }
        $name = strtolower((string)$row['column_name']);
        $type = strtolower((string)$row['data_type']);
        $names[] = $name;
        $types[$name] = $type;
        $nullable = (string)$row[$lane === 'B' ? 'is_nullable' : 'nullable'];
        $default = $row[$lane === 'B' ? 'column_default' : 'data_default'] ?? null;
        $extra = (string)($row['extra'] ?? '');
        if (in_array($nullable, ['NO', 'N'], true) && $default === null
            && stripos($extra, 'auto_increment') === false) {
            $required[] = $name . ':' . $type;
        }
    }
    if (!$names || count($names) > 100) throw new RuntimeException('table missing/unbounded');
    if ($lane === 'B') {
        $triggerSql = 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TRIGGERS'
            . ' WHERE TRIGGER_SCHEMA=? AND EVENT_OBJECT_TABLE=?';
        $fkSql = 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE'
            . ' WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND REFERENCED_TABLE_NAME IS NOT NULL';
        $indexSql = 'SELECT DISTINCT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS'
            . ' WHERE TABLE_SCHEMA=? AND TABLE_NAME=?';
    } else {
        $triggerSql = 'SELECT COUNT(*) FROM ALL_TRIGGERS WHERE OWNER=? AND TABLE_NAME=?';
        $fkSql = "SELECT COUNT(*) FROM ALL_CONSTRAINTS WHERE OWNER=? AND TABLE_NAME=? AND CONSTRAINT_TYPE='R'";
        $indexSql = 'SELECT INDEX_NAME FROM ALL_INDEXES WHERE OWNER=? AND TABLE_NAME=?';
    }
    $triggers = $db->prepare($triggerSql); $triggers->execute($args);
    $fks = $db->prepare($fkSql); $fks->execute($args);
    $indexes = $db->prepare($indexSql); $indexes->execute($args);
    $indexNames = $indexes->fetchAll(PDO::FETCH_COLUMN);
    sort($indexNames);
    if ($lane === 'C') {
        $rawDdl = $db->query("SELECT DBMS_METADATA.GET_DDL('TABLE','" . $table
            . "') FROM DUAL")->fetchColumn();
        $ddl = is_resource($rawDdl) ? stream_get_contents($rawDdl) : (string)$rawDdl;
    } else {
        $show = $db->query('SHOW CREATE TABLE `' . $table . '`')->fetch(PDO::FETCH_ASSOC);
        $ddl = (string)($show['create table'] ?? '');
    }
    $idAutoIncrement = (bool)preg_match('/\bID\b[^,\n]*\bAUTO_INCREMENT\b/i', $ddl);
    $result[$suffix] = ['columns' => count($names), 'required' => $required,
        'selected_types' => array_intersect_key($types, array_fill_keys([
            'id', 'uuid', 'account', 'create_by_uuid', 'status', 'type',
            'file_path', 'file_name', 'query_conditions', 'hash_key'], true)),
        'triggers' => (int)$triggers->fetchColumn(),
        'foreign_keys' => (int)$fks->fetchColumn(),
        'id_auto_increment' => $idAutoIncrement,
        'indexes' => $indexNames];
}
echo json_encode(['lane' => $lane, 'identity_match' => true,
    'tables' => $result], JSON_UNESCAPED_UNICODE), PHP_EOL;
