import { describe, it, expect } from 'vitest'
import {
  // @ts-expect-error — plain JS ESM audit script, no types
  findCoveredDecorations, isStrokeOnlyDecoration, strokeBands, OPAQUE_MIN,
} from '../scripts/audit-mockup-layer-order.mjs'

// 几何全部取自真实交付帧 `0054ib0nLmt27bC3QlGDl7` / `8062:6873`（LCD 选 R 页，2026-09-16 实测）。
// ⛔ 不是编的数：绿框 = 手画阶梯形连体边框（fills 隐藏、只有 2px INSIDE 绿描边），
// 高亮块 = 选中行底色。改前绿框在 z=7、高亮块在 z=8 ⇒ 高亮块把绿框上边线盖掉；
// 修法是把绿框 appendChild 到容器末尾（z=最大）。
const GREEN_OUTLINE = {
  id: '8062:7019', name: 'Combined Shape', type: 'BOOLEAN_OPERATION',
  strokeWeight: 2, strokeAlign: 'INSIDE',
  fills: [{ type: 'SOLID', visible: false, color: { r: 0.49, g: 0.83, b: 0.13 } }],
  strokes: [{ type: 'SOLID', color: { r: 0.49, g: 0.83, b: 0.13 } }],
  absoluteBoundingBox: { x: 740, y: 54.94782638549805, width: 434, height: 200 },
}
const HIGHLIGHT = {
  id: '8062:7021', name: 'Rectangle 4', type: 'RECTANGLE', strokeWeight: 0,
  fills: [{ type: 'SOLID', color: { r: 0.145, g: 0.145, b: 0.145 } }],
  strokes: [{ type: 'SOLID', visible: false }],
  absoluteBoundingBox: { x: 1043, y: 56.84782409667969, width: 127, height: 36.20000076293945 },
}
const LABEL = {
  id: '8062:7023', name: 'PM_X7L', type: 'TEXT',
  fills: [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }], strokes: [],
  absoluteBoundingBox: { x: 1076, y: 66.4, width: 64, height: 19 },
}

const container = (children: any[]) => ({
  id: '8062:7011', name: 'Content', type: 'FRAME', children,
})

describe('isStrokeOnlyDecoration — 谁算「描边装饰」', () => {
  it('must-hit：连体绿框（描边可见 + 填充隐藏）算装饰', () => {
    expect(isStrokeOnlyDecoration(GREEN_OUTLINE)).toBe(true)
  })

  it('🔴 阴性对照：有可见填充的高亮块 ⛔ 不算装饰（它是内容，不是轮廓）', () => {
    expect(isStrokeOnlyDecoration(HIGHLIGHT)).toBe(false)
  })

  it('🔴 阴性对照：没有描边的文字 ⛔ 不算装饰', () => {
    expect(isStrokeOnlyDecoration(LABEL)).toBe(false)
  })

  it('🔴 阴性对照：隐藏节点 ⛔ 不参与判定', () => {
    expect(isStrokeOnlyDecoration({ ...GREEN_OUTLINE, visible: false })).toBe(false)
  })

  it('🔴 阴性对照：裸 VECTOR（折线类）⛔ 不算装饰 —— 它的描边不贴 bbox 四边', () => {
    // 真实回归样本：流程连线 connector/password-to-connecting，box 1960×512，
    // 其箭头与端点圆点本就该画在线端之上；旧版把它判成 6 起假阳。
    const polyline = {
      ...GREEN_OUTLINE, id: '10386:846', name: 'connector/password-to-connecting',
      type: 'VECTOR', strokeWeight: 2,
      absoluteBoundingBox: { x: 0, y: 0, width: 1960, height: 512 },
    }
    expect(isStrokeOnlyDecoration(polyline)).toBe(false)
  })

  it('🔴 阴性对照：ELLIPSE ⛔ 不算装饰（圆的描边内切于 bbox，不贴边）', () => {
    expect(isStrokeOnlyDecoration({ ...GREEN_OUTLINE, type: 'ELLIPSE' })).toBe(false)
  })
})

