import { describe, expect, it } from 'vitest'
import * as allIcons from './icon-definitions.js'
import type { IconCategory } from './icon-types.js'

const iconEntries = Object.entries(allIcons)

const validCategories: IconCategory[] = ['Actions', 'Navigation', 'Status', 'Content', 'UI', 'Common']

describe('Icon definitions', () => {
  it('should export at least 100 icons', () => {
    expect(iconEntries.length).toBeGreaterThanOrEqual(100)
  })

  describe.each(iconEntries)('%s', (_name, icon) => {
    it('should have a paths array with at least one path', () => {
      expect(Array.isArray(icon.paths)).toBe(true)
      expect(icon.paths.length).toBeGreaterThanOrEqual(1)
    })

    it('should have non-empty d attributes on all paths', () => {
      for (const path of icon.paths) {
        expect(typeof path.d).toBe('string')
        expect(path.d.length).toBeGreaterThan(0)
      }
    })

    it('should have a valid style if specified', () => {
      if (icon.style !== undefined) {
        expect(['fill', 'stroke']).toContain(icon.style)
      }
    })

    it('should have a valid viewBox format if specified', () => {
      if (icon.viewBox !== undefined) {
        expect(icon.viewBox).toMatch(/^\d+\s+\d+\s+\d+\s+\d+$/)
      }
    })

    it('should have a positive strokeWidth if specified', () => {
      if (icon.strokeWidth !== undefined) {
        expect(icon.strokeWidth).toBeGreaterThan(0)
      }
    })

    it('should have valid fillRule on paths if specified', () => {
      for (const path of icon.paths) {
        if (path.fillRule !== undefined) {
          expect(['evenodd', 'nonzero']).toContain(path.fillRule)
        }
      }
    })

    it('should have a non-empty name', () => {
      expect(typeof icon.name).toBe('string')
      expect(icon.name!.length).toBeGreaterThan(0)
    })

    it('should have a non-empty description', () => {
      expect(typeof icon.description).toBe('string')
      expect(icon.description!.length).toBeGreaterThan(0)
    })

    it('should have at least one keyword', () => {
      expect(Array.isArray(icon.keywords)).toBe(true)
      expect(icon.keywords!.length).toBeGreaterThanOrEqual(1)
      for (const kw of icon.keywords!) {
        expect(typeof kw).toBe('string')
        expect(kw.length).toBeGreaterThan(0)
      }
    })

    it('should have a valid category', () => {
      expect(validCategories).toContain(icon.category)
    })
  })

  it('should not have duplicate path data across different icons', () => {
    const pathSignatures = new Map<string, string>()
    for (const [name, icon] of iconEntries) {
      const signature = icon.paths.map((p) => p.d).join('|')
      const existing = pathSignatures.get(signature)
      if (existing) {
        // Allow outline/fill variants of the same shape (e.g. star / starOutline, heart / heartOutline)
        const isVariantPair =
          (name.includes('Outline') && existing === name.replace('Outline', '')) ||
          (existing.includes('Outline') && name === existing.replace('Outline', ''))
        if (!isVariantPair) {
          expect.fail(`Icon "${name}" has identical path data to "${existing}"`)
        }
      }
      pathSignatures.set(signature, name)
    }
  })
})
