"use client";

import {
  createContext,
  useContext,
  useState,
  useEffect,
  useCallback,
  type ReactNode,
} from "react";
import { themes, getTheme, DEFAULT_THEME, type Theme } from "@/lib/themes";

interface ThemeContextValue {
  theme: Theme;
  themeName: string;
  setTheme: (name: string) => void;
}

const ThemeContext = createContext<ThemeContextValue>({
  theme: themes[0],
  themeName: DEFAULT_THEME,
  setTheme: () => {},
});

export function useTheme() {
  return useContext(ThemeContext);
}

// Unique ID for the dynamic style element
const STYLE_ID = "theme-gradient-style";

function applyTheme(theme: Theme) {
  const root = document.documentElement;

  // Toggle dark class based on theme
  if (theme.isDark) {
    root.classList.add("dark");
  } else {
    root.classList.remove("dark");
  }

  // Set all CSS custom properties from the theme
  for (const [key, value] of Object.entries(theme.vars)) {
    root.style.setProperty(key, value);
  }

  // Set the body background
  document.body.style.background = theme.bodyBg;

  // Set the gradient via a style element (body::before can't be styled inline)
  let styleEl = document.getElementById(STYLE_ID) as HTMLStyleElement | null;
  if (!styleEl) {
    styleEl = document.createElement("style");
    styleEl.id = STYLE_ID;
    document.head.appendChild(styleEl);
  }
  styleEl.textContent = `
    body::before {
      background: ${theme.bgGradient} !important;
    }
  `;

  // Store in localStorage
  try {
    localStorage.setItem("homelab-theme", theme.name);
  } catch {
    // ignore storage errors
  }
}

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [themeName, setThemeName] = useState(DEFAULT_THEME);
  const theme = getTheme(themeName);

  // Load saved theme on mount
  useEffect(() => {
    try {
      const saved = localStorage.getItem("homelab-theme");
      if (saved && themes.some((t) => t.name === saved)) {
        setThemeName(saved);
      }
    } catch {
      // ignore
    }
  }, []);

  // Apply theme whenever it changes
  useEffect(() => {
    applyTheme(theme);
  }, [theme]);

  const setTheme = useCallback((name: string) => {
    if (themes.some((t) => t.name === name)) {
      setThemeName(name);
    }
  }, []);

  return (
    <ThemeContext.Provider value={{ theme, themeName, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}