describe('strokeBands — 边框带向内取 strokeWeight 宽', () => {
  it('四条边各一条带，宽度 = strokeWeight（INSIDE）', () => {
    const bands = strokeBands(GREEN_OUTLINE.absoluteBoundingBox, 2)
    expect(bands.map((b: any) => b.edge)).toEqual(['top', 'bottom', 'left', 'right'])
    expect(bands[0]).toMatchObject({ edge: 'top', height: 2, width: 434 })
    expect(bands[2]).toMatchObject({ edge: 'left', width: 2, height: 200 })
  })
})

describe('findCoveredDecorations — 两臂（真实交付帧实测几何）', () => {
  it('🔴 must-hit：绿框在高亮块之下（改前 z=7 vs z=8）⇒ 上边线被盖，报红', () => {
    const doc = container([GREEN_OUTLINE, HIGHLIGHT, LABEL])
    const { findings, checkedDecorations } = findCoveredDecorations(doc)
    expect(checkedDecorations).toBe(1)
    expect(findings).toHaveLength(1)
    expect(findings[0].edges).toContain('top')
    expect(findings[0].decoName).toBe('Combined Shape')
    expect(findings[0].coverName).toBe('Rectangle 4')
    // (1170−1043) × 0.1 = 12.7 —— 与手算、与渲染图绿像素 +126 三方吻合
    expect(findings[0].area).toBeCloseTo(12.7, 1)
  })

  it('✅ 修好后：绿框移到容器末尾（最上层）⇒ 0 findings', () => {
    const doc = container([HIGHLIGHT, LABEL, GREEN_OUTLINE])
    const { findings, checkedDecorations } = findCoveredDecorations(doc)
    expect(checkedDecorations).toBe(1)
    expect(findings).toHaveLength(0)
  })

  it('🔴 阴性对照：高亮块离边线 2px 以上（原稿 8062:8004 的 y=644.9）⇒ 不报', () => {
    // 这是我第一次选错的「阳性样本」—— 它其实本来就没压住，闸判绿是对的。
    const far = { ...HIGHLIGHT, absoluteBoundingBox: { ...HIGHLIGHT.absoluteBoundingBox, y: 58.9 } }
    const doc = container([GREEN_OUTLINE, far])
    expect(findCoveredDecorations(doc).findings).toHaveLength(0)
  })

  it('🔴 阴性对照：半透明填充 ⛔ 不算遮挡（叠色是合法手法）', () => {
    const sheer = { ...HIGHLIGHT, fills: [{ type: 'SOLID', opacity: OPAQUE_MIN - 0.2, color: { r: 0, g: 0, b: 0 } }] }
    const doc = container([GREEN_OUTLINE, sheer])
    expect(findCoveredDecorations(doc).findings).toHaveLength(0)
  })

  it('🔴 阴性对照：覆盖块排在装饰**之前**（在它下层）⇒ 不报', () => {
    const doc = container([HIGHLIGHT, GREEN_OUTLINE])
    expect(findCoveredDecorations(doc).findings).toHaveLength(0)
  })

  it('🔴 阴性对照：填充完全落在边框带以内（不碰边线）⇒ 不报', () => {
    const inner = {
      ...HIGHLIGHT,
      absoluteBoundingBox: { x: 800, y: 100, width: 100, height: 40 },
    }
    const doc = container([GREEN_OUTLINE, inner])
    expect(findCoveredDecorations(doc).findings).toHaveLength(0)
  })

  it('分母诚实：扫描面里没有描边装饰时 checkedDecorations = 0（调用方须标未验）', () => {
    const doc = container([HIGHLIGHT, LABEL])
    expect(findCoveredDecorations(doc).checkedDecorations).toBe(0)
  })
})
