export type ColorSchemeId = 'default' | 'gold' | 'navy' | 'emerald' | 'rose' | 'slate' | 'teal' | 'orange' | 'neo' | 'xp';

export type ThemePreferences = {
    theme: string;
    menu: string;
    layout: string;
    rtlClass: string;
    animation: string;
    navbar: string;
    semidark: boolean;
    colorScheme: ColorSchemeId;
};

export type ColorSchemePreset = {
    id: ColorSchemeId;
    label: string;
    /** CSS `R G B` channels for Tailwind opacity support */
    primaryRgb: string;
    lightRgb: string;
    darkLightAlpha: string;
    primary: string;
    light: string;
    darkLight: string;
};

const LEGACY_KEYS = ['theme', 'menu', 'layout', 'rtlClass', 'animation', 'navbar', 'semidark', 'colorScheme'] as const;

function buildPreset(id: ColorSchemeId, label: string, primary: string, light: string): ColorSchemePreset {
    const primaryRgb = hexToRgbChannels(primary);
    const lightRgb = hexToRgbChannels(light);
    return {
        id,
        label,
        primary,
        light,
        primaryRgb,
        lightRgb,
        darkLightAlpha: '0.15',
        darkLight: `rgb(${primaryRgb} / 0.15)`,
    };
}

export const COLOR_SCHEME_PRESETS: ColorSchemePreset[] = [
    buildPreset('default', 'Default', '#4361ee', '#eaf1ff'),
    buildPreset('gold', 'Gold', '#c9a227', '#fbf6e8'),
    buildPreset('navy', 'Navy', '#1e40af', '#e8eef9'),
    buildPreset('emerald', 'Emerald', '#059669', '#e6f7f1'),
    buildPreset('rose', 'Rose', '#e11d48', '#fde8ee'),
    buildPreset('slate', 'Slate', '#475569', '#eef1f4'),
    buildPreset('teal', 'Teal', '#0d9488', '#e6f7f5'),
    buildPreset('orange', 'Orange', '#ea580c', '#fff1e8'),
    buildPreset('neo', 'Neo', '#111111', '#FFDB57'),
    buildPreset('xp', 'XP', '#0054e3', '#d4e8ff'),
];

export const DEFAULT_COLOR_SCHEME: ColorSchemeId = 'default';

export function isNeoScheme(id?: string | null): boolean {
    return id === 'neo';
}

export function isXpScheme(id?: string | null): boolean {
    return id === 'xp';
}

/** Presets that force light mode and disable semidark (Neo, XP). */
export function isLightOnlyScheme(id?: string | null): boolean {
    return isNeoScheme(id) || isXpScheme(id);
}

export function getColorSchemePreset(id?: string | null): ColorSchemePreset {
    return COLOR_SCHEME_PRESETS.find((preset) => preset.id === id) || COLOR_SCHEME_PRESETS[0];
}

/** Primary (+ related) colors for ApexCharts / custom visuals */
export function getThemeChartColors(colorScheme?: string | null): string[] {
    if (isNeoScheme(colorScheme)) {
        return ['#111111', '#6B7280', '#FFDB57', '#00ab55', '#e7515a'];
    }
    if (isXpScheme(colorScheme)) {
        return ['#0054e3', '#3c8a3c', '#7ba7e1', '#c44d4d', '#e2a03f', '#316ac5'];
    }
    const primary = getColorSchemePreset(colorScheme).primary;
    return [primary, mixWithWhite(primary, 0.45), mixWithWhite(primary, 0.7)];
}

export function getThemeChartFont(colorScheme?: string | null): string {
    if (isNeoScheme(colorScheme)) return 'IBM Plex Sans, sans-serif';
    if (isXpScheme(colorScheme)) return 'Tahoma, Verdana, sans-serif';
    return 'Nunito, sans-serif';
}

const NEO_DATA_LABEL = '#FFDB57';
const DEFAULT_DATA_LABEL = '#1f2937';
const NEO_DATA_LABEL_ON_LIGHT = '#111111';

/** Label di atas bar / angka chart — kuning Neo di bar hitam, gelap di tema lain */
export function getThemeChartDataLabelColor(colorScheme?: string | null): string {
    return isNeoScheme(colorScheme) ? NEO_DATA_LABEL : DEFAULT_DATA_LABEL;
}

