/**
 * A `next-themes` stand-in.
 *
 * Most shadcn / 21st.dev components import `useTheme` from "next-themes",
 * which is a Next.js package and cannot run here. Rather than editing every
 * component you paste in — which defeats the point of copy-paste components —
 * Vite aliases the "next-themes" specifier to this file (see astro.config.mjs).
 *
 * It speaks the same API surface the components actually use
 * (`theme`, `resolvedTheme`, `setTheme`, `systemTheme`) but drives the
 * existing class-based theme already implemented in BaseLayout and Header:
 * a `.dark` class on <html> plus a `theme` key in localStorage.
 *
 * That means the React components and the plain-Astro header stay in sync —
 * toggling either one updates the other.
 */
import { useCallback, useEffect, useState } from "react";

export type Theme = "light" | "dark" | "system";

const STORAGE_KEY = "theme";

const prefersDark = () =>
  typeof window !== "undefined" &&
  window.matchMedia("(prefers-color-scheme: dark)").matches;

const currentIsDark = () =>
  typeof document !== "undefined" &&
  document.documentElement.classList.contains("dark");

export function useTheme() {
  // Start undefined so server render and first client render agree; components
  // gate on `mounted` before reading it, which is why they all do that dance.
  const [resolvedTheme, setResolvedTheme] = useState<"light" | "dark" | undefined>(
    undefined,
  );

  useEffect(() => {
    setResolvedTheme(currentIsDark() ? "dark" : "light");

    // Keep in step with the vanilla toggle in Header.astro.
    const observer = new MutationObserver(() => {
      setResolvedTheme(currentIsDark() ? "dark" : "light");
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"],
    });

    return () => observer.disconnect();
  }, []);

  const setTheme = useCallback((next: Theme) => {
    const dark = next === "system" ? prefersDark() : next === "dark";
    document.documentElement.classList.toggle("dark", dark);
    try {
      if (next === "system") localStorage.removeItem(STORAGE_KEY);
      else localStorage.setItem(STORAGE_KEY, next);
    } catch {
      /* private mode — the class still applies for this session */
    }
    setResolvedTheme(dark ? "dark" : "light");
  }, []);

  return {
    theme: resolvedTheme as Theme | undefined,
    resolvedTheme,
    setTheme,
    systemTheme: (prefersDark() ? "dark" : "light") as "light" | "dark",
    themes: ["light", "dark", "system"] as Theme[],
  };
}

/** No-op: the theme class is applied by the inline script in BaseLayout. */
export function ThemeProvider({ children }: { children?: React.ReactNode }) {
  return children ?? null;
}
