import { useCallback, useMemo, useSyncExternalStore } from 'react';

import { SYSTEM_SIGNALE_STANDARD, type SystemAnzeigeSignale } from '../../../shared/theme';

const ABFRAGEN = {
  bevorzugtDunkel: '(prefers-color-scheme: dark)',
  erzwungeneFarben: '(forced-colors: active)',
  bevorzugtMehrKontrast: '(prefers-contrast: more)',
} as const satisfies Record<keyof SystemAnzeigeSignale, string>;

type SignalName = keyof typeof ABFRAGEN;

/** jsdom kennt `matchMedia` nicht immer – deshalb defensiv abfragen. */
function medienAbfrage(abfrage: string): MediaQueryList | null {
  if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
    return null;
  }
  return window.matchMedia(abfrage);
}

/**
 * Abonniert eine Media Query über `useSyncExternalStore`. Damit bleibt der
 * gerenderte Zustand auch bei nebenläufigem Rendern konsistent.
 */
function useMedienAbfrage(name: SignalName): boolean {
  const abfrage = useMemo(() => medienAbfrage(ABFRAGEN[name]), [name]);

  const abonnieren = useCallback(
    (benachrichtigen: () => void) => {
      if (!abfrage) {
        return () => undefined;
      }
      abfrage.addEventListener('change', benachrichtigen);
      return () => {
        abfrage.removeEventListener('change', benachrichtigen);
      };
    },
    [abfrage],
  );

  const lesen = useCallback(
    () => abfrage?.matches ?? SYSTEM_SIGNALE_STANDARD[name],
    [abfrage, name],
  );

  // Der Server-Snapshot ist hier irrelevant (reine Desktop-App), muss aber
  // stabil sein, damit React nicht endlos neu rendert.
  return useSyncExternalStore(abonnieren, lesen, () => SYSTEM_SIGNALE_STANDARD[name]);
}

/** Liefert die aktuellen Anzeige-Einstellungen des Betriebssystems. */
export function useSystemSignale(): SystemAnzeigeSignale {
  const bevorzugtDunkel = useMedienAbfrage('bevorzugtDunkel');
  const erzwungeneFarben = useMedienAbfrage('erzwungeneFarben');
  const bevorzugtMehrKontrast = useMedienAbfrage('bevorzugtMehrKontrast');

  return useMemo(
    () => ({ bevorzugtDunkel, erzwungeneFarben, bevorzugtMehrKontrast }),
    [bevorzugtDunkel, erzwungeneFarben, bevorzugtMehrKontrast],
  );
}
