// ==========================================
// Switchboard Core — SDK: Theme Control
// ==========================================
// Theme management: localStorage + data-theme + system pref.
// Port of Theme from ui-primitives.js as ES module.
//
// Factory: createTheme(emitFn)
// ==========================================

const _key = 'switchboard_theme';

/**
 * Create the theme module.
 *
 * @param {Function} emitFn — events.emit (for 'theme.changed')
 * @returns {object} theme
 */
export function createTheme(emitFn) {

    let _mqListener = null;
    const _listeners = new Set();  // local change subscribers

    function _apply(mode) {
        // Remove prior system-preference listener
        if (_mqListener) {
            window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', _mqListener);
            _mqListener = null;
        }

        if (mode === 'system') {
            const resolved = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
            document.documentElement.setAttribute('data-theme', resolved);

            _mqListener = (e) => {
                if (_getMode() === 'system') {
                    const r = e.matches ? 'dark' : 'light';
                    document.documentElement.setAttribute('data-theme', r);
                    _notify(r);
                }
            };
            window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', _mqListener);
        } else {
            document.documentElement.setAttribute('data-theme', mode);
        }
    }

    function _getMode() {
        return localStorage.getItem(_key) || 'system';
    }

    function _getResolved() {
        const mode = _getMode();
        if (mode !== 'system') return mode;
        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
    }

    function _notify(resolved) {
        for (const fn of _listeners) {
            try { fn(resolved); } catch (e) { console.error('[sw.theme] Listener error:', e); }
        }
        emitFn('theme.changed', { theme: resolved }, { localOnly: true });
    }

    // ── Public API ──────────────────────────────

    return {
        get current() { return _getResolved(); },
        get mode()    { return _getMode(); },

        set(mode) {
            localStorage.setItem(_key, mode);
            _apply(mode);
            _notify(_getResolved());
        },

        /**
         * Subscribe to theme changes.
         * @param {string} event — 'change'
         * @param {Function} fn — receives resolved theme string
         * @returns {Function} unsubscribe
         */
        on(event, fn) {
            if (event !== 'change') {
                console.warn(`[sw.theme] Unknown event '${event}'`);
                return () => {};
            }
            _listeners.add(fn);
            return () => _listeners.delete(fn);
        },

        /**
         * Live CSS variable tokens as a JS object.
         * Keys are camelCased variable names (e.g. --bg-surface → bgSurface).
         * Recomputes on each access to reflect the current theme.
         */
        get tokens() {
            const style = getComputedStyle(document.documentElement);
            const names = [
                'bg', 'bg-surface', 'bg-raised', 'bg-hover', 'bg-elevated',
                'border', 'border-elevated', 'border-light',
                'text', 'text-2', 'text-3',
                'accent', 'accent-hover', 'accent-dim',
                'danger', 'success', 'warning', 'purple',
                'danger-dim', 'success-dim', 'warning-dim',
                'overlay', 'glass', 'input-bg', 'shadow-lg',
                'radius', 'radius-lg', 'font', 'mono', 'transition',
            ];
            const t = {};
            for (const n of names) {
                t[n.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase())] =
                    style.getPropertyValue('--' + n).trim();
            }
            return Object.freeze(t);
        },

        /** Apply stored theme. Called during boot. */
        init() {
            _apply(_getMode());
        },
    };
}
