import { describe, it, expect, vi, beforeEach } from 'vitest';
import {
  hexToHSL,
  hslToHex,
  generateColorPalette,
  applyColorPalette,
  applyBrandColors,
  defaultColorPalette,
} from '../colorUtils';

describe('colorUtils', () => {
  describe('hexToHSL', () => {
    it('converts pure red correctly', () => {
      const result = hexToHSL('#ff0000');
      expect(result.h).toBeCloseTo(0, 0);
      expect(result.s).toBeCloseTo(100, 0);
      expect(result.l).toBeCloseTo(50, 0);
    });

    it('converts pure green correctly', () => {
      const result = hexToHSL('#00ff00');
      expect(result.h).toBeCloseTo(120, 0);
      expect(result.s).toBeCloseTo(100, 0);
      expect(result.l).toBeCloseTo(50, 0);
    });

    it('converts pure blue correctly', () => {
      const result = hexToHSL('#0000ff');
      expect(result.h).toBeCloseTo(240, 0);
      expect(result.s).toBeCloseTo(100, 0);
      expect(result.l).toBeCloseTo(50, 0);
    });

    it('converts white correctly', () => {
      const result = hexToHSL('#ffffff');
      expect(result.l).toBeCloseTo(100, 0);
    });

    it('converts black correctly', () => {
      const result = hexToHSL('#000000');
      expect(result.l).toBeCloseTo(0, 0);
    });

    it('handles hex without hash', () => {
      const result = hexToHSL('ff0000');
      expect(result.h).toBeCloseTo(0, 0);
    });

    it('returns zeros for invalid hex', () => {
      const result = hexToHSL('invalid');
      expect(result).toEqual({ h: 0, s: 0, l: 0 });
    });

    it('converts gray correctly (no saturation)', () => {
      const result = hexToHSL('#808080');
      expect(result.s).toBeCloseTo(0, 0);
      expect(result.l).toBeCloseTo(50, 0);
    });
  });

  describe('hslToHex', () => {
    it('converts red HSL to hex', () => {
      const result = hslToHex(0, 100, 50);
      expect(result.toLowerCase()).toBe('#ff0000');
    });

    it('converts green HSL to hex', () => {
      const result = hslToHex(120, 100, 50);
      expect(result.toLowerCase()).toBe('#00ff00');
    });

    it('converts blue HSL to hex', () => {
      const result = hslToHex(240, 100, 50);
      expect(result.toLowerCase()).toBe('#0000ff');
    });

    it('converts white correctly', () => {
      const result = hslToHex(0, 0, 100);
      expect(result.toLowerCase()).toBe('#ffffff');
    });

    it('converts black correctly', () => {
      const result = hslToHex(0, 0, 0);
      expect(result.toLowerCase()).toBe('#000000');
    });

    it('handles cyan (h=180)', () => {
      const result = hslToHex(180, 100, 50);
      expect(result.toLowerCase()).toBe('#00ffff');
    });

    it('handles magenta (h=300)', () => {
      const result = hslToHex(300, 100, 50);
      expect(result.toLowerCase()).toBe('#ff00ff');
    });

    it('handles yellow (h=60)', () => {
      const result = hslToHex(60, 100, 50);
      expect(result.toLowerCase()).toBe('#ffff00');
    });
  });

  describe('generateColorPalette', () => {
    it('generates a palette with all shade keys', () => {
      const palette = generateColorPalette('#3b82f6');
      expect(palette).toHaveProperty('50');
      expect(palette).toHaveProperty('100');
      expect(palette).toHaveProperty('200');
      expect(palette).toHaveProperty('300');
      expect(palette).toHaveProperty('400');
      expect(palette).toHaveProperty('500');
      expect(palette).toHaveProperty('600');
      expect(palette).toHaveProperty('700');
      expect(palette).toHaveProperty('800');
      expect(palette).toHaveProperty('900');
    });

    it('uses the base color for shade 600', () => {
      const baseColor = '#3b82f6';
      const palette = generateColorPalette(baseColor);
      expect(palette['600']).toBe(baseColor);
    });

    it('generates lighter shades for lower numbers', () => {
      const palette = generateColorPalette('#3b82f6');
      const hsl50 = hexToHSL(palette['50']);
      const hsl500 = hexToHSL(palette['500']);
      expect(hsl50.l).toBeGreaterThan(hsl500.l);
    });

    it('generates darker shades for higher numbers', () => {
      const palette = generateColorPalette('#3b82f6');
      const hsl500 = hexToHSL(palette['500']);
      const hsl900 = hexToHSL(palette['900']);
      expect(hsl900.l).toBeLessThan(hsl500.l);
    });
  });

  describe('applyColorPalette', () => {
    beforeEach(() => {
      // Reset any CSS custom properties
      document.documentElement.style.cssText = '';
    });

    it('sets CSS custom properties for each shade', () => {
      const palette = { '500': '#3b82f6', '600': '#2563eb' };
      applyColorPalette(palette);

      expect(document.documentElement.style.getPropertyValue('--color-brand-500')).toBe('#3b82f6');
      expect(document.documentElement.style.getPropertyValue('--color-brand-600')).toBe('#2563eb');
    });
  });

  describe('applyBrandColors', () => {
    beforeEach(() => {
      document.documentElement.style.cssText = '';
    });

    it('applies primary color palette', () => {
      applyBrandColors('#3b82f6');
      expect(document.documentElement.style.getPropertyValue('--color-brand-600')).toBe('#3b82f6');
    });

    it('sets secondary color to primary when not provided', () => {
      applyBrandColors('#3b82f6');
      expect(document.documentElement.style.getPropertyValue('--color-brand-secondary')).toBe('#3b82f6');
    });

    it('sets secondary color when provided', () => {
      applyBrandColors('#3b82f6', '#10b981');
      expect(document.documentElement.style.getPropertyValue('--color-brand-secondary')).toBe('#10b981');
    });
  });

  describe('defaultColorPalette', () => {
    it('has all required shades', () => {
      expect(Object.keys(defaultColorPalette)).toHaveLength(10);
      expect(defaultColorPalette).toHaveProperty('50');
      expect(defaultColorPalette).toHaveProperty('900');
    });

    it('contains valid hex colors', () => {
      Object.values(defaultColorPalette).forEach((color) => {
        expect(color).toMatch(/^#[0-9a-fA-F]{6}$/);
      });
    });
  });
});
