// tests/mockup-connector.test.ts
import { describe, it, expect } from 'vitest'
import { classifyConnectorViolations, segmentsOf } from '../scripts/audit-mockup-connector.mjs'

const BLUE = { type: 'SOLID', color: { r: 0.2, g: 0.64, b: 0.99 } }   // #33A4FD
const WHITE = { type: 'SOLID', color: { r: 1, g: 1, b: 1 } }
const GREEN = { type: 'SOLID', color: { r: 0.2, g: 0.67, b: 0.31 } }  // #33ab4f

function vec(data) { return { id: 'v1', type: 'VECTOR', strokes: [BLUE], strokeWeight: 2, vectorPaths: [{ data }] } }
function dot(fills, strokes) { return { id: 'd1', type: 'ELLIPSE', width: 6, height: 6, fills, strokes, strokeWeight: 2 } }

describe('segmentsOf', () => {
  it('flags a diagonal segment (Δx>4 && Δy>4)', () => {
    const segs = segmentsOf('M 0 0 L 100 80')
    expect(segs.some(s => s.diagonal)).toBe(true)
  })
  it('passes pure horizontal/vertical segments', () => {
    const segs = segmentsOf('M 0 8 L 100 8 M 100 8 L 100 60')
    expect(segs.every(s => !s.diagonal)).toBe(true)  // none diagonal
    expect(segs.some(s => s.diagonal)).toBe(false)
  })
})

describe('classifyConnectorViolations', () => {
  const trigger = { id: 'btn', absoluteBoundingBox: { x: 100, y: 100, width: 40, height: 20 } }
  const target = { id: 'tgt', absoluteBoundingBox: { x: 400, y: 100, width: 60, height: 20 } }
  const okArrow = {
    id: 'g1', fromCanvas: { x: 140, y: 110 }, tipCanvas: { x: 402, y: 110 },
    from: { triggerElemId: 'btn' }, to: { targetElemId: 'tgt' },
    groupChildren: [dot([WHITE], [BLUE]), vec('M 0 8 L 260 8 M 252 0 L 260 8 L 252 16')],
  }
  const index = { btn: trigger, tgt: target }

  it('passes a compliant arrow', () => {
    const r = classifyConnectorViolations({ arrows: [okArrow] }, index)
    expect(r.missing).toBe(false)
    expect(r.orthogonal).toHaveLength(0)
    expect(r.anchoring).toHaveLength(0)
    expect(r.color).toHaveLength(0)
  })
  it('flags start dot not anchored on trigger bbox (card-edge LINE)', () => {
    const bad = { ...okArrow, fromCanvas: { x: 300, y: 110 } }   // 远离 btn bbox
    const r = classifyConnectorViolations({ arrows: [bad] }, index)
    expect(r.anchoring.map(a => a.end)).toContain('start')
  })
  it('flags green stroke on the connector (C4)', () => {
    const bad = { ...okArrow, groupChildren: [dot([WHITE], [GREEN]), vec('M 0 8 L 260 8')] }
    const r = classifyConnectorViolations({ arrows: [bad] }, index)
    expect(r.color.length).toBeGreaterThan(0)
  })
  it('flags hollow start dot (fills empty)', () => {
    const bad = { ...okArrow, groupChildren: [dot([], [BLUE]), vec('M 0 8 L 260 8')] }
    const r = classifyConnectorViolations({ arrows: [bad] }, index)
    expect(r.color.length).toBeGreaterThan(0)
  })
  it('reports missing when reconnectMap absent', () => {
    const r = classifyConnectorViolations(null, index)
    expect(r.missing).toBe(true)
  })
})
