/**
 * Theme Service
 * Handles theme switching, persistence, and sync with user account
 *
 * Features:
 * - User-prefixed localStorage key to prevent cross-user theme bleeding
 * - Server sync via settings API
 * - System preference detection and listener
 * - Quick toggle cycling through themes
 *
 * Security note: This file only uses internal API endpoints (/settings/api/...)
 * and does not handle external URLs. URLValidator is not required.
 * @url-security-exempt internal-api-only
 */
(function() {
    'use strict';

    const STORAGE_KEY_PREFIX = 'ldr-theme';
    const SETTING_KEY = 'app.theme';

    // Themes are auto-detected from CSS and injected by base.html
    // window.LDR_THEME_METADATA is set before this script loads
    // This avoids having to maintain duplicate theme lists
    const THEMES = window.LDR_THEME_METADATA || {
        // Fallback in case metadata wasn't injected (shouldn't happen)
        'hashed': { label: 'Hashed', icon: 'fa-hashtag', group: 'core' },
        'light': { label: 'Light', icon: 'fa-sun', group: 'core' },
        'system': { label: 'System', icon: 'fa-desktop', group: 'system' }
    };

    // Valid theme names for validation (auto-detected)
    const VALID_THEMES = Object.keys(THEMES);

    // Theme cycle order for quick toggle button (subset of popular themes)
    const THEME_CYCLE = ['hashed', 'light', 'nord', 'dracula'];

    /**
     * Get user ID from page context (if available)
     * Falls back to 'anonymous' for logged-out users
     */
    function getUserId() {
        // Try to get user ID from meta tag or data attribute
        const userMeta = document.querySelector('meta[name="user-id"]');
        if (userMeta) {
            const content = userMeta.getAttribute('content')?.trim();
            if (content) {
                return content;
            }
        }

        // Try to get from body data attribute
        const body = document.body;
        if (body && body.dataset.userId?.trim()) {
            return body.dataset.userId.trim();
        }

        // Fallback for anonymous users
        return 'anonymous';
    }

    /**
     * Get the localStorage key for current user
     */
    function getStorageKey() {
        const userId = getUserId();
        return `${STORAGE_KEY_PREFIX}-${userId}`;
    }

    /**
     * Get the effective theme (resolving 'system' to actual value)
     */
    function getEffectiveTheme(theme) {
        if (theme === 'system') {
            // Sepia is the default light theme - easier on eyes for research/reading
            return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'hashed' : 'sepia';
        }
        return theme;
    }

    /**
     * Get current theme from localStorage or default
     */
    function getCurrentTheme() {
        const storageKey = getStorageKey();
        return localStorage.getItem(storageKey) || 'system';
    }

    /**
     * Apply theme to document
     */
    function applyTheme(theme) {
        const effectiveTheme = getEffectiveTheme(theme);
        document.documentElement.setAttribute('data-theme', effectiveTheme);

        // Store raw theme preference (including 'system')
        const storageKey = getStorageKey();
        localStorage.setItem(storageKey, theme);

        // Update any theme toggle buttons
        updateThemeToggles(theme, effectiveTheme);

        // Dispatch event for other components
        window.dispatchEvent(new CustomEvent('themechange', {
            detail: { theme, effectiveTheme }
        }));

        SafeLogger.log(`Theme applied: ${theme} (effective: ${effectiveTheme})`);
    }

    /**
     * Save theme to user account via settings API
     */
    function saveThemeToServer(theme) {
        const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
        if (!csrfToken) {
            SafeLogger.warn('CSRF token not found, cannot save theme to server');
            return Promise.resolve();
        }

        return fetch(`/settings/api/${SETTING_KEY}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({ value: theme })
        })
        .then(response => {
            if (!response.ok) throw new Error(`HTTP ${response.status}`);
            return response.json();
        })
        .then(data => {
            SafeLogger.log('Theme saved to server:', theme);
        })
        .catch(error => {
            SafeLogger.warn('Could not save theme to server (user may not be logged in):', error.message);
        });
    }

    /**
     * Load theme from server (on page load)
     */
    function loadThemeFromServer() {
        return fetch(`/settings/api/${SETTING_KEY}`)
            .then(response => {
                if (!response.ok) throw new Error(`HTTP ${response.status}`);
                return response.json();
            })
            .then(data => {
                if (data && data.value) {
                    return data.value;
                }
                return null;
            })
            .catch(error => {
                SafeLogger.warn('Could not load theme from server:', error.message);
                return null;
            });
    }

    /**
     * Set theme with both local and server sync
     */
    function setTheme(theme, syncToServer = true) {
        // Validate theme using VALID_THEMES array
        if (!VALID_THEMES.includes(theme)) {
            SafeLogger.warn('Invalid theme:', theme, '- falling back to hashed');
            theme = 'hashed';
        }

        applyTheme(theme);

        if (syncToServer) {
            saveThemeToServer(theme);
        }
    }

    /**
     * Populate a dropdown with all available themes
     */
    function populateThemeDropdown(selectElement) {
        if (!selectElement) return;

        // Clear existing options
        selectElement.innerHTML = '';

        // Group themes - dynamically determine groups from theme metadata
        const groups = {
            'core': 'Core Themes',
            'nature': 'Nature',
            'dev': 'Developer Themes',
            'research': 'Research & Reading',
            'other': 'Other',
            'system': 'System'
        };

        // Create optgroups
        Object.entries(groups).forEach(([groupKey, groupLabel]) => {
            const themesInGroup = Object.entries(THEMES).filter(([_, t]) => t.group === groupKey);
            if (themesInGroup.length > 0) {
                const optgroup = document.createElement('optgroup');
                optgroup.label = groupLabel;

                themesInGroup.forEach(([value, theme]) => {
                    const option = document.createElement('option');
                    option.value = value;
                    option.textContent = theme.label;
                    optgroup.appendChild(option);
                });

                selectElement.appendChild(optgroup);
            }
        });

        // Set current value
        selectElement.value = getCurrentTheme();
    }

    /**
     * Set up the header theme dropdown
     */
    function setupHeaderDropdown() {
        const dropdown = document.getElementById('theme-dropdown');
        if (!dropdown) return;

        // Populate dropdown (always repopulate to ensure it has options)
        populateThemeDropdown(dropdown);

        // Only add event listeners if not already added (prevent duplicates)
        if (!dropdown.dataset.themeInitialized) {
            dropdown.dataset.themeInitialized = 'true';

            // Handle change
            dropdown.addEventListener('change', (e) => {
                setTheme(e.target.value, true);
            });

            // Update dropdown when theme changes elsewhere
            window.addEventListener('themechange', (e) => {
                const currentDropdown = document.getElementById('theme-dropdown');
                if (currentDropdown && currentDropdown.value !== e.detail.theme) {
                    currentDropdown.value = e.detail.theme;
                }
            });
        }

        // Always ensure current value is set
        dropdown.value = getCurrentTheme();
    }

    /**
     * Cycle to next theme (for quick toggle button)
     */
    function cycleTheme() {
        const current = getCurrentTheme();
        let currentIndex = THEME_CYCLE.indexOf(current);

        // If current theme is not in cycle (e.g., high-contrast), start from beginning
        if (currentIndex === -1) {
            currentIndex = 0;
        } else {
            currentIndex = (currentIndex + 1) % THEME_CYCLE.length;
        }

        const nextTheme = THEME_CYCLE[currentIndex];
        setTheme(nextTheme);
        return nextTheme;
    }

    /**
     * Update theme toggle button UI
     */
    function updateThemeToggles(rawTheme, effectiveTheme) {
        // Update quick toggle button in nav
        const quickToggle = document.getElementById('theme-toggle');
        if (quickToggle) {
            // Show icon for CURRENT theme (what's active now)
            const currentIcon = THEMES[effectiveTheme]?.icon || 'fa-palette';
            // bearer:disable javascript_lang_dangerous_insert_html
            quickToggle.innerHTML = `<i class="fas ${currentIcon}"></i>`;

            // Set tooltip for next theme in cycle
            const nextIndex = (THEME_CYCLE.indexOf(rawTheme) + 1) % THEME_CYCLE.length;
            const nextTheme = THEME_CYCLE[nextIndex] || 'hashed';
            quickToggle.setAttribute('title', `Switch to ${THEMES[nextTheme]?.label || nextTheme} theme`);
            quickToggle.setAttribute('aria-label', `Current theme: ${THEMES[rawTheme]?.label || rawTheme}. Click to switch.`);
        }

        // Update theme selector dropdown if on settings page
        const themeSelector = document.querySelector('select[data-key="app.theme"], #theme-select, select[name="app.theme"]');
        if (themeSelector && themeSelector.value !== rawTheme) {
            themeSelector.value = rawTheme;
        }
    }

    /**
     * Listen for system theme changes
     */
    function setupSystemThemeListener() {
        const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

        mediaQuery.addEventListener('change', (e) => {
            const currentTheme = getCurrentTheme();
            if (currentTheme === 'system') {
                SafeLogger.log('System theme changed, updating...');
                applyTheme('system');
            }
        });
    }

    /**
     * Clear theme from localStorage (for logout)
     */
    function clearTheme() {
        const storageKey = getStorageKey();
        localStorage.removeItem(storageKey);

        // Also clear anonymous key if exists
        localStorage.removeItem(`${STORAGE_KEY_PREFIX}-anonymous`);

        SafeLogger.log('Theme cleared from localStorage');
    }

    /**
     * Clear ALL theme keys from localStorage (for full cleanup)
     */
    function clearAllThemes() {
        const keysToRemove = [];
        for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i);
            if (key && key.startsWith(STORAGE_KEY_PREFIX)) {
                keysToRemove.push(key);
            }
        }
        keysToRemove.forEach(key => localStorage.removeItem(key));
        SafeLogger.log('All theme keys cleared:', keysToRemove);
    }

    /**
     * Initialize theme on page load
     */
    function initializeTheme() {
        // Get stored theme - FOUC prevention script in <head> already applied it
        const storedTheme = getCurrentTheme();

        // Validate stored theme (in case localStorage was corrupted)
        // bearer:disable javascript_lang_observable_timing — timing comparison on public theme names, not secrets
        const validatedTheme = VALID_THEMES.includes(storedTheme) ? storedTheme : 'hashed';
        if (validatedTheme !== storedTheme) {
            SafeLogger.warn('Invalid stored theme, resetting to hashed');
            applyTheme(validatedTheme);
        }

        // Try to load from server and sync (for logged-in users)
        // Only update if server theme is valid AND different
        loadThemeFromServer().then(serverTheme => {
            if (serverTheme && VALID_THEMES.includes(serverTheme) && serverTheme !== getCurrentTheme()) {
                SafeLogger.log('Server has different theme, syncing:', serverTheme);
                applyTheme(serverTheme);
            }
        });

        // Set up system preference listener
        setupSystemThemeListener();

        // Set up header theme dropdown (new)
        setupHeaderDropdown();

        // Set up quick toggle button (legacy, kept for compatibility)
        const quickToggle = document.getElementById('theme-toggle');
        if (quickToggle) {
            quickToggle.addEventListener('click', (e) => {
                e.preventDefault();
                cycleTheme();
            });
            updateThemeToggles(validatedTheme, getEffectiveTheme(validatedTheme));
        }

        SafeLogger.log('Theme service initialized with', Object.keys(THEMES).length, 'themes');
    }

    // Expose API globally
    window.themeService = {
        THEMES,
        THEME_CYCLE,
        VALID_THEMES,
        getCurrentTheme,
        getEffectiveTheme,
        setTheme,
        cycleTheme,
        loadThemeFromServer,
        saveThemeToServer,
        clearTheme,
        clearAllThemes,
        initializeTheme,
        applyTheme,
        populateThemeDropdown,
        setupHeaderDropdown
    };

    // Initialize when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initializeTheme);
    } else {
        // DOM already loaded, initialize immediately
        initializeTheme();
    }

    // Handle back-forward cache (bfcache) - reinitialize dropdown when page is restored
    window.addEventListener('pageshow', function(event) {
        if (event.persisted) {
            // Page was restored from bfcache, reinitialize dropdown
            SafeLogger.log('Page restored from bfcache, reinitializing theme dropdown');
            setupHeaderDropdown();
        }
    });

    // Also handle visibilitychange for tab switching
    document.addEventListener('visibilitychange', function() {
        if (document.visibilityState === 'visible') {
            // Ensure dropdown is populated when tab becomes visible
            const dropdown = document.getElementById('theme-dropdown');
            if (dropdown && dropdown.options.length === 0) {
                SafeLogger.log('Theme dropdown was empty, repopulating');
                setupHeaderDropdown();
            }
        }
    });
})();
