"use client";

import { Moon, Sun } from "lucide-react";
import {
  createContext,
  type ReactNode,
  useContext,
  useMemo,
  useSyncExternalStore,
} from "react";

import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

type DashboardTheme = "light" | "dark";

type DashboardThemeContextValue = {
  theme: DashboardTheme;
  toggleTheme: () => void;
};

const storageKey = "webdev-dashboard-theme";
const themeChangeEvent = "webdev-dashboard-theme-change";

const DashboardThemeContext =
  createContext<DashboardThemeContextValue | null>(null);

function isDashboardTheme(value: string | null): value is DashboardTheme {
  return value === "dark" || value === "light";
}

function getStoredDashboardTheme(): DashboardTheme {
  const storedTheme = window.localStorage.getItem(storageKey);

  return isDashboardTheme(storedTheme) ? storedTheme : "light";
}

function getServerDashboardTheme(): DashboardTheme {
  return "light";
}

function subscribeToDashboardTheme(onStoreChange: () => void) {
  window.addEventListener("storage", onStoreChange);
  window.addEventListener(themeChangeEvent, onStoreChange);

  return () => {
    window.removeEventListener("storage", onStoreChange);
    window.removeEventListener(themeChangeEvent, onStoreChange);
  };
}

export function DashboardThemeProvider({ children }: { children: ReactNode }) {
  const theme = useSyncExternalStore(
    subscribeToDashboardTheme,
    getStoredDashboardTheme,
    getServerDashboardTheme,
  );

  const value = useMemo<DashboardThemeContextValue>(
    () => ({
      theme,
      toggleTheme: () => {
        const nextTheme = theme === "dark" ? "light" : "dark";
        window.localStorage.setItem(storageKey, nextTheme);
        window.dispatchEvent(new Event(themeChangeEvent));
      },
    }),
    [theme],
  );

  return (
    <DashboardThemeContext.Provider value={value}>
      <div
        suppressHydrationWarning
        className={cn(
          "min-h-dvh bg-background text-foreground md:flex",
          theme === "dark" && "dark",
        )}
      >
        {children}
      </div>
    </DashboardThemeContext.Provider>
  );
}

export function DashboardThemeToggle() {
  const context = useContext(DashboardThemeContext);

  if (!context) {
    return null;
  }

  const isDark = context.theme === "dark";
  const Icon = isDark ? Sun : Moon;

  return (
    <Button
      className="w-full justify-start"
      variant="ghost"
      onClick={context.toggleTheme}
      aria-pressed={isDark}
    >
      <Icon />
      {isDark ? "Hellmodus" : "Dunkelmodus"}
    </Button>
  );
}
