import { useCallback, useSyncExternalStore } from "react";

const STORAGE_KEY = "gatavase:reduced-motion";

let listeners: Array<() => void> = [];
let reduced = false;

function emit() {
  for (const l of listeners) l();
}

function apply(next: boolean) {
  reduced = next;
  if (typeof document !== "undefined") {
    document.documentElement.dataset["motion"] = next ? "reduced" : "full";
  }
  emit();
}

/** Reads the stored/system preference. Call once from a client effect. */
export function initReducedMotion() {
  if (typeof window === "undefined") return;
  const stored = window.localStorage.getItem(STORAGE_KEY);
  const system = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  apply(stored === null ? system : stored === "1");
}

export function setReducedMotion(next: boolean) {
  if (typeof window !== "undefined") {
    window.localStorage.setItem(STORAGE_KEY, next ? "1" : "0");
  }
  apply(next);
}

function subscribe(cb: () => void) {
  listeners.push(cb);
  return () => {
    listeners = listeners.filter((l) => l !== cb);
  };
}

export function useReducedMotion() {
  const value = useSyncExternalStore(
    subscribe,
    () => reduced,
    () => false,
  );
  const toggle = useCallback(() => setReducedMotion(!reduced), []);
  return { reducedMotion: value, setReducedMotion, toggleReducedMotion: toggle };
}
