//! Theme toggle component
//!
//! Provides a button to toggle between light and dark themes.
//! Theme preference is persisted to localStorage.

/// Theme preference
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Theme {
    /// Light theme
    #[default]
    Light,
    /// Dark theme
    Dark,
}

impl Theme {
    /// Get the display icon for the theme
    pub fn icon(&self) -> &'static str {
        match self {
            Self::Light => "☀️",
            Self::Dark => "🌙",
        }
    }

    /// Get the CSS class for the theme
    pub fn css_class(&self) -> &'static str {
        match self {
            Self::Light => "light",
            Self::Dark => "dark",
        }
    }

    /// Toggle to the opposite theme
    pub fn toggle(&self) -> Self {
        match self {
            Self::Light => Self::Dark,
            Self::Dark => Self::Light,
        }
    }

    /// Parse theme from string
    pub fn parse_theme(s: &str) -> Self {
        match s.to_lowercase().as_str() {
            "dark" => Self::Dark,
            _ => Self::Light,
        }
    }
}

/// Generate HTML for the theme toggle button
///
/// # Arguments
///
/// * `current_theme` - Current theme (Light or Dark)
///
/// # Returns
///
/// HTML string for the theme toggle button
pub fn theme_toggle_html(current_theme: Theme) -> String {
    format!(
        r#"<button
    id="theme-toggle"
    class="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"
    title="Toggle theme (current: {})"
    aria-label="Toggle dark mode">
    <span class="text-2xl">{}</span>
</button>

<script>
    (function() {{
        // Get current theme from localStorage or default to light
        let currentTheme = localStorage.getItem('theme') || 'light';

        // Apply theme to document root
        function applyTheme(theme) {{
            if (theme === 'dark') {{
                document.documentElement.classList.add('dark');
            }} else {{
                document.documentElement.classList.remove('dark');
            }}
        }}

        // Apply initial theme
        applyTheme(currentTheme);

        // Handle toggle button click
        document.getElementById('theme-toggle')?.addEventListener('click', function() {{
            currentTheme = currentTheme === 'dark' ? 'light' : 'dark';
            localStorage.setItem('theme', currentTheme);
            applyTheme(currentTheme);

            // Update button icon
            this.querySelector('span').textContent = currentTheme === 'dark' ? '🌙' : '☀️';
            this.setAttribute('title', 'Toggle theme (current: ' + currentTheme + ')');
        }});
    }})();
</script>"#,
        current_theme.css_class(),
        current_theme.icon()
    )
}

/// Generate inline script to apply theme before page render
///
/// This should be included in the <head> to prevent flash of unstyled content.
///
/// # Returns
///
/// HTML script tag to apply theme immediately
pub fn theme_init_script() -> &'static str {
    r#"<script>
    // Apply theme immediately to prevent flash
    (function() {
        const theme = localStorage.getItem('theme') || 'light';
        if (theme === 'dark') {
            document.documentElement.classList.add('dark');
        }
    })();
</script>"#
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_theme_icon() {
        assert_eq!(Theme::Light.icon(), "☀️");
        assert_eq!(Theme::Dark.icon(), "🌙");
    }

    #[test]
    fn test_theme_css_class() {
        assert_eq!(Theme::Light.css_class(), "light");
        assert_eq!(Theme::Dark.css_class(), "dark");
    }

    #[test]
    fn test_theme_toggle() {
        assert_eq!(Theme::Light.toggle(), Theme::Dark);
        assert_eq!(Theme::Dark.toggle(), Theme::Light);
    }

    #[test]
    fn test_theme_parse() {
        assert_eq!(Theme::parse_theme("dark"), Theme::Dark);
        assert_eq!(Theme::parse_theme("Dark"), Theme::Dark);
        assert_eq!(Theme::parse_theme("DARK"), Theme::Dark);
        assert_eq!(Theme::parse_theme("light"), Theme::Light);
        assert_eq!(Theme::parse_theme("invalid"), Theme::Light);
    }

    #[test]
    fn test_theme_default() {
        assert_eq!(Theme::default(), Theme::Light);
    }

    #[test]
    fn test_theme_toggle_html() {
        let html = theme_toggle_html(Theme::Light);
        assert!(html.contains("id=\"theme-toggle\""));
        assert!(html.contains("☀️"));
        assert!(html.contains("Toggle theme"));
    }

    #[test]
    fn test_theme_init_script() {
        let script = theme_init_script();
        assert!(script.contains("<script>"));
        assert!(script.contains("localStorage.getItem('theme')"));
        assert!(script.contains("classList.add('dark')"));
    }
}
