import { describe, it, expect } from 'vitest'
import {
  normalizeBoxShadow,
  extractCssVarValue,
  parseTextShorthand,
  auditStyleContract,
} from '../scripts/audit-style-contract.mjs'

// -----------------------------------------------------------------------------
// 纯函数单元测试 — 全部用注入 fixture，不读真实文件（真实数据由 CLI 跑）
// -----------------------------------------------------------------------------

describe('normalizeBoxShadow', () => {
  it('把 figma 的 `0px` 与 CSS 的 `0` 视为相等（含多层 + 换行 + 缩进）', () => {
    const figma = '0px 9px 28px 8px #0000000d, 0px 6px 16px 0px #00000014, 0px 3px 6px -4px #0000001f'
    const css = `
    0 9px 28px 8px #0000000d,
    0 6px 16px 0 #00000014,
    0 3px 6px -4px #0000001f`
    expect(normalizeBoxShadow(css)).toBe(normalizeBoxShadow(figma))
  })

  it('不会把 `10px` / `40px` 里的 0 误改', () => {
    expect(normalizeBoxShadow('0px 10px 40px 0px #000')).toBe('0 10px 40px 0 #000')
  })
})

describe('extractCssVarValue', () => {
  it('抽出多行 box-shadow 的完整值', () => {
    const css = `:root {
  --shadow-l2:
    0 9px 28px 8px #0000000d,
    0 6px 16px 0 #00000014;
  --other: 1px;
}`
    const v = extractCssVarValue(css, '--shadow-l2')
    expect(v).not.toBeNull()
    expect(normalizeBoxShadow(v!)).toBe('0 9px 28px 8px #0000000d, 0 6px 16px 0 #00000014')
  })

  it('token 不存在返回 null', () => {
    expect(extractCssVarValue(':root { --a: 1px; }', '--missing')).toBeNull()
  })
})

describe('parseTextShorthand', () => {
  it('解析 font shorthand 出 weight/size/lineHeight', () => {
    expect(parseTextShorthand('400 14px/21px var(--font-family-base)')).toEqual({
      fontWeight: 400,
      fontSize: 14,
      lineHeight: 21,
    })
  })
})

// ── auditStyleContract：核心比对（注入 figmaStyles 对象 + cssText 字符串）──

const CONSISTENT_CSS = `:root {
  --shadow-l2:
    0 9px 28px 8px #0000000d,
    0 6px 16px 0 #00000014;
  --text-style-body: 400 14px/21px var(--font-family-base);
}`

const CONSISTENT_STYLES = {
  effectStyles: {
    'L2 shadow': {
      cssBoxShadow: '0px 9px 28px 8px #0000000d, 0px 6px 16px 0px #00000014',
      canonicalToken: '--shadow-l2',
    },
    // background-blur 类：无 cssBoxShadow + 复合描述 token → 必须被跳过
    'Mask blur8 #000-60%': {
      cssBackdropFilter: 'blur(8px)',
      canonicalToken: '--mask-overlay (bg) + --mask-overlay-blur (filter)',
    },
  },
  textStyles: {
    'Roboto/14 body': {
      fontFamily: 'Roboto',
      fontWeight: 400,
      fontSize: 14,
      lineHeight: 21,
      canonicalToken: '--text-style-body',
    },
    // PingFang SC 变体：无 canonicalToken → 必须被跳过
    'Roboto/PingFang SC/14 body': {
      fontFamily: 'PingFang SC',
      fontWeight: 400,
      fontSize: 14,
      lineHeight: 21,
    },
  },
}

describe('auditStyleContract', () => {
  it('一致 → pass，且只 check 了带干净 canonicalToken 的 2 条', () => {
    const r = auditStyleContract(CONSISTENT_STYLES, CONSISTENT_CSS)
    expect(r.ok).toBe(true)
    expect(r.drifts).toEqual([])
    expect(r.checked).toBe(2)
  })

  it('shadow 值改一位 → fail', () => {
    const css = CONSISTENT_CSS.replace('0 9px 28px 8px', '0 9px 28px 7px')
    const r = auditStyleContract(CONSISTENT_STYLES, css)
    expect(r.ok).toBe(false)
    const d = r.drifts.find(x => x.token === '--shadow-l2')
    expect(d).toBeDefined()
    expect(d!.kind).toBe('effect')
  })

  it('textStyle fontSize 改 → fail', () => {
    const css = CONSISTENT_CSS.replace('400 14px/21px', '400 15px/21px')
    const r = auditStyleContract(CONSISTENT_STYLES, css)
    expect(r.ok).toBe(false)
    const d = r.drifts.find(x => x.token === '--text-style-body' && x.field === 'fontSize')
    expect(d).toBeDefined()
    expect(Number(d!.expected)).toBe(14)
    expect(Number(d!.actual)).toBe(15)
  })

  it('token 缺失（figma 有 canonicalToken 但 CSS 没声明）→ fail', () => {
    const styles = {
      effectStyles: {
        'L9 shadow': { cssBoxShadow: '0px 1px 1px 0px #000', canonicalToken: '--shadow-l9' },
      },
      textStyles: {},
    }
    const r = auditStyleContract(styles, ':root { --shadow-l2: 0 1px 1px 0 #000; }')
    expect(r.ok).toBe(false)
    expect(r.drifts[0].token).toBe('--shadow-l9')
  })
})
