import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import {
  fetchSiteSettings,
  fetchSiteSettingsAdmin,
  notifySiteSettingsUpdated,
  readSiteSettingsVersion,
  SITE_SETTINGS_UPDATED_EVENT,
  SITE_SETTINGS_VERSION_KEY,
  type SiteSettings,
} from "@/lib/siteSettings";

type SiteSettingsContextValue = {
  settings: SiteSettings;
  loading: boolean;
  error: string | null;
  refresh: () => Promise<void>;
};

const SiteSettingsContext = createContext<SiteSettingsContextValue | null>(null);

type SiteSettingsProviderProps = {
  children: ReactNode;
  /** Admin dashboard uses the same public endpoint via adminApiUrl. */
  source?: "public" | "admin";
};

export function SiteSettingsProvider({ children, source = "public" }: SiteSettingsProviderProps) {
  const [settings, setSettings] = useState<SiteSettings>({
    header_layout: "default",
    footer_layout: "default",
  });
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [version, setVersion] = useState<string | null>(() => readSiteSettingsVersion());

  const refresh = useCallback(async () => {
    setError(null);
    try {
      const data = source === "admin" ? await fetchSiteSettingsAdmin() : await fetchSiteSettings();
      setSettings(data);
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to load site settings");
    } finally {
      setLoading(false);
    }
  }, [source]);

  useEffect(() => {
    void refresh();
  }, [refresh, version]);

  useEffect(() => {
    const onUpdated = () => {
      setVersion(readSiteSettingsVersion());
    };

    window.addEventListener(SITE_SETTINGS_UPDATED_EVENT, onUpdated);
    const onStorage = (event: StorageEvent) => {
      if (event.key === SITE_SETTINGS_VERSION_KEY) {
        onUpdated();
      }
    };
    window.addEventListener("storage", onStorage);

    return () => {
      window.removeEventListener(SITE_SETTINGS_UPDATED_EVENT, onUpdated);
      window.removeEventListener("storage", onStorage);
    };
  }, []);

  const value = useMemo(
    () => ({ settings, loading, error, refresh }),
    [settings, loading, error, refresh]
  );

  return <SiteSettingsContext.Provider value={value}>{children}</SiteSettingsContext.Provider>;
}

export function useSiteSettings(): SiteSettingsContextValue {
  const ctx = useContext(SiteSettingsContext);
  if (!ctx) {
    throw new Error("useSiteSettings must be used within SiteSettingsProvider");
  }
  return ctx;
}

/** Optional hook for components that may render outside the provider (e.g. tests). */
export function useSiteSettingsOptional(): SiteSettingsContextValue | null {
  return useContext(SiteSettingsContext);
}

export { notifySiteSettingsUpdated };
