utilities_theme.js

const STORAGE_KEY       = 'theme';
const CUSTOM_THEMES_KEY = 'custom-themes';
const LIGHT_QUERY       = window.matchMedia('(prefers-color-scheme: light)');

// All CSS variable names managed by the theme system.
// Must stay in sync with COLOR_VARS in account.js.
export const MANAGED_VARS = [
    '--accent', '--accent2', '--bg', '--surface', '--surface2', '--border',
    '--text', '--muted', '--waveform', '--waveform-progress',
    '--danger', '--success', '--rec',
];

/**
 * Returns the stored theme ID, or 'auto' if none saved.
 * @returns {string}
 */
export function getTheme() {
    return localStorage.getItem(STORAGE_KEY) || 'auto';
}

/**
 * @typedef {object} CustomTheme
 * @property {string} id
 * @property {string} name
 * @property {'light'|'dark'} base
 * @property {object} colors
 */

/**
 * Returns all saved custom theme objects.
 * @returns {CustomTheme[]}
 */
export function getCustomThemes() {
    try { return JSON.parse(localStorage.getItem(CUSTOM_THEMES_KEY) || '[]'); } catch { return []; }
}

/**
 * Persists the custom themes array.
 * @param {Array} themes - The custom themes array to persist.
 */
export function saveCustomThemes(themes) {
    localStorage.setItem(CUSTOM_THEMES_KEY, JSON.stringify(themes));
}

/**
 * Resolves any theme ID to 'light' or 'dark'.
 * @param {string} themeId - The theme ID to resolve ('auto', 'light', 'dark', or custom ID).
 * @returns {'light'|'dark'}
 */
function resolveBase(themeId) {
    if (themeId === 'auto')  return LIGHT_QUERY.matches ? 'light' : 'dark';
    if (themeId === 'light') return 'light';
    if (themeId === 'dark')  return 'dark';
    const custom = getCustomThemes().find(t => t.id === themeId);
    return custom ? custom.base : (LIGHT_QUERY.matches ? 'light' : 'dark');
}

/**
 * Clears all managed CSS variables then applies the saved colors for `themeId`.
 * @param {string} themeId - The theme ID whose colors to apply.
 */
function applyThemeColors(themeId) {
    MANAGED_VARS.forEach(v => document.documentElement.style.removeProperty(v));

    let colors = {};
    if (themeId === 'auto' || themeId === 'light' || themeId === 'dark') {
        try { colors = JSON.parse(localStorage.getItem('custom-colors-' + resolveBase(themeId)) || '{}'); } catch {}
    } else {
        const custom = getCustomThemes().find(t => t.id === themeId);
        if (custom) colors = custom.colors;
    }
    Object.entries(colors).forEach(([k, v]) => document.documentElement.style.setProperty(k, v));
}

/**
 * Switches to `themeId`, applies data-theme + color overrides, and persists the choice.
 * Accepts 'auto', 'light', 'dark', or a custom theme ID.
 * @param {string} themeId - The theme ID to switch to.
 */
export function setTheme(themeId) {
    localStorage.setItem(STORAGE_KEY, themeId);
    document.documentElement.dataset.theme = resolveBase(themeId);
    applyThemeColors(themeId);
    window.dispatchEvent(new CustomEvent('themechange', { detail: themeId }));
}

/** Reads the saved preference and applies it. Call as early as possible. */
export function initTheme() {
    const themeId = getTheme();
    document.documentElement.dataset.theme = resolveBase(themeId);
    applyThemeColors(themeId);
    LIGHT_QUERY.addEventListener('change', () => {
        if (getTheme() === 'auto') initTheme();
    });
}