import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";

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

/** Metadata for each theme — used by Layout, MarkdownBody, InstanceGeneralSettings */
export const THEME_META: Record<Theme, { label: string; dark: boolean; bg: string; primary: string }> = {
  dark: { label: "Dark", dark: true, bg: "#000000", primary: "#faff69" },
  light: { label: "Light", dark: false, bg: "#fafafa", primary: "#166534" },
};

/** Ordered list of themes for display in theme selector UI */
export const ORDERED_THEMES: Theme[] = ["dark", "light"];

interface ThemeContextValue {
  theme: Theme;
  setTheme: (theme: Theme) => void;
  toggleTheme: () => void;
  /** @deprecated Custom themes are no longer supported. No-op retained for backwards compat. */
  applyCustomTheme: (...args: unknown[]) => void;
}

const THEME_STORAGE_KEY = "paperclip.theme";
const DARK_THEME_COLOR = "#000000";
const LIGHT_THEME_COLOR = "#fafafa";
const ThemeContext = createContext<ThemeContextValue | undefined>(undefined);

function coerceStoredTheme(raw: string | null): Theme {
  if (raw === "light") return "light";
  if (raw === "dark") return "dark";
  // Legacy values: "catppuccin-latte" was the old light; anything else defaulted to dark.
  if (raw === "catppuccin-latte") return "light";
  return "dark";
}

function resolveInitialTheme(): Theme {
  if (typeof localStorage !== "undefined") {
    const stored = localStorage.getItem(THEME_STORAGE_KEY);
    if (stored !== null) return coerceStoredTheme(stored);
  }
  if (typeof document !== "undefined") {
    return document.documentElement.classList.contains("dark") ? "dark" : "dark";
  }
  return "dark";
}

function applyTheme(theme: Theme) {
  if (typeof document === "undefined") return;
  const dark = theme === "dark";
  const root = document.documentElement;
  root.classList.toggle("dark", dark);
  root.style.colorScheme = dark ? "dark" : "light";
  const themeColorMeta = document.querySelector('meta[name="theme-color"]');
  if (themeColorMeta instanceof HTMLMetaElement) {
    themeColorMeta.setAttribute("content", dark ? DARK_THEME_COLOR : LIGHT_THEME_COLOR);
  }
}

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [theme, setThemeState] = useState<Theme>(() => resolveInitialTheme());

  const setTheme = useCallback((nextTheme: Theme) => {
    setThemeState(nextTheme);
  }, []);

  const toggleTheme = useCallback(() => {
    setThemeState((current) => (current === "dark" ? "light" : "dark"));
  }, []);

  // Deprecated no-op kept so any stale imports don't break the build.
  const applyCustomTheme = useCallback((..._args: unknown[]) => {
    void _args;
  }, []);

  useEffect(() => {
    applyTheme(theme);
    try {
      localStorage.setItem(THEME_STORAGE_KEY, theme);
    } catch (_e) {
      // Ignore local storage write failures in restricted environments.
    }
  }, [theme]);

  const value = useMemo(
    () => ({
      theme,
      setTheme,
      toggleTheme,
      applyCustomTheme,
    }),
    [theme, setTheme, toggleTheme, applyCustomTheme],
  );

  return (
    <ThemeContext.Provider value={value}>
      {children}
    </ThemeContext.Provider>
  );
}

export function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error("useTheme must be used within ThemeProvider");
  }
  return context;
}
