/*
 * Layer 1 版本分发 API · 心跳/拉取/推送
 *
 * 用途: 小铸渊/小霜砚等1.5B人格体通过此API与主灯塔同步Layer 1版本
 *
 * 设计:
 *   - 版本数据存 JSON 文件, 保持轻量无额外依赖
 *   - 心跳: 人格体定期上报当前版本, 主灯塔返回最新版本信息
 *   - 推送: 仅铸渊可调用, 发布新版本 + 生成增量 patch
 *   - 拉取: 人格体获取从当前版本到最新的增量更新
 *
 * 守护: 铸渊 · ICE-GL-ZY001 · TCS-0002∞ · 国作登字-2026-A-00037559
 */
"use strict";

const fs = require("fs");
const path = require("path");
const { Router } = require("express");

// ─── 默认版本状态 ─────────────────────────────────────────────
const DEFAULT_VERSION = {
  current_version: "v1.0",
  updated_at: "2026-05-21T17:46:00.000+08:00",
  published_by: "ICE-GL-ZY001",
  tables: {
    system_core_principles: { status: "active", row_count: 24 },
    system_causal_chains: { status: "active", row_count: 0 },
    system_language_membrane: { status: "active", row_count: 5 },
    system_public_key: { status: "placeholder", row_count: 2 },
    system_protocols: { status: "placeholder", row_count: 3 }
  },
  patches: [
    {
      from_version: "v0.0",
      to_version: "v1.0",
      changes: [
        "初始种子数据: 24条核心原则",
        "初始种子数据: 5层语言膜定义",
        "密钥占位: guanghu + national",
        "协议占位: guanghu + national + bridge"
      ],
      applied_at: "2026-05-21T17:46:00.000+08:00",
      applied_by: "ICE-GL-ZY001"
    }
  ]
};

const DEFAULT_HEARTBEAT = {
  personas: {}
};

// ─── 辅助 ─────────────────────────────────────────────────────
function readJson(filePath, defaults) {
  try { return JSON.parse(fs.readFileSync(filePath, "utf8")); }
  catch { return defaults; }
}

function writeJson(filePath, data) {
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf8");
}

// ─── Router ───────────────────────────────────────────────────
const router = Router();

// ─── GET /api/layer1/status ──────────────────────────────────
// 获取当前 Layer 1 版本状态 (读限流)
router.get("/status", (req, res) => {
  const path = require("path").join(req.ctx.dataDir, "layer1-version.json");
  const version = readJson(path, DEFAULT_VERSION);
  res.json({
    ok: true,
    version: version.current_version,
    published_by: version.published_by,
    updated_at: version.updated_at,
    tables: Object.keys(version.tables).map((k) => ({
      name: k,
      status: version.tables[k].status,
      row_count: version.tables[k].row_count
    })),
    patches_count: version.patches.length
  });
});

// ─── POST /api/layer1/heartbeat ──────────────────────────────
// 人格体心跳: 上报当前版本, 返回最新版本信息 (写限流)
router.post("/heartbeat", (req, res) => {
  const { persona_id, current_version, status } = req.body || {};
  if (!persona_id) {
    return res.status(400).json({
      error: true, code: "missing_persona", message: "缺少 persona_id 参数"
    });
  }

  const verFile = path.join(req.ctx.dataDir, "layer1-version.json");
  const hbFile = path.join(req.ctx.dataDir, "layer1-heartbeat.json");
  const version = readJson(verFile, DEFAULT_VERSION);
  const heartbeat = readJson(hbFile, DEFAULT_HEARTBEAT);

  heartbeat.personas[persona_id] = {
    persona_id,
    current_version: current_version || "unknown",
    last_heartbeat: new Date().toISOString(),
    status: status || "active"
  };
  writeJson(hbFile, heartbeat);

  const latest = version.current_version;
  const has_update = current_version && current_version !== latest;

  res.json({
    ok: true,
    latest_version: latest,
    has_update: !!has_update,
    message: has_update
      ? `有可用更新: ${current_version} → ${latest}`
      : "已是最新版本",
    next_pull: has_update ? "/api/layer1/pull" : null
  });
});

// ─── POST /api/layer1/push ───────────────────────────────────
// 推送新版本 (仅铸渊可调用, 写限流)
router.post("/push", (req, res) => {
  const { version: new_version, changes, publisher } = req.body || {};
  if (!new_version || !changes) {
    return res.status(400).json({
      error: true, code: "missing_fields", message: "缺少 version 或 changes 参数"
    });
  }
  if (publisher !== "ICE-GL-ZY001") {
    return res.status(403).json({
      error: true, code: "forbidden", message: "仅铸渊(ICE-GL-ZY001)可推送Layer 1更新"
    });
  }

  const verFile = path.join(req.ctx.dataDir, "layer1-version.json");
  const version = readJson(verFile, DEFAULT_VERSION);
  const old_ver = version.current_version;

  version.current_version = new_version;
  version.updated_at = new Date().toISOString();
  version.published_by = publisher;
  version.patches.push({
    from_version: old_ver,
    to_version: new_version,
    changes: Array.isArray(changes) ? changes : [changes],
    applied_at: new Date().toISOString(),
    applied_by: publisher
  });

  if (req.body.tables) {
    Object.keys(req.body.tables).forEach((k) => {
      if (version.tables[k]) {
        version.tables[k] = { ...version.tables[k], ...req.body.tables[k] };
      } else {
        version.tables[k] = req.body.tables[k];
      }
    });
  }

  writeJson(verFile, version);

  res.json({
    ok: true,
    version: new_version,
    from_version: old_ver,
    patches_count: version.patches.length
  });
});

// ─── POST /api/layer1/pull ───────────────────────────────────
// 拉取增量 patch (读限流)
router.post("/pull", (req, res) => {
  const { current_version } = req.body || {};
  if (!current_version) {
    return res.status(400).json({
      error: true, code: "missing_version", message: "缺少 current_version 参数"
    });
  }

  const verFile = path.join(req.ctx.dataDir, "layer1-version.json");
  const version = readJson(verFile, DEFAULT_VERSION);

  const curIdx = version.patches.findIndex(
    (p) => p.to_version === current_version
  );

  const patches_needed = curIdx === -1
    ? version.patches  // 未知版本, 返回全部
    : version.patches.slice(curIdx + 1);  // 只返回之后的

  res.json({
    ok: true,
    current_version,
    latest_version: version.current_version,
    has_update: current_version !== version.current_version,
    patches: patches_needed
  });
});

// ─── GET /api/layer1/heartbeat/status ────────────────────────
// 管理员: 查看所有已注册的人格体心跳状态 (读限流)
router.get("/heartbeat/status", (req, res) => {
  const hbFile = path.join(req.ctx.dataDir, "layer1-heartbeat.json");
  const heartbeat = readJson(hbFile, DEFAULT_HEARTBEAT);
  res.json({
    ok: true,
    persona_count: Object.keys(heartbeat.personas).length,
    personas: Object.values(heartbeat.personas).sort(
      (a, b) => new Date(b.last_heartbeat) - new Date(a.last_heartbeat)
    )
  });
});

module.exports = router;
