import { browser } from "$app/environment";
import {
    getContrast,
    hexToHsl,
    generateHslColor,
    DEFAULT_THEME,
} from "$lib/utils/color";
import { storage, STORAGE_KEYS } from "$lib/services";

// Re-export for backwards compatibility
export { DEFAULT_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);
}

// Load initial values from storage
function getInitialTheme() {
    const saved = storage.get<typeof DEFAULT_THEME>(STORAGE_KEYS.THEME);
    if (saved) {
        return {
            primary: saved.primary ?? DEFAULT_THEME.primary,
            secondary: saved.secondary ?? DEFAULT_THEME.secondary,
            text: saved.text ?? DEFAULT_THEME.text,
            background: saved.background ?? DEFAULT_THEME.background,
        };
    }
    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 storage)
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 storage
function save() {
    storage.set(STORAGE_KEYS.THEME, {
        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 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 = 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 = 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 = generateHslColor(
            null,
            [70, 100], // High Saturation
            isDarkTheme ? [30, 60] : [40, 60] // Mid-Tone Luminance for True Color
        );

        // --- VALIDATION ---

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

        // Check Hue Diversity (Ensures Primary and Secondary don't look like the same color)
        const primHsl = hexToHsl(newPrim);
        const secHsl = 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,
};