import { describe, it, expect } from 'vitest';
import {
    hexToRgb,
    getLuminance,
    getContrast,
    hexToHsl,
    hslToHex,
    generateHslColor,
    DEFAULT_THEME,
} from '$lib/utils/color';

describe('ColorUtils', () => {
    describe('hexToRgb', () => {
        it('should convert white hex to RGB', () => {
            expect(hexToRgb('#FFFFFF')).toEqual([255, 255, 255]);
        });

        it('should convert black hex to RGB', () => {
            expect(hexToRgb('#000000')).toEqual([0, 0, 0]);
        });

        it('should convert red hex to RGB', () => {
            expect(hexToRgb('#FF0000')).toEqual([255, 0, 0]);
        });

        it('should convert green hex to RGB', () => {
            expect(hexToRgb('#00FF00')).toEqual([0, 255, 0]);
        });

        it('should convert blue hex to RGB', () => {
            expect(hexToRgb('#0000FF')).toEqual([0, 0, 255]);
        });

        it('should handle hex without hash', () => {
            expect(hexToRgb('FF0000')).toEqual([255, 0, 0]);
        });
    });

    describe('getLuminance', () => {
        it('should return 1 for white', () => {
            expect(getLuminance(255, 255, 255)).toBeCloseTo(1, 2);
        });

        it('should return 0 for black', () => {
            expect(getLuminance(0, 0, 0)).toBeCloseTo(0, 2);
        });

        it('should return ~0.2126 for pure red', () => {
            expect(getLuminance(255, 0, 0)).toBeCloseTo(0.2126, 2);
        });

        it('should return ~0.7152 for pure green', () => {
            expect(getLuminance(0, 255, 0)).toBeCloseTo(0.7152, 2);
        });

        it('should return ~0.0722 for pure blue', () => {
            expect(getLuminance(0, 0, 255)).toBeCloseTo(0.0722, 2);
        });
    });

    describe('getContrast', () => {
        it('should return 21 for black on white (max contrast)', () => {
            const contrast = getContrast('#FFFFFF', '#000000');
            expect(contrast).toBeCloseTo(21, 0);
        });

        it('should return 1 for same colors (no contrast)', () => {
            const contrast = getContrast('#FF0000', '#FF0000');
            expect(contrast).toBeCloseTo(1, 2);
        });

        it('should return same value regardless of order', () => {
            const contrast1 = getContrast('#FFFFFF', '#003B9B');
            const contrast2 = getContrast('#003B9B', '#FFFFFF');
            expect(contrast1).toBeCloseTo(contrast2, 2);
        });

        it('should meet WCAG AA (4.5:1) for default theme text on primary', () => {
            const contrast = getContrast(DEFAULT_THEME.text, DEFAULT_THEME.primary);
            expect(contrast).toBeGreaterThanOrEqual(4.5);
        });
    });

    describe('hexToHsl', () => {
        it('should convert red to HSL', () => {
            const [h, s, l] = hexToHsl('#FF0000');
            expect(h).toBeCloseTo(0, 0);
            expect(s).toBeCloseTo(1, 2);
            expect(l).toBeCloseTo(0.5, 2);
        });

        it('should convert green to HSL', () => {
            const [h, s, l] = hexToHsl('#00FF00');
            expect(h).toBeCloseTo(120, 0);
            expect(s).toBeCloseTo(1, 2);
            expect(l).toBeCloseTo(0.5, 2);
        });

        it('should convert blue to HSL', () => {
            const [h, s, l] = hexToHsl('#0000FF');
            expect(h).toBeCloseTo(240, 0);
            expect(s).toBeCloseTo(1, 2);
            expect(l).toBeCloseTo(0.5, 2);
        });

        it('should convert white to HSL with 0 saturation', () => {
            const [h, s, l] = hexToHsl('#FFFFFF');
            expect(s).toBeCloseTo(0, 2);
            expect(l).toBeCloseTo(1, 2);
        });

        it('should convert black to HSL with 0 saturation and lightness', () => {
            const [h, s, l] = hexToHsl('#000000');
            expect(s).toBeCloseTo(0, 2);
            expect(l).toBeCloseTo(0, 2);
        });
    });

    describe('hslToHex', () => {
        it('should convert red HSL to hex', () => {
            expect(hslToHex(0, 100, 50).toUpperCase()).toBe('#FF0000');
        });

        it('should convert green HSL to hex', () => {
            expect(hslToHex(120, 100, 50).toUpperCase()).toBe('#00FF00');
        });

        it('should convert blue HSL to hex', () => {
            expect(hslToHex(240, 100, 50).toUpperCase()).toBe('#0000FF');
        });

        it('should convert white HSL to hex', () => {
            expect(hslToHex(0, 0, 100).toUpperCase()).toBe('#FFFFFF');
        });

        it('should convert black HSL to hex', () => {
            expect(hslToHex(0, 0, 0).toUpperCase()).toBe('#000000');
        });
    });

    describe('generateHslColor', () => {
        it('should generate valid hex color', () => {
            const color = generateHslColor(null, [50, 100], [30, 70]);
            expect(color).toMatch(/^#[0-9A-Fa-f]{6}$/);
        });

        it('should generate color within specified hue range', () => {
            for (let i = 0; i < 10; i++) {
                const color = generateHslColor([0, 60], [50, 100], [30, 70]);
                const [h] = hexToHsl(color);
                expect(h).toBeGreaterThanOrEqual(-5);
                expect(h).toBeLessThanOrEqual(65);
            }
        });
    });
});

describe('DEFAULT_THEME', () => {
    it('should have all required color properties', () => {
        expect(DEFAULT_THEME).toHaveProperty('primary');
        expect(DEFAULT_THEME).toHaveProperty('secondary');
        expect(DEFAULT_THEME).toHaveProperty('text');
        expect(DEFAULT_THEME).toHaveProperty('background');
    });

    it('should have valid hex colors', () => {
        const hexRegex = /^#[0-9A-Fa-f]{6}$/;
        expect(DEFAULT_THEME.primary).toMatch(hexRegex);
        expect(DEFAULT_THEME.secondary).toMatch(hexRegex);
        expect(DEFAULT_THEME.text).toMatch(hexRegex);
        expect(DEFAULT_THEME.background).toMatch(hexRegex);
    });

    it('should have good contrast between text and background', () => {
        const contrast = getContrast(DEFAULT_THEME.text, DEFAULT_THEME.background);
        expect(contrast).toBeGreaterThanOrEqual(7);
    });
});
