use std::str::FromStr;

use leptos::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
pub enum Theme {
    Light,
    Dark,
    #[default]
    Auto,
}

impl std::fmt::Display for Theme {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let s = match self {
            Theme::Light => "light",
            Theme::Dark => "dark",
            Theme::Auto => "auto",
        };
        write!(f, "{}", s)
    }
}

impl FromStr for Theme {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "light" => Ok(Theme::Light),
            "dark" => Ok(Theme::Dark),
            "auto" => Ok(Theme::Auto),
            _ => Err(format!("Unknown theme: {}", s)),
        }
    }
}

#[component]
pub fn ThemeProvider(children: Children) -> impl IntoView {
    let app_state = crate::store::use_app_state();
    let app_state_clone = app_state.clone();

    // Set up theme change listener
    Effect::new(move |_| {
        let theme = app_state.get_theme();
        apply_theme_to_dom(theme);
    });

    // Listen for system theme changes when in auto mode
    Effect::new(move |_| {
        if app_state_clone.get_theme() == Theme::Auto {
            // Set up media query listener for system theme changes
            if let Some(window) = web_sys::window() {
                if let Ok(Some(_media_query)) = window.match_media("(prefers-color-scheme: dark)") {
                    apply_theme_to_dom(Theme::Auto);
                }
            }
        }
    });

    children()
}

fn apply_theme_to_dom(theme: Theme) {
    if let Some(document) = web_sys::window().and_then(|w| w.document()) {
        if let Some(html) = document.document_element() {
            let theme_str = match theme {
                Theme::Light => "light",
                Theme::Dark => "dark",
                Theme::Auto => {
                    // Check system preference
                    if web_sys::window()
                        .and_then(|w| w.match_media("(prefers-color-scheme: dark)").ok())
                        .flatten()
                        .map(|mq| mq.matches())
                        .unwrap_or(false)
                    {
                        "dark"
                    } else {
                        "light"
                    }
                }
            };
            let _ = html.set_attribute("data-theme", theme_str);
        }
    }
}