/** Label per slice donut: kuning di slice gelap, hitam di slice terang (kuning Neo) */
export function getThemeChartSliceLabelColors(
    sliceColors: string[],
    colorScheme?: string | null
): string[] | undefined {
    if (!isNeoScheme(colorScheme)) return undefined;
    return sliceColors.map((color) => (hexLuminance(color) < 0.45 ? NEO_DATA_LABEL : NEO_DATA_LABEL_ON_LIGHT));
}

function hexLuminance(hex: string): number {
    const rgb = hexToRgb(hex);
    if (!rgb) return 1;
    return (0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b) / 255;
}

export function applyColorSchemeToDom(colorScheme?: string | null): void {
    if (typeof document === 'undefined') return;
    const preset = getColorSchemePreset(colorScheme);
    const root = document.documentElement;
    root.style.setProperty('--color-primary', preset.primaryRgb);
    root.style.setProperty('--color-primary-light', preset.lightRgb);
    root.style.setProperty('--color-primary-dark-light', `${preset.primaryRgb} / ${preset.darkLightAlpha}`);
    root.classList.toggle('theme-neo', isNeoScheme(preset.id));
    root.classList.toggle('theme-xp', isXpScheme(preset.id));
}

export function themeStorageKey(userId: string): string {
    return `aurumlab_theme_${userId}`;
}

export function isLoggedInUserId(userId?: string | null): userId is string {
    return Boolean(userId && userId !== 'false' && userId.trim() !== '');
}

export function readUserThemePreferences(userId: string): Partial<ThemePreferences> | null {
    if (typeof localStorage === 'undefined' || !isLoggedInUserId(userId)) return null;
    try {
        const raw = localStorage.getItem(themeStorageKey(userId));
        if (!raw) return null;
        const parsed = JSON.parse(raw);
        return parsed && typeof parsed === 'object' ? parsed : null;
    } catch {
        return null;
    }
}

export function writeUserThemePreferences(userId: string, prefs: ThemePreferences): void {
    if (typeof localStorage === 'undefined' || !isLoggedInUserId(userId)) return;
    localStorage.setItem(themeStorageKey(userId), JSON.stringify(prefs));
}

/** One-time migrate legacy global keys into the logged-in user's theme bag. */
export function migrateLegacyThemePreferences(userId: string): Partial<ThemePreferences> | null {
    if (typeof localStorage === 'undefined' || !isLoggedInUserId(userId)) return null;
    if (localStorage.getItem(themeStorageKey(userId))) return null;

    const migrated: Partial<ThemePreferences> = {};
    let hasAny = false;

    for (const key of LEGACY_KEYS) {
        const value = localStorage.getItem(key);
        if (value === null) continue;
        hasAny = true;
        if (key === 'semidark') {
            migrated.semidark = value === 'true';
        } else if (key === 'colorScheme') {
            migrated.colorScheme = (COLOR_SCHEME_PRESETS.some((p) => p.id === value) ? value : DEFAULT_COLOR_SCHEME) as ColorSchemeId;
        } else {
            (migrated as Record<string, string>)[key] = value;
        }
    }

    if (!hasAny) return null;
    return migrated;
}

export function clearLegacyThemeKeys(): void {
    if (typeof localStorage === 'undefined') return;
    for (const key of LEGACY_KEYS) {
        localStorage.removeItem(key);
    }
}

function mixWithWhite(hex: string, whiteRatio: number): string {
    const rgb = hexToRgb(hex);
    if (!rgb) return hex;
    const r = Math.round(rgb.r + (255 - rgb.r) * whiteRatio);
    const g = Math.round(rgb.g + (255 - rgb.g) * whiteRatio);
    const b = Math.round(rgb.b + (255 - rgb.b) * whiteRatio);
    return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

function hexToRgbChannels(hex: string): string {
    const rgb = hexToRgb(hex);
    if (!rgb) return '67 97 238';
    return `${rgb.r} ${rgb.g} ${rgb.b}`;
}

function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
    const normalized = hex.replace('#', '');
    if (normalized.length !== 6) return null;
    return {
        r: parseInt(normalized.slice(0, 2), 16),
        g: parseInt(normalized.slice(2, 4), 16),
        b: parseInt(normalized.slice(4, 6), 16),
    };
}

function toHex(value: number): string {
    return value.toString(16).padStart(2, '0');
}
