import { browser } from "$app/environment";

const THEME_STORAGE_KEY = "kuldvillak-theme";
const THEME_CHANNEL_NAME = "kuldvillak-theme-sync";

// BroadcastChannel for syncing theme across windows
let channel: BroadcastChannel | null = null;
if (browser) {
    channel = new BroadcastChannel(THEME_CHANNEL_NAME);
}

// Default theme colors
export const DEFAULT_THEME = {
    primary: "#003B9B",
    secondary: "#FFAB00",
    text: "#FFFFFF",
    background: "#000000",
};

// --- WCAG & Color Utilities (Updated for HSL generation/checking) ---
const ColorUtils = {
    // Convert Hex to RGB array
    hexToRgb(hex: string) {
        const bigint = parseInt(hex.replace('#', ''), 16);
        return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255];
    },

    // Calculate Relative Luminance (WCAG 2.0 formula)
    getLuminance(r: number, g: number, b: number) {
        const a = [r, g, b].map((v) => {
            v /= 255;
            return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
        });
        return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
    },

    // Calculate Contrast Ratio
    getContrast(hex1: string, hex2: string) {
        const rgb1 = this.hexToRgb(hex1);
        const rgb2 = this.hexToRgb(hex2);
        const l1 = this.getLuminance(rgb1[0], rgb1[1], rgb1[2]);
        const l2 = this.getLuminance(rgb2[0], rgb2[1], rgb2[2]);
        return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
    },

    // Convert Hex to HSL for checking hue distance
    hexToHsl(hex: string): [number, number, number] {
        let r = 0, g = 0, b = 0;
        const rgb = this.hexToRgb(hex);
        r = rgb[0] / 255; g = rgb[1] / 255; b = rgb[2] / 255;
        const max = Math.max(r, g, b), min = Math.min(r, g, b);
        let h = 0, s = 0, l = (max + min) / 2;

        if (max !== min) {
            const d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
            switch (max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
        return [h * 360, s, l]; // Return H in degrees, S/L as 0-1.
    },

    // Generate a color with strictly controlled HSL (Luminance and Saturation)
    generateHslColor(hueRange: [number, number] | null, satRange: [number, number], lumRange: [number, number]): string {
        const h = hueRange
            ? Math.floor(Math.random() * (hueRange[1] - hueRange[0])) + hueRange[0]
            : Math.floor(Math.random() * 360);

        const s = Math.floor(Math.random() * (satRange[1] - satRange[0])) + satRange[0];
        const l = Math.floor(Math.random() * (lumRange[1] - lumRange[0])) + lumRange[0];

        return this.hslToHex(h, s, l);
    },

    hslToHex(h: number, s: number, l: number) {
        l /= 100;
        const a = s * Math.min(l, 1 - l) / 100;
        const f = (n: number) => {
            const k = (n + h / 30) % 12;
            const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
            return Math.round(255 * color).toString(16).padStart(2, '0');
        };
        return `#${f(0)}${f(8)}${f(4)}`;
    }
};


// Load initial values from localStorage
function getInitialTheme() {
    if (browser) {
        const saved = localStorage.getItem(THEME_STORAGE_KEY);
        if (saved) {
            try {
                const theme = JSON.parse(saved);
                return {
                    primary: theme.primary ?? DEFAULT_THEME.primary,
                    secondary: theme.secondary ?? DEFAULT_THEME.secondary,
                    text: theme.text ?? DEFAULT_THEME.text,
                    background: theme.background ?? DEFAULT_THEME.background,
                };
            } catch {
                // Ignore parse errors
            }
        }
    }
    return { ...DEFAULT_THEME };
}

const initialTheme = getInitialTheme();

// Current applied values (what's visually shown)
let primary = $state(initialTheme.primary);
let secondary = $state(initialTheme.secondary);
let text = $state(initialTheme.text);
let background = $state(initialTheme.background);

// Saved values (what's persisted to localStorage)
let savedPrimary = $state(initialTheme.primary);
let savedSecondary = $state(initialTheme.secondary);
let savedText = $state(initialTheme.text);
let savedBackground = $state(initialTheme.background);

function applyTheme(broadcast = true) {
    if (browser) {
        document.documentElement.style.setProperty("--kv-blue", primary);
        document.documentElement.style.setProperty("--kv-yellow", secondary);
        document.documentElement.style.setProperty("--kv-text", text);
        document.documentElement.style.setProperty("--kv-background", background);

        // Broadcast to other windows
        if (broadcast && channel) {
            channel.postMessage({ primary, secondary, text, background });
        }
    }
}

// Listen for theme changes from other windows
if (browser && channel) {
    channel.onmessage = (event) => {
        const { primary: p, secondary: s, text: t, background: b } = event.data;
        if (p) primary = p;
        if (s) secondary = s;
        if (t) text = t;
        if (b) background = b;
        applyTheme(false); // Don't re-broadcast
    };
}

// Save current values to localStorage
function save() {
    if (browser) {
        localStorage.setItem(THEME_STORAGE_KEY, JSON.stringify({
            primary,
            secondary,
            text,
            background
        }));
        // Update saved state
        savedPrimary = primary;
        savedSecondary = secondary;
        savedText = text;
        savedBackground = background;
    }
}

// Revert to last saved values (for cancel/close without saving)
function revert() {
    primary = savedPrimary;
    secondary = savedSecondary;
    text = savedText;
    background = savedBackground;
    applyTheme();
}

// Reset to default values (applies immediately for preview)
function resetToDefaults() {
    primary = DEFAULT_THEME.primary;
    secondary = DEFAULT_THEME.secondary;
    text = DEFAULT_THEME.text;
    background = DEFAULT_THEME.background;
    applyTheme();
}

// Returns a simple random hex (utility for single color needs)
function getRandomColor() {
    // High saturation for a beautiful single random color
    return ColorUtils.generateHslColor(null, [70, 100], [40, 60]);
}

// Smart Randomization with WCAG and Vibrancy Enforcement
function randomizeColors() {
    let attempts = 0;
    const maxAttempts = 50;

    while (attempts < maxAttempts) {
        attempts++;

        // 1. Decide Polarity
        const isDarkTheme = Math.random() < 0.5;

        // 2. Generate Background (Low Saturation, Extreme Luminance)
        const newBg = ColorUtils.generateHslColor(
            null,
            [10, 30], // Low Saturation for a neutral BG
            isDarkTheme ? [4, 10] : [95, 99] // Extreme Dark or Light
        );

        // 3. Generate Text (Pure White or Near Black)
        const newText = isDarkTheme ? "#FFFFFF" : "#050505";

        // 4. Generate Secondary (The "Pop" Color - 7:1 against BG)
        const newSec = ColorUtils.generateHslColor(
            null,
            [75, 100], // High Saturation (Vibrant!)
            isDarkTheme ? [60, 85] : [20, 45] // Opposite L to BG
        );

        // 5. Generate Primary (The "Brand" Color - Mid-Tone Vibrancy)
        const newPrim = ColorUtils.generateHslColor(
            null,
            [70, 100], // High Saturation
            isDarkTheme ? [30, 60] : [40, 60] // Mid-Tone Luminance for True Color
        );

        // --- VALIDATION ---

        // Check Contrast
        const ratio_Prim_Text = ColorUtils.getContrast(newPrim, newText);
        const ratio_Sec_Bg = ColorUtils.getContrast(newSec, newBg);
        const ratio_Prim_Sec = ColorUtils.getContrast(newPrim, newSec);

        // Check Hue Diversity (Ensures Primary and Secondary don't look like the same color)
        const primHsl = ColorUtils.hexToHsl(newPrim);
        const secHsl = ColorUtils.hexToHsl(newSec);
        // We use Math.min to handle the 360-degree color wheel wrap
        const hueDiff = Math.min(Math.abs(primHsl[0] - secHsl[0]), 360 - Math.abs(primHsl[0] - secHsl[0]));
        // Require at least 40 degrees difference for visual distinction
        const distinctHues = hueDiff >= 40;

        if (
            ratio_Prim_Text >= 4.5 &&  // WCAG AA for normal text (Relaxed for vibrancy)
            ratio_Sec_Bg >= 7.0 &&     // WCAG AAA (Ensures Secondary/CTA pops)
            ratio_Prim_Sec >= 3.0 &&   // WCAG for non-text/graphical elements (Ensures distinction)
            distinctHues               // Ensures visual diversity
        ) {
            primary = newPrim;
            secondary = newSec;
            text = newText;
            background = newBg;
            applyTheme();
            return;
        }
    }

    // Fallback if 50 attempts fail
    console.warn("Could not generate vibrant palette with accessibility. Resetting to defaults.");
    resetToDefaults();
}

function reset() {
    resetToDefaults();
    save();
}

export const themeStore = {
    get primary() { return primary; },
    set primary(value: string) { primary = value; applyTheme(); },
    get secondary() { return secondary; },
    set secondary(value: string) { secondary = value; applyTheme(); },
    get text() { return text; },
    set text(value: string) { text = value; applyTheme(); },
    get background() { return background; },
    set background(value: string) { background = value; applyTheme(); },
    applyTheme,
    save,
    revert,
    reset,
    resetToDefaults,
    getRandomColor,
    randomizeColors,
};