import { describe, expect, it } from 'vitest'
import { assignProjectColor, assignProjectColors, oklabDeltaE } from './project-colors'

function circularStepDistance(hueA: number, hueB: number): number {
  const diff = Math.abs(hueA - hueB) % 360
  const deg = Math.min(diff, 360 - diff)
  return deg / 30 // 30° = 1 wheel step (12 hues)
}

describe('assignProjectColor', () => {
  it('assigns 12 distinct hues on the first rotation, each a wheel-unique hue', () => {
    const colors = Array.from({ length: 12 }, (_, i) => assignProjectColor(i))
    const hues = colors.map((c) => (c.source === 'wheel' ? c.hue : -1))
    expect(new Set(hues).size).toBe(12)
  })

  it('keeps consecutively-assigned hues at least 2 wheel steps apart', () => {
    const colors = Array.from({ length: 12 }, (_, i) => assignProjectColor(i))
    for (let i = 0; i < colors.length - 1; i++) {
      const a = colors[i]!
      const b = colors[i + 1]!
      if (a.source !== 'wheel' || b.source !== 'wheel') throw new Error('expected wheel color')
      expect(circularStepDistance(a.hue, b.hue)).toBeGreaterThanOrEqual(2)
    }
  })

  it('shifts lightness/chroma on the second rotation by >= 20 ΔE vs the same hue in rotation 0', () => {
    for (let i = 0; i < 12; i++) {
      const first = assignProjectColor(i)
      const second = assignProjectColor(i + 12)
      if (first.source !== 'wheel' || second.source !== 'wheel') throw new Error('expected wheel color')
      expect(second.wheelIndex).toBe(first.wheelIndex)
      expect(second.rotation).toBe(first.rotation + 1)
      expect(oklabDeltaE(first.hex, second.hex)).toBeGreaterThanOrEqual(20)
    }
  })

  it('uses a manual override from collector config passthrough instead of the wheel', () => {
    const overrides = { multideal: '#ff00aa' }
    const auto = assignProjectColor(0, overrides, 'zync')
    const overridden = assignProjectColor(1, overrides, 'multideal')
    expect(auto.source).toBe('wheel')
    expect(overridden).toEqual({ source: 'override', hex: '#ff00aa' })
  })
})

describe('assignProjectColors', () => {
  it('assigns colors positionally, honoring per-id overrides', () => {
    const result = assignProjectColors(['multideal', 'zync', 'press'], { zync: '#123456' })
    expect(result.multideal!.source).toBe('wheel')
    expect(result.zync).toEqual({ source: 'override', hex: '#123456' })
    expect(result.press!.source).toBe('wheel')
  })
})
