#!/usr/bin/env node
/**
 * rcl (教学版 CLI, package: rcl-demo)
 * 道風悠遊科技有限公司 · RCL Learn & Developer Hub
 *
 * 说明：本 CLI 与 Hub Playground 中的 Demo 适配器同源，执行的是
 * RCL 源码的结构化静态分析（结构面覆盖 + 4R 检查 + IR 概要），
 * 不是官方闭源编译器。输出的 authenticity 恒为 "demo-simulated"。
 */
import { readFileSync, existsSync } from "node:fs";
import { createHash } from "node:crypto";
import path from "node:path";

const CLI_VERSION = "0.94.0-alpha.1+demo.1";
const RCL_VERSION = "rcl-0.94.0-alpha.1";
const DOCS_VERSION = "docs-0.94.0-alpha.1";
const AUTHENTICITY = "demo-simulated";

const FACE_KEYS = [
  "identity","boundary","state","time","causality","constraint","capability","intent",
  "contract","resource","actor","channel","event","policy","risk","evidence",
  "observability","lifecycle","dependency","compensation","authority","consistency",
  "adaptation","termination",
];

const R4 = ["reversible","recoverable","reconcilable","responsible"];

function parse(src) {
  const lines = src.split(/\r?\n/);
  const blocks = [];
  const faces = new Set();
  const r4 = new Set();
  let decl = null;
  lines.forEach((raw, i) => {
    const line = raw.trim();
    if (!line || line.startsWith("//") || line.startsWith("#")) return;
    const m = line.match(/^([a-zA-Z_][\w.-]*)\s+([\w.:-]+)?\s*\{?$/);
    if (m) blocks.push({ keyword: m[1], name: m[2] ?? null, line: i + 1 });
    if (/^reality\s+/.test(line)) decl = line;
    for (const f of FACE_KEYS) if (new RegExp(`(^|[^\\w])${f}([^\\w]|$)`, "i").test(line)) faces.add(f);
    for (const r of R4) if (new RegExp(r, "i").test(line)) r4.add(r);
  });
  return { lines, blocks, faces: [...faces], r4: [...r4], decl };
}

function analyze(src, file) {
  const { lines, blocks, faces, r4, decl } = parse(src);
  const diagnostics = [];
  if (!decl) diagnostics.push({ code: "RCL-P101", severity: "error", message: "缺少 reality 声明：文件必须以 reality <名称> 开始。" });
  const missing = R4.filter((r) => !r4.includes(r));
  const codeByR = { reversible: "RCL-R201", recoverable: "RCL-R202", reconcilable: "RCL-R203", responsible: "RCL-R204" };
  for (const m of missing) {
    diagnostics.push({ code: codeByR[m], severity: "error", message: `4R 缺口：未声明 ${m} 策略。` });
  }
  if (faces.length < 6) {
    diagnostics.push({ code: "RCL-S301", severity: "warning", message: `结构面覆盖偏低（${faces.length}/24），建议补齐关键结构面。` });
  }
  const braces = (src.match(/\{/g) || []).length - (src.match(/\}/g) || []).length;
  if (braces !== 0) diagnostics.push({ code: "RCL-P102", severity: "error", message: `花括号不平衡（差值 ${braces}）。` });

  const ok = diagnostics.every((d) => d.severity !== "error");
  return {
    file, authenticity: AUTHENTICITY, cliVersion: CLI_VERSION,
    rclVersion: RCL_VERSION, docsVersion: DOCS_VERSION,
    ok, diagnostics,
    ir: {
      nodes: blocks.length,
      lines: lines.length,
      declaration: decl,
      blocks: blocks.map((b) => `${b.keyword}${b.name ? " " + b.name : ""}@L${b.line}`),
    },
    faces: { covered: faces, coveredCount: faces.length, total: 24 },
    robust: {
      declared: r4, missing,
      certificate: ok ? `4R-CERT/${createHash("sha256").update(src).digest("hex").slice(0, 16)}` : null,
    },
  };
}

function readSource(file) {
  if (!file) { console.error("用法: rcl <check|run|robust> <file.rcl>"); process.exit(2); }
  const p = path.resolve(process.cwd(), file);
  if (!existsSync(p)) { console.error(`找不到文件: ${p}`); process.exit(2); }
  return readFileSync(p, "utf8");
}

function printReport(r, mode) {
  const tag = r.ok ? "PASS" : "FAIL";
  console.log(`rcl ${mode} · ${r.file}`);
  console.log(`  版本: ${r.rclVersion} / 文档: ${r.docsVersion} / CLI: ${r.cliVersion}`);
  console.log(`  执行真实性: ${r.authenticity}（教学版静态分析，非官方编译结论）`);
  console.log(`  IR 节点: ${r.ir.nodes} · 结构面覆盖: ${r.faces.coveredCount}/24`);
  if (mode !== "check") {
    console.log(`  4R 已声明: ${r.robust.declared.join(", ") || "无"}`);
    console.log(`  4R 缺口: ${r.robust.missing.join(", ") || "无"}`);
    console.log(`  4R 证书: ${r.robust.certificate ?? "未签发"}`);
  }
  for (const d of r.diagnostics) console.log(`  [${d.severity.toUpperCase()}] ${d.code} ${d.message}`);
  console.log(`  结果: ${tag}`);
  return r.ok ? 0 : 1;
}

const [cmd, ...rest] = process.argv.slice(2);
const json = rest.includes("--json");
const file = rest.find((a) => !a.startsWith("-"));

switch (cmd) {
  case undefined:
  case "-h":
  case "--help":
    console.log(`rcl (教学版 CLI ${CLI_VERSION})

命令:
  rcl --version              输出 CLI 与绑定的 RCL / 文档版本
  rcl doctor                 检查运行环境
  rcl check <file.rcl>       语法与结构面检查
  rcl run <file.rcl>         结构化推导（Demo 适配器）
  rcl robust <file.rcl>      4R 全局现实鲁棒核检查
  rcl sha256 <file>          计算文件 SHA-256（用于下载校验）
选项:
  --json                     以 JSON 输出结果`);
    break;
  case "--version":
  case "-v":
    console.log(`rcl ${CLI_VERSION}\nrcl-language ${RCL_VERSION}\ndocs ${DOCS_VERSION}\nauthenticity ${AUTHENTICITY}`);
    break;
  case "doctor": {
    const major = Number(process.versions.node.split(".")[0]);
    const okNode = major >= 18;
    console.log(`rcl doctor
  Node.js         ${process.versions.node} ${okNode ? "OK" : "需要 >= 18"}
  平台            ${process.platform}/${process.arch}
  CLI             ${CLI_VERSION}
  适配器          demo-static-analyzer (${AUTHENTICITY})
  绑定文档        ${DOCS_VERSION}
  结果            ${okNode ? "PASS" : "FAIL"}`);
    process.exit(okNode ? 0 : 1);
  }
  case "sha256": {
    const p = path.resolve(process.cwd(), file ?? "");
    if (!existsSync(p)) { console.error(`找不到文件: ${p}`); process.exit(2); }
    console.log(`${createHash("sha256").update(readFileSync(p)).digest("hex")}  ${file}`);
    break;
  }
  case "check":
  case "run":
  case "robust": {
    const src = readSource(file);
    const r = analyze(src, file);
    if (json) { console.log(JSON.stringify(r, null, 2)); process.exit(r.ok ? 0 : 1); }
    process.exit(printReport(r, cmd));
  }
  default:
    console.error(`未知命令: ${cmd}（运行 rcl --help）`);
    process.exit(2);
}
