/**
 * 键共振 Destiny · 案例分析模块（键·共振·纠缠 回测）
 * 隐去身份版命例 + 已发生事件；用键引擎回推「成局」是否被检出。
 * 依赖：kr_relations.js（KRRelations.scan，支持动态柱 extra）。
 * © 2026 Jason Li（泽森）
 */
(function (global) {
  "use strict";

  // 三个隐去身份的命局
  const CASES = {
    jia: {
      id: "jia", name: "案例一 · 甲日主男命",
      pillars: { year: "癸丑", month: "壬戌", day: "甲申", time: "庚午" },
      dayun: "丁巳(2016–2026) → 丙辰(2026–2036)",
      note: "甲木无根靠壬癸养；午火制庚；丑戌刑开库；戌午半合火；壬癸通根申丑。",
    },
    ding: {
      id: "ding", name: "案例二 · 丁日主男命",
      pillars: { year: "戊申", month: "壬戌", day: "丁丑", time: "辛丑" },
      dayun: "戊辰(逢2023)",
      note: "丁火微根戌中丁；双丑刑戌伤丁。字令地我 0.98；定体（＋广州）正格·身弱。",
    },
    wu: {
      id: "wu", name: "案例三 · 戊日主男命",
      pillars: { year: "癸酉", month: "丁巳", day: "戊戌", time: "壬子" },
      dayun: "戊申(天地合运)",
      note: "戊土坐戌（火土两旺）；时支子水为最后水气。",
    },
  };

  // 事件回测：dynamics=加入的动态柱；expect=文档所述应检出的成局
  const EVENTS = [
    {
      caseId: "jia", title: "2003 癸未年秋 · 跨国迁徙",
      dynamics: [{ label: "流年", gz: "癸未" }, { label: "流月", gz: "庚申" }],
      expect: [{ cls: "冲", chars: ["丑", "未"] }, { cls: "同字共振", chars: ["癸", "癸"] }],
      toucang: "癸水同字共振", waiying: "地理切换 火土→金水",
      result: "水库开、当令金动，触发迁徙。",
    },
    {
      caseId: "jia", title: "2010 庚寅年 · 妻二胎流产",
      dynamics: [{ label: "流年", gz: "庚寅" }],
      expect: [{ cls: "三合局", chars: ["寅", "午", "戌"] }, { cls: "同字共振", chars: ["庚", "庚"] }],
      toucang: "庚金子星透干", waiying: "妻怀孕",
      result: "寅午戌三合火，火熔庚金 → 5 月流产。",
    },
    {
      caseId: "jia", title: "2016 丙申年 · 外父去世",
      dynamics: [{ label: "流年", gz: "丙申" }, { label: "流月", gz: "癸巳" }, { label: "流日", gz: "壬寅" }, { label: "流时", gz: "戊申" }],
      expect: [{ cls: "六合", chars: ["巳", "申"] }, { cls: "三刑", chars: ["寅", "巳", "申"] }, { cls: "同字共振", chars: ["壬", "壬"] }],
      toucang: "壬水透干", waiying: "南方火地（三重火）",
      result: "巳申合绊+寅巳申三刑 → 申中壬水气源断。",
    },
    {
      caseId: "jia", title: "2023 癸卯年 · 父去世＋兄换肾",
      dynamics: [{ label: "流年", gz: "癸卯" }, { label: "流月", gz: "乙卯" }],
      expect: [{ cls: "六合", chars: ["卯", "戌"] }, { cls: "同字共振", chars: ["癸", "癸"] }],
      toucang: "癸水透干（四重汇聚）", waiying: "父（戌中戊）＋兄（月干壬）",
      result: "癸浸戌土，父去；四重癸救壬，兄活。",
    },
    {
      caseId: "jia", title: "2026 丙午年 · 职业转换",
      dynamics: [{ label: "大运", gz: "丙辰" }, { label: "流年", gz: "丙午" }],
      expect: [{ cls: "冲", chars: ["辰", "戌"] }, { cls: "同字共振", chars: ["丙", "丙"] }],
      toucang: "双丙透干", waiying: "流动水职业、北向",
      result: "辰戌冲，壬水偏印闭绝，癸水仍在。",
    },
    {
      caseId: "ding", title: "2023 癸卯年 · 父去世＋换肾（大运戊辰）",
      dynamics: [{ label: "大运", gz: "戊辰" }, { label: "流年", gz: "癸卯" }],
      expect: [{ cls: "冲", chars: ["辰", "戌"] }],
      toucang: "—", waiying: "与甲命同步（同一流年不同键）",
      result: "辰戌冲 → 父体（戌）引动。",
    },
    {
      caseId: "wu", title: "2023-03-17 丑时 · 亡日",
      dynamics: [{ label: "大运", gz: "戊申" }, { label: "流年", gz: "癸卯" }, { label: "流月", gz: "乙卯" }, { label: "流日", gz: "己卯" }, { label: "流时", gz: "乙丑" }],
      expect: [
        { cls: "六合", chars: ["卯", "戌"] },
        { cls: "刑", chars: ["丑", "戌"] },
        { cls: "六合", chars: ["子", "丑"] },
        { cls: "天干五合", chars: ["戊", "癸"] },
        { cls: "天干五合", chars: ["丁", "壬"] },
        { cls: "三会方", chars: ["申", "酉", "戌"] },
      ],
      toucang: "八字全参与合化，最终归土", waiying: "三重卯木合戌 + 丑戌刑 + 子丑封水",
      result: "水气断绝，生命终结。",
    },
  ];

  function sameSet(a, b) {
    if (!a || !b || a.length !== b.length) return false;
    const sa = a.slice().sort().join(""), sb = b.slice().sort().join("");
    return sa === sb;
  }

  /** 回测单个事件：跑引擎，检查每个 expect 是否被检出 */
  function backtest(ev) {
    const R = global.KRRelations;
    const c = CASES[ev.caseId];
    const r = R.scan(c.pillars, { 木: 1, 火: 1, 土: 1, 金: 1, 水: 1 }, global.KRParams, ev.dynamics);
    const detected = r.keys;
    const checks = ev.expect.map(exp => {
      const hit = detected.find(k => k.cls === exp.cls && sameSet(k.chars, exp.chars));
      return { cls: exp.cls, chars: exp.chars.join(""), hit: !!hit, intensity: hit ? hit.intensity : null, note: hit ? hit.note : "" };
    });
    const pass = checks.every(c2 => c2.hit);
    return { event: ev, case: c, checks, pass, detected };
  }

  function runAll() {
    const results = EVENTS.map(backtest);
    const passed = results.filter(r => r.pass).length;
    return { results, passed, total: results.length };
  }

  global.KRCases = { CASES, EVENTS, backtest, runAll };
})(typeof window !== "undefined" ? window : globalThis);
