<?php
declare(strict_types=1);

// Read-only table-shape gate before designing isolated cash-refund write fixtures.
$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 (!is_array($cfg) || ($cfg['prefix'] ?? '') !== 'ydy_'
    || ($cfg['ai_zhct']['prefix'] ?? '') !== 'yoshop_') {
    throw new RuntimeException('worker database config');
}
$ac = $cfg['ai_zhct'];
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)
            || ($ac[$key] ?? null) !== ($local['ai_zhct'][$key] ?? null)) {
            throw new RuntimeException('not code-local MySQL');
        }
    }
    $storeDsn = 'mysql:host=' . $cfg['hostname'] . ';port=' . ($cfg['hostport'] ?? 3306)
        . ';dbname=' . $cfg['database'] . ';charset=utf8mb4';
    $aiDsn = 'mysql:host=' . $ac['hostname'] . ';port=' . ($ac['hostport'] ?? 3306)
        . ';dbname=' . $ac['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('Store DM config');
        }
    }
    foreach (['hostname' => 'POC_AI_HOST', 'hostport' => 'POC_AI_PORT',
        'database' => 'POC_AI_SCHEMA', 'username' => 'POC_AI_USER',
        'password' => 'POC_AI_PASSWORD'] as $key => $env) {
        if ((string)($ac[$key] ?? '') !== (string)getenv($env)) {
            throw new RuntimeException('AI DM config');
        }
    }
    if ((string)getenv('POC_HOST') !== '127.0.0.1'
        || (string)getenv('POC_PORT') !== '5237'
        || strtoupper((string)getenv('POC_SCHEMA')) !== 'ZHCT_APP'
        || (string)getenv('POC_AI_HOST') !== '127.0.0.1'
        || (string)getenv('POC_AI_PORT') !== '5238'
        || strtoupper((string)getenv('POC_AI_SCHEMA')) !== 'AIZHCT_APP') {
        throw new RuntimeException('not approved DM');
    }
    $storeDsn = 'dm:host=127.0.0.1;port=5237;schema=ZHCT_APP';
    $aiDsn = 'dm:host=127.0.0.1;port=5238;schema=AIZHCT_APP';
}
$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_TIMEOUT => 5];
$store = new PDO($storeDsn, (string)$cfg['username'], (string)$cfg['password'], $options);
$ai = new PDO($aiDsn, (string)$ac['username'], (string)$ac['password'], $options);
$storeTables = ['ydy_user', 'ydy_staff', 'ydy_staff_department',
    'ydy_department', 'ydy_security_audit_log'];
$aiTables = ['yoshop_user', 'yoshop_recharge_order', 'yoshop_cash_refund_order',
    'yoshop_cash_refund_order_log', 'yoshop_user_balance_log'];
$referenceColumnsSql = $lane === 'C'
    ? "SELECT TABLE_NAME,COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE OWNER='AIZHCT_APP'"
      . " AND COLUMN_NAME IN ('USER_ID','RECHARGE_ORDER_ID') ORDER BY TABLE_NAME,COLUMN_NAME"
    : "SELECT TABLE_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS"
      . " WHERE TABLE_SCHEMA='" . str_replace("'", "''", (string)$ac['database']) . "'"
      . " AND COLUMN_NAME IN ('user_id','recharge_order_id') ORDER BY TABLE_NAME,COLUMN_NAME";
$referenceColumns = array_map(static function (array $row): array {
    $row = array_change_key_case($row, CASE_LOWER);
    return ['table' => strtolower((string)$row['table_name']),
        'column' => strtolower((string)$row['column_name'])];
}, $ai->query($referenceColumnsSql)->fetchAll(PDO::FETCH_ASSOC));
$read = static function (PDO $db, array $tables, string $schema, bool $dm): array {
    $summary = [];
    foreach ($tables as $name) {
        $physical = $dm ? strtoupper($name) : $name;
        if ($dm) {
            $sql = 'SELECT COLUMN_NAME,DATA_TYPE,NULLABLE,DATA_DEFAULT'
                . ' FROM ALL_TAB_COLUMNS WHERE OWNER=? AND TABLE_NAME=? ORDER BY COLUMN_ID';
            $stmt = $db->prepare($sql);
            $stmt->execute([$schema, $physical]);
        } else {
            $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';
            $stmt = $db->prepare($sql);
            $stmt->execute([$schema, $physical]);
        }
        $columns = [];
        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);
            }
            $nullable = (string)($row[$dm ? 'nullable' : 'is_nullable'] ?? '');
            $default = $row[$dm ? 'data_default' : 'column_default'] ?? null;
            $extra = (string)($row['extra'] ?? '');
            $columns[] = ['name' => strtolower((string)$row['column_name']),
                'type' => strtolower((string)$row['data_type']),
                'required_no_default' => $nullable === 'N' || $nullable === 'NO'
                    ? $default === null && stripos($extra, 'auto_increment') === false
                    : false,
                'default_present' => $default !== null,
                'auto_increment' => stripos($extra, 'auto_increment') !== false];
        }
        if (!$columns || count($columns) > 200) throw new RuntimeException('table missing/unbounded');
        $required = array_values(array_map(static function (array $c): string {
            return $c['name'] . ':' . $c['type'];
        }, array_filter($columns, static function (array $c): bool {
            return $c['required_no_default'];
        })));
        if ($dm) {
            $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'";
        } else {
            $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';
        }
        $triggers = $db->prepare($triggerSql);
        $triggers->execute([$schema, $physical]);
        $fks = $db->prepare($fkSql);
        $fks->execute([$schema, $physical]);
        $summary[$name] = ['columns' => count($columns),
            'required_no_default' => $required,
            'triggers' => (int)$triggers->fetchColumn(),
            'foreign_keys' => (int)$fks->fetchColumn(),
            'column_names' => array_column($columns, 'name')];
    }
    return $summary;
};
echo json_encode(['lane' => $lane,
    'ai_reference_columns' => $referenceColumns,
    'store' => $read($store, $storeTables,
        $lane === 'C' ? 'ZHCT_APP' : (string)$cfg['database'], $lane === 'C'),
    'ai' => $read($ai, $aiTables,
        $lane === 'C' ? 'AIZHCT_APP' : (string)$ac['database'], $lane === 'C')],
    JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE), PHP_EOL;
