import { describe, expect, it } from 'vitest'

import {
  contrastRatio,
  contrastText,
  hexToRgb,
  isLight,
  meetsWcagAA,
  relativeLuminance,
} from '../contrast'

describe('hexToRgb', () => {
  it('parses 6-digit hex with leading #', () => {
    expect(hexToRgb('#FFFFFF')).toEqual([255, 255, 255])
    expect(hexToRgb('#000000')).toEqual([0, 0, 0])
    expect(hexToRgb('#FF7F00')).toEqual([255, 127, 0])
  })

  it('parses lowercase hex without #', () => {
    expect(hexToRgb('037493')).toEqual([3, 116, 147])
    expect(hexToRgb('a8dfff')).toEqual([168, 223, 255])
  })

  it('parses 3-digit shorthand', () => {
    expect(hexToRgb('#FFF')).toEqual([255, 255, 255])
    expect(hexToRgb('#000')).toEqual([0, 0, 0])
    expect(hexToRgb('#F70')).toEqual([255, 119, 0])
  })

  it('throws on invalid hex', () => {
    expect(() => hexToRgb('#12345')).toThrow()
    expect(() => hexToRgb('not a hex')).toThrow()
    expect(() => hexToRgb('')).toThrow()
  })
})

describe('isLight', () => {
  it('returns true for canvas/white', () => {
    expect(isLight('#FFFFFF')).toBe(true)
    expect(isLight('#FAFAFA')).toBe(true)
  })

  it('returns false for the DCT Petrol primary', () => {
    expect(isLight('#037493')).toBe(false)
  })

  it('returns true for the soft Petrol tint', () => {
    expect(isLight('#E0F2FF')).toBe(true)
    expect(isLight('#A8DFFF')).toBe(true)
  })

  it('returns false for saturated reds / black', () => {
    expect(isLight('#000000')).toBe(false)
    expect(isLight('#D93025')).toBe(false)
  })
})

describe('contrastText', () => {
  it('returns the dark token on light backgrounds', () => {
    expect(contrastText('#FFFFFF')).toBe('#353A41')
    expect(contrastText('#E0F2FF')).toBe('#353A41')
    expect(contrastText('#C8E6C9')).toBe('#353A41')
  })

  it('returns the light token on dark backgrounds', () => {
    expect(contrastText('#037493')).toBe('#FFFFFF')
    expect(contrastText('#7E1F81')).toBe('#FFFFFF')
    expect(contrastText('#000000')).toBe('#FFFFFF')
  })

  it('honours custom dark / light tokens', () => {
    expect(contrastText('#FFFFFF', { dark: '#222', light: '#EEE' })).toBe('#222')
    expect(contrastText('#000000', { dark: '#222', light: '#EEE' })).toBe('#EEE')
  })
})

describe('relativeLuminance + contrastRatio', () => {
  it('white has luminance 1', () => {
    expect(relativeLuminance('#FFFFFF')).toBeCloseTo(1, 3)
  })

  it('black has luminance 0', () => {
    expect(relativeLuminance('#000000')).toBeCloseTo(0, 3)
  })

  it('black on white reaches the spec ratio 21', () => {
    expect(contrastRatio('#000000', '#FFFFFF')).toBeCloseTo(21, 1)
  })

  it('is symmetric (fg/bg order does not matter)', () => {
    const a = contrastRatio('#037493', '#FFFFFF')
    const b = contrastRatio('#FFFFFF', '#037493')
    expect(a).toBeCloseTo(b, 6)
  })
})

describe('meetsWcagAA', () => {
  it('AA normal-text threshold is 4.5:1', () => {
    expect(meetsWcagAA('#000000', '#FFFFFF')).toBe(true)
    expect(meetsWcagAA('#FFFFFF', '#000000')).toBe(true)
    expect(meetsWcagAA('#888888', '#999999')).toBe(false)
  })

  it('AA large-text threshold is 3:1 when largeText=true', () => {
    // Mid-grey on white: ~3.95:1 — fails normal AA, passes large-text AA.
    expect(meetsWcagAA('#888888', '#FFFFFF')).toBe(false)
    expect(meetsWcagAA('#888888', '#FFFFFF', { largeText: true })).toBe(true)
  })
})

describe('DCT palette — WCAG-AA contrast (KAR-630 DoD)', () => {
  // contrastText is the text-token contract: dark #353A41 on light fills,
  // white #FFFFFF on dark fills. Both pairings must hit AA normal-text.
  const DCT_FILLS = {
    'Primary (Petrol)':       { bg: '#037493', expectedText: '#FFFFFF' },
    'Primary-Hover':          { bg: '#035970', expectedText: '#FFFFFF' },
    'Primary-Tint':           { bg: '#A8DFFF', expectedText: '#353A41' },
    'Primary-Soft':           { bg: '#E0F2FF', expectedText: '#353A41' },
    'Canvas':                 { bg: '#FFFFFF', expectedText: '#353A41' },
    'Status-Red strong':      { bg: '#F8BBD0', expectedText: '#353A41' },
    'Status-Red soft':        { bg: '#FCE4EC', expectedText: '#353A41' },
    'Status-Yellow':          { bg: '#FFE082', expectedText: '#353A41' },
    'Status-Grey':            { bg: '#D7D8DA', expectedText: '#353A41' },
    'Status-Green':           { bg: '#C8E6C9', expectedText: '#353A41' },
    'Destructive':            { bg: '#D93025', expectedText: '#FFFFFF' },
  }

  it.each(Object.entries(DCT_FILLS))(
    'contrastText picks the AA-passing text token for %s',
    (_label, { bg, expectedText }) => {
      expect(contrastText(bg)).toBe(expectedText)
      expect(meetsWcagAA(expectedText, bg)).toBe(true)
    },
  )
})
