// tests/mockup-handoff-evidence.test.ts
//
// F62-a 报告防伪：handoff gate 从"正则找 Integrity audit 文本"（可手打伪造）升级为
// "解析 handoff 里引用的 conformance report 文件路径 → 校验文件存在 + 每个子审计 exitCode=0
//  + timestamp 在时效窗口内"。校验对象是脚本 writeFileSync 产出的结构化 JSON，不是可手打的文本。
// 依赖注入 readReport / now 保持 checkHandoffEvidence 为纯函数、无 fs/clock 副作用。
import { describe, it, expect } from 'vitest'
import { checkHandoffEvidence } from '../scripts/audit-mockup-handoff-evidence.mjs'

const NOW = Date.parse('2026-07-10T12:00:00.000Z')
const HOUR = 3600 * 1000

// 一份合法 report：脚本产出的结构化 JSON，全子审计 exitCode=0
const freshPassReport = {
  fileKey: 'abc123',
  nodeIds: ['456:789'],
  subAudits: [
    { key: 'integrity', exitCode: 0 },
    { key: 'colors', exitCode: 0 },
    { key: 'overlap', exitCode: 0 },
  ],
  timestamp: '2026-07-10T11:30:00.000Z', // 30min 前，新鲜
  figmaLastModified: null,
  ok: true,
}

const handoffWithReport = `
<!-- mockup-handoff -->
## Handoff
Rule checklist: [M0 ✅ / M23 ✅]
Conformance report: docs/handoffs/.conformance/abc123-456_789-20260710T113000Z.json
`

// 反例：老式手打文本（无 report 文件引用）——防伪核心：这种再也不能过闸
const handoffHandTypedText = `
<!-- mockup-handoff -->
## Handoff
Rule checklist: [M0 ✅ / M23 ✅]
\`\`\`
✅ mockup-conformance: all sub-audits passed
Integrity audit: I1=pass / I2=overlap-gap 12px / I3=overflow-count 0 / I4=orphan-count 0
\`\`\`
`

const notHandoff = `# 普通文档\n没有 mockup-handoff 标记`

// plan/conventions 文档：提到 "Rule checklist:" 但无 <!-- mockup-handoff --> 标记
const docMentioningRuleChecklist = `
# mockup-conventions.md
设计交付时请填写 Rule checklist: [M0 / M1 ...] 并跑 pnpm audit:mockup-conformance --report。
这只是规范说明文档，不是真实 handoff。
`

// 规范文档在散文/反引号内提及标记（mockup-conventions.md:2437 实况）——不是真 handoff
const docMentioningMarkerInProse = `
# mockup-conventions.md §M-DISCIPLINE.SYNC
3. handoff 反映同步结果 —— 顶部加 \`<!-- mockup-handoff -->\` 标记 + 一行 \`Conformance report: <path>\`。
这是规则说明，不该被守门当成真 handoff 拦截。
`

// 模板在引用块里展示标记（_handoff.template.md:27 实况）——占位示例，不是真 handoff
const templateMarkerInBlockquote = `
# Handoff 模板
mockup 交付时在顶部放：
> <!-- mockup-handoff -->
> Conformance report: docs/handoffs/.conformance/<fileKey>-<nodes>-<timestamp>.json
`

// 注入的 readReport：按路径返回预置 report 对象，未知路径返回 null（= 文件不存在）
const makeReader = (map) => (path) => (path in map ? map[path] : null)
const REPORT_PATH = 'docs/handoffs/.conformance/abc123-456_789-20260710T113000Z.json'

describe('checkHandoffEvidence — report-path anti-forgery', () => {
  it('ignores a non-handoff doc', () => {
    const r = checkHandoffEvidence(notHandoff, { now: NOW })
    expect(r.isHandoff).toBe(false)
    expect(r.ok).toBe(true)
  })

  it('ignores a doc mentioning "Rule checklist:" without the <!-- mockup-handoff --> marker', () => {
    const r = checkHandoffEvidence(docMentioningRuleChecklist, { now: NOW })
    expect(r.isHandoff).toBe(false)
    expect(r.ok).toBe(true)
  })

  it('ignores a convention doc that mentions the marker inline in prose/backticks (not its own line)', () => {
    const r = checkHandoffEvidence(docMentioningMarkerInProse, { now: NOW })
    expect(r.isHandoff).toBe(false)
    expect(r.ok).toBe(true)
  })

  it('ignores a template that shows the marker inside a blockquote example', () => {
    const r = checkHandoffEvidence(templateMarkerInBlockquote, { now: NOW })
    expect(r.isHandoff).toBe(false)
    expect(r.ok).toBe(true)
  })

  it('passes a handoff that references a fresh, all-pass report file', () => {
    const r = checkHandoffEvidence(handoffWithReport, {
      readReport: makeReader({ [REPORT_PATH]: freshPassReport }),
      now: NOW,
    })
    expect(r.isHandoff).toBe(true)
    expect(r.reportPath).toBe(REPORT_PATH)
    expect(r.ok).toBe(true)
  })

  it('FAILS a handoff whose referenced report file does not exist', () => {
    const r = checkHandoffEvidence(handoffWithReport, {
      readReport: makeReader({}), // 路径不在 map → null → 文件不存在
      now: NOW,
    })
    expect(r.isHandoff).toBe(true)
    expect(r.reportFound).toBe(false)
    expect(r.ok).toBe(false)
  })

  it('FAILS a handoff whose report has a sub-audit exitCode != 0', () => {
    const failing = { ...freshPassReport, subAudits: [{ key: 'integrity', exitCode: 0 }, { key: 'overlap', exitCode: 1 }] }
    const r = checkHandoffEvidence(handoffWithReport, {
      readReport: makeReader({ [REPORT_PATH]: failing }),
      now: NOW,
    })
    expect(r.reportPassed).toBe(false)
    expect(r.ok).toBe(false)
  })

  it('FAILS a handoff whose report timestamp is stale (older than the freshness window)', () => {
    const stale = { ...freshPassReport, timestamp: '2026-07-08T11:30:00.000Z' } // 2 天前
    const r = checkHandoffEvidence(handoffWithReport, {
      readReport: makeReader({ [REPORT_PATH]: stale }),
      now: NOW,
      maxAgeMs: 24 * HOUR,
    })
    expect(r.fresh).toBe(false)
    expect(r.ok).toBe(false)
  })

  it('FAILS a handoff that only hand-types the old Integrity-audit text (no report file reference)', () => {
    // 防伪核心断言：编造的文本行不再能过闸——没有 report 路径引用即失败
    const r = checkHandoffEvidence(handoffHandTypedText, {
      readReport: makeReader({ [REPORT_PATH]: freshPassReport }),
      now: NOW,
    })
    expect(r.isHandoff).toBe(true)
    expect(r.reportPath).toBe(null)
    expect(r.ok).toBe(false)
  })
})
