//! Client-side theme system components
//!
//! Reactive implementations of theme components for client-side rendering.

// Re-export shared theme types
pub use ::rustelo_core_lib::{EffectiveTheme, ThemeMode, ThemeUtils};
use leptos::prelude::*;

/// Theme system context for managing application-wide theme state
#[derive(Clone)]
pub struct ThemeContext {
    pub theme_mode: ReadSignal<ThemeMode>,
    pub set_theme_mode: WriteSignal<ThemeMode>,
    pub is_dark: Memo<bool>,
}

impl Default for ThemeContext {
    fn default() -> Self {
        Self::new()
    }
}

impl ThemeContext {
    pub fn new() -> Self {
        // Initialize with theme from cookie/localStorage or fallback to System
        let initial_theme = Self::detect_initial_theme();
        let (theme_mode, set_theme_mode) = signal(initial_theme);
        let is_dark = Memo::new(move |_| theme_mode.get() == ThemeMode::Dark);

        Self {
            theme_mode,
            set_theme_mode,
            is_dark,
        }
    }

    /// Detect initial theme from browser storage
    fn detect_initial_theme() -> ThemeMode {
        #[cfg(target_arch = "wasm32")]
        {
            if let Some(window) = web_sys::window() {
                if let Some(document) = window.document() {
                    // Check localStorage first
                    if let Ok(Some(storage)) = window.local_storage() {
                        if let Ok(Some(theme_value)) = storage.get_item("theme") {
                            match theme_value.as_str() {
                                "light" => return ThemeMode::Light,
                                "dark" => return ThemeMode::Dark,
                                "system" => return ThemeMode::System,
                                _ => {}
                            }
                        }
                    }

                    // Fallback: check current document class (what theme-init.js set)
                    if let Some(html_element) = document.document_element() {
                        let class_list = html_element.class_list();
                        if class_list.contains("dark") {
                            return ThemeMode::Dark;
                        } else if class_list.contains("light") {
                            return ThemeMode::Light;
                        }
                    }
                }
            }
        }

        // Ultimate fallback for SSR or when detection fails - use Light instead of
        // System to avoid automatic dark
        ThemeMode::Light
    }
}

/// Client-side reactive theme provider
#[component]
pub fn ThemeProvider(
    #[prop(optional)] _default_theme: Option<ThemeMode>,
    #[prop(optional)] _language: Option<String>,
    children: leptos::children::ChildrenFn,
) -> impl IntoView {
    let theme_context = ThemeContext::new();
    provide_context(theme_context.clone());

    // Effect to apply theme changes to the DOM
    #[cfg(target_arch = "wasm32")]
    {
        Effect::new(move |_| {
            let theme = theme_context.theme_mode.get();
            apply_theme_to_dom(theme);
        });
    }

    children()
}

/// Client-side reactive dark mode toggle
#[component]
pub fn DarkModeToggle(#[prop(optional)] class: Option<String>) -> impl IntoView {
    let theme_context = use_context::<ThemeContext>().expect("ThemeContext must be provided");

    let handle_click = move |_| {
        let current = theme_context.theme_mode.get();
        let new_theme = match current {
            ThemeMode::Dark => ThemeMode::Light,
            ThemeMode::Light => ThemeMode::Dark,
            _ => ThemeMode::Dark,
        };
        theme_context.set_theme_mode.set(new_theme);
    };

    view! {
        <button
            class=format!("ds-theme-toggle btn-icon {}", class.unwrap_or_default())
            aria-label="Toggle theme"
            title="Toggle theme"
            on:click=handle_click
        >
            <svg
                class="w-4 h-4 theme-light-icon hidden dark:block"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
            >
                <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="2"
                    d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z">
                </path>
            </svg>
            <svg
                class="w-4 h-4 theme-dark-icon dark:hidden"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
            >
                <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="2"
                    d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z">
                </path>
            </svg>
        </button>
    }
}

/// Hook to access theme context
pub fn use_theme() -> ThemeContext {
    use_context::<ThemeContext>().expect("ThemeContext must be provided by ThemeProvider")
}

/// Apply theme to DOM by setting data attributes and classes
#[cfg(target_arch = "wasm32")]
fn apply_theme_to_dom(theme: ThemeMode) {
    if let Some(window) = web_sys::window() {
        if let Some(document) = window.document() {
            if let Some(html_element) = document.document_element() {
                // Remove existing theme classes
                let _ = html_element.class_list().remove_1("dark");
                let _ = html_element.class_list().remove_1("light");

                // Prepare theme value for persistence
                let theme_value = match theme {
                    ThemeMode::Dark => "dark",
                    ThemeMode::Light => "light",
                    ThemeMode::System => "system",
                };

                // Store in localStorage (theme-init.js will read this on next page load)
                if let Ok(Some(storage)) = window.local_storage() {
                    let _ = storage.set_item("theme", theme_value);
                }

                // Add new theme class and data attribute
                match theme {
                    ThemeMode::Dark => {
                        let _ = html_element.class_list().add_1("dark");
                        let _ = html_element.set_attribute("data-theme", "dark");
                    }
                    ThemeMode::Light => {
                        let _ = html_element.class_list().add_1("light");
                        let _ = html_element.set_attribute("data-theme", "light");
                    }
                    ThemeMode::System => {
                        // Use system preference detection
                        if let Ok(media_query) = window.match_media("(prefers-color-scheme: dark)")
                        {
                            if let Some(media_query_list) = media_query {
                                if media_query_list.matches() {
                                    let _ = html_element.class_list().add_1("dark");
                                    let _ = html_element.set_attribute("data-theme", "dark");
                                } else {
                                    let _ = html_element.class_list().add_1("light");
                                    let _ = html_element.set_attribute("data-theme", "light");
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
