import { useCallback, useEffect, useState } from 'react';

import { EINSTELLUNGEN_STANDARD, type Einstellungen } from '../../../shared/ipc';
import { bridge } from '../bridge';

export interface Einstellungssteuerung {
  readonly werte: Einstellungen;
  /** `true`, solange der gespeicherte Stand noch nicht vorliegt. */
  readonly laedt: boolean;
  /** Meldung, wenn eine Änderung nicht dauerhaft gesichert werden konnte. */
  readonly meldung: string | null;
  readonly aendern: (aenderung: Partial<Einstellungen>) => void;
}

/**
 * Die dauerhaft gespeicherten Einstellungen, außer dem Farbschema.
 *
 * Das Farbschema hat einen eigenen Hook, weil es zusätzlich gegen die
 * Systemsignale aufgelöst und sofort auf das Wurzelelement geschrieben wird;
 * hier geht es nur um Lesen, Ändern, Sichern.
 *
 * Bis der Anwendungskern geantwortet hat, gelten die Standardwerte. Das ist
 * bei diesen Feldern gefahrlos: Die beiden Schwierigkeitsregler stehen ab
 * Werk auf „aus“, ein zu früh gelesener Wert macht die Anwendung also nicht
 * unversehens schwerer; und eine Sprachausgabe, die eine Zehntelsekunde zu
 * spät scharf wird, spricht nur die erste Frage nicht mit.
 *
 * Schlägt das Speichern fehl, wird das gesagt statt verschwiegen – die
 * Einstellung gilt dann bis zum Beenden und ist danach wieder weg.
 */
export function useEinstellungen(): Einstellungssteuerung {
  const [werte, setzeWerte] = useState<Einstellungen>(EINSTELLUNGEN_STANDARD);
  /* Ohne Kanal wird nie etwas nachgeladen – dann ist der Anfangswert schon
     der Endwert. Das gleich hier zu entscheiden erspart einen Zustandswechsel
     aus dem Effekt heraus und damit eine überflüssige Renderrunde. */
  const [laedt, setzeLaedt] = useState(() => bridge()?.einstellungenLesen !== undefined);
  const [meldung, setzeMeldung] = useState<string | null>(null);

  useEffect(() => {
    let lebt = true;

    const lesen = bridge()?.einstellungenLesen;
    if (!lesen) {
      return;
    }

    void lesen()
      .then((gespeichert) => {
        if (lebt) {
          setzeWerte(gespeichert);
        }
      })
      .catch((fehler: unknown) => {
        console.warn('[einstellungen] konnten nicht gelesen werden:', fehler);
      })
      .finally(() => {
        if (lebt) {
          setzeLaedt(false);
        }
      });

    return () => {
      lebt = false;
    };
  }, []);

  const aendern = useCallback((aenderung: Partial<Einstellungen>) => {
    /* Sofort wirksam, unabhängig davon, ob das Sichern gelingt: Eine
       Einstellung, die erst nach einer Rückmeldung greift, fühlt sich kaputt
       an – und wer sie gerade umgelegt hat, will die Wirkung sehen. */
    setzeWerte((bisher) => ({ ...bisher, ...aenderung }));
    setzeMeldung(null);

    const schreiben = bridge()?.einstellungenSchreiben;
    if (!schreiben) {
      return;
    }

    void schreiben(aenderung)
      .then((neuerStand) => {
        setzeWerte(neuerStand);
      })
      .catch((fehler: unknown) => {
        console.warn('[einstellungen] konnten nicht gespeichert werden:', fehler);
        setzeMeldung(
          'Diese Einstellung konnte nicht dauerhaft gespeichert werden und gilt nur für diese Sitzung.',
        );
      });
  }, []);

  return { werte, laedt, meldung, aendern };
}
