<script lang="ts" module>
    import { createContext } from "../create-context";

    // Define theme types
    export type Theme = "light" | "dark" | "system";

    // Create theme context
    export const { get: getThemeContext, set: setThemeContext } =
        createContext<{
            theme: Theme;
            setTheme: (theme: Theme) => void;
            subscribe?: (callback: (theme: Theme) => void) => () => void;
        }>();
</script>

<script lang="ts">
    import { onMount } from "svelte";

    // Props
    export let initialTheme: Theme = "system";

    // State with reactivity
    let theme = initialTheme;
    let mounted = false;

    // Create a custom store for the theme
    const themeStore = {
        subscribe: (callback: (theme: Theme) => void) => {
            // Initial call
            callback(theme);

            // Setup a MutationObserver to watch for class changes on documentElement
            const observer = new MutationObserver(() => {
                callback(theme);
            });

            observer.observe(document.documentElement, {
                attributes: true,
                attributeFilter: ["class"],
            });

            // Return unsubscribe function
            return () => observer.disconnect();
        },
    };

    // Set the theme in localStorage and update the DOM
    function setTheme(newTheme: Theme) {
        theme = newTheme;

        if (mounted) {
            updateTheme(theme);
            localStorage.setItem("theme", theme);
        }
    }

    // Update the DOM based on the current theme
    function updateTheme(currentTheme: Theme) {
        const isDark =
            currentTheme === "dark" ||
            (currentTheme === "system" &&
                window.matchMedia("(prefers-color-scheme: dark)").matches);

        document.documentElement.classList.toggle("dark", isDark);
    }

    // Initialize theme on mount
    onMount(() => {
        // Get stored theme or use system preference
        const storedTheme = localStorage.getItem("theme") as Theme | null;
        if (storedTheme) {
            theme = storedTheme;
        }

        // Set up system theme change listener
        const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
        const handleChange = () => {
            if (theme === "system") {
                updateTheme("system");
            }
        };

        mediaQuery.addEventListener("change", handleChange);

        // Apply initial theme
        updateTheme(theme);
        mounted = true;

        return () => {
            mediaQuery.removeEventListener("change", handleChange);
        };
    });

    // Set the context with the store
    setThemeContext({
        get theme() {
            return theme;
        },
        setTheme,
        subscribe: themeStore.subscribe,
    });
</script>

<slot />
