#!/usr/bin/env node
/**
 * 「靜態租戶字串不得用於資料面過濾」機械閘的**執行殼**（Arcrun#108）。
 *
 * 規則本體（純函式、零 node 相依）在 `tenant-source-rules.mjs`——拆開的理由是
 * **這道閘自己要能被測試**：Workers runtime 的 vitest 沒有 node:fs，規則若和走檔案系統的
 * 程式碼綁在一起就 import 不動，測試也就寫不出來（當晚有一道閘連讀自己的原始碼都擋，
 * 結果沒人驗得了它會不會誤攔）。現在 tests/tenant-gate.test.ts 直接餵字串驗規則。
 *
 * 用法：
 *   node scripts/check-tenant-source.mjs [projectRoot]   # 掃 src/，有違規 → exit 1
 *   node scripts/check-tenant-source.mjs --stdin <相對路徑>  # 從 stdin 讀「即將寫入的內容」
 *   npm run check:tenant
 *
 * `--stdin` 是給 `.claude/hooks/pre-write-guard.sh`（規則 8.1）用的：在檔案**還沒寫下去之前**
 * 就擋，這樣違規根本進不了工作區。Edit 只給片段也沒關係——規則是逐行的，正好只看新寫的那幾行。
 */
import { readFileSync, readdirSync, statSync } from 'node:fs';
import { join, relative, sep } from 'node:path';
import { fileURLToPath } from 'node:url';
import { scanSource } from './tenant-source-rules.mjs';

/** 遞迴列出目錄下的 .ts 檔（相對 root 的路徑）。 */
function listTsFiles(root, dir = root, out = []) {
  for (const name of readdirSync(dir)) {
    const full = join(dir, name);
    if (statSync(full).isDirectory()) listTsFiles(root, full, out);
    else if (name.endsWith('.ts')) out.push(relative(root, full));
  }
  return out;
}

/** 掃整個 cypher-executor/src。回傳違規清單。 */
export function scanProject(projectRoot) {
  const srcRoot = join(projectRoot, 'src');
  const all = [];
  for (const rel of listTsFiles(projectRoot, srcRoot)) {
    const relPosix = rel.split(sep).join('/');
    all.push(
      ...scanSource(relPosix, readFileSync(join(projectRoot, rel), 'utf8')).map((v) => ({
        ...v,
        file: relPosix,
      })),
    );
  }
  return all;
}

/** stdin 模式：讀「即將寫入的內容」，印違規、有違規 → exit 1。 */
async function runStdin(relPath) {
  const chunks = [];
  for await (const chunk of process.stdin) chunks.push(chunk);
  const violations = scanSource(relPath, Buffer.concat(chunks).toString('utf8'));
  if (violations.length === 0) return 0;
  for (const v of violations) {
    console.error(`[${v.rule}] ${relPath}（新寫入的第 ${v.line} 行）：${v.text}`);
    console.error(`  → ${v.message}`);
  }
  return 1;
}

if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
  if (process.argv[2] === '--stdin') {
    process.exit(await runStdin(process.argv[3] ?? 'src/unknown.ts'));
  }
  const projectRoot = process.argv[2] ?? process.cwd();
  const violations = scanProject(projectRoot);
  if (violations.length === 0) {
    console.log('✓ 租戶來源檢查通過：資料面 owner_id 全部來自 src/lib/tenant.ts');
    process.exit(0);
  }
  console.error('❌ 租戶來源檢查失敗（Arcrun#108 的閘）\n');
  for (const v of violations) {
    console.error(`  [${v.rule}] ${v.file}:${v.line}`);
    console.error(`        ${v.text}`);
    console.error(`        → ${v.message}\n`);
  }
  process.exit(1);
}
