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

import { useFokusBeimAufbau } from '../../hooks/useFokusBeimAufbau';
import { bridge } from '../../bridge';
import { fehlerMeldung, kanalFehltMeldung } from '../../lernen/bruecke';
import { Hinweis } from './Hinweis';

type Zustand =
  | { readonly art: 'bereit' }
  | { readonly art: 'rueckfrage' }
  | { readonly art: 'laeuft' }
  | { readonly art: 'fertig' }
  | { readonly art: 'fehler'; readonly meldung: string };

export interface NeuanfangProps {
  readonly profilId: number | null;
  /** Nach dem Zurücksetzen muss die Übersicht neu geladen werden. */
  readonly onZurueckgesetzt: () => void;
}

/**
 * Von vorn anfangen.
 *
 * **Warum das überhaupt hier steht.** Der Anwendungskern konnte den Lernstand
 * seit jeher zurücksetzen – `lernen:zuruecksetzen` ist geprüft und getestet.
 * Die Oberfläche hat den Kanal nie aufgerufen. Wer neu anfangen wollte, hatte
 * keine Möglichkeit dazu.
 *
 * **Warum eine Rückfrage und kein Klick.** Der Schritt ist unwiderruflich und
 * kann Wochen Arbeit kosten. WCAG 3.3.4 verlangt für folgenreiche Aktionen
 * eine Umkehr, eine Prüfung oder eine Bestätigung; umkehren lässt sich das
 * hier nicht, also bleibt die Bestätigung. Sie steht im Textfluss statt in
 * einem modalen Dialog – wie schon bei der Prüfungsabgabe: Der Bereich holt
 * den Fokus, fängt ihn aber nicht ein (WCAG 2.1.2).
 *
 * **Warum sie sagt, was verschwindet.** Eine Rückfrage, die nur „Sind Sie
 * sicher?" fragt, hilft niemandem beim Entscheiden.
 */
export function Neuanfang({ profilId, onZurueckgesetzt }: NeuanfangProps): React.JSX.Element {
  const [zustand, setzeZustand] = useState<Zustand>({ art: 'bereit' });

  /*
    Der Weg zurück aus der Rückfrage.

    Die Rückfrage holt den Fokus zu sich. Verschwindet sie wieder, fällt er
    ohne Zutun auf `<body>` – wer per Tastatur bedient, steht dann am
    Seitenanfang und muss sich durch die ganzen Einstellungen zurückarbeiten.
    Er gehört auf den Knopf, der sie geöffnet hat. So macht es die
    Prüfungsabgabe schon (Pruefungslauf.tsx), und so muss es hier auch sein.
  */
  const ausloeserRef = useRef<HTMLButtonElement | null>(null);
  const warRueckfrage = useRef(false);

  useEffect(() => {
    const vorher = warRueckfrage.current;
    warRueckfrage.current = zustand.art === 'rueckfrage';

    if (vorher && zustand.art !== 'rueckfrage') {
      ausloeserRef.current?.focus();
    }
  }, [zustand.art]);

  const zuruecksetzen = useCallback(() => {
    const kanal = bridge()?.lernZuruecksetzen;
    if (!kanal || profilId === null) {
      setzeZustand({
        art: 'fehler',
        meldung: !kanal
          ? kanalFehltMeldung(
              'lernen:zuruecksetzen',
              'Der Lernstand lässt sich nicht zurücksetzen.',
            )
          : 'Ohne Lernprofil gibt es nichts zurückzusetzen.',
      });
      return;
    }

    setzeZustand({ art: 'laeuft' });
    void kanal(profilId, null)
      .then(() => {
        setzeZustand({ art: 'fertig' });
        onZurueckgesetzt();
      })
      .catch((fehler: unknown) => {
        setzeZustand({
          art: 'fehler',
          meldung: fehlerMeldung(fehler, 'Der Lernstand konnte nicht zurückgesetzt werden.'),
        });
      });
  }, [onZurueckgesetzt, profilId]);

  return (
    <div className="neuanfang">
      <p>
        Setzt Ihren Lernstand auf null: alle Antworten, der Fortschritt je Frage, die Merkliste und
        die abgeschlossenen Prüfungssimulationen. Der Fragenkatalog, Ihre Einstellungen und ein
        eingetragener Prüfungstermin bleiben.
      </p>

      {zustand.art === 'rueckfrage' ? (
        <Rueckfrage
          onJa={zuruecksetzen}
          onNein={() => {
            setzeZustand({ art: 'bereit' });
          }}
        />
      ) : (
        <div>
          <button
            type="button"
            className="knopf"
            ref={ausloeserRef}
            aria-disabled={zustand.art === 'laeuft'}
            onClick={() => {
              if (zustand.art !== 'laeuft') {
                setzeZustand({ art: 'rueckfrage' });
              }
            }}
          >
            {zustand.art === 'laeuft' ? 'Wird zurückgesetzt …' : 'Lernstand zurücksetzen'}
          </button>
        </div>
      )}

      <div role="status" aria-live="polite" className="neuanfang__meldung">
        {zustand.art === 'fertig' ? (
          <Hinweis art="hinweis">
            Ihr Lernstand ist zurückgesetzt. Sie beginnen wieder bei null.
          </Hinweis>
        ) : null}
        {zustand.art === 'fehler' ? <Hinweis art="fehler">{zustand.meldung}</Hinweis> : null}
      </div>
    </div>
  );
}

/** Die Rückfrage – eigener Baustein, damit der Fokus beim Aufbau greift. */
function Rueckfrage({
  onJa,
  onNein,
}: {
  readonly onJa: () => void;
  readonly onNein: () => void;
}): React.JSX.Element {
  const bereichRef = useFokusBeimAufbau<HTMLDivElement>();
  const titelId = useId();

  return (
    <div
      className="neuanfang__rueckfrage"
      ref={bereichRef}
      tabIndex={-1}
      role="group"
      aria-labelledby={titelId}
      aria-describedby={`${titelId}-text`}
    >
      <h4 className="neuanfang__titel" id={titelId}>
        Lernstand wirklich zurücksetzen?
      </h4>
      <p id={`${titelId}-text`}>
        Das lässt sich nicht rückgängig machen. Alles, was Sie bisher beantwortet haben, ist danach
        weg.
      </p>

      <div className="neuanfang__aktionen">
        {/* Das Abbrechen steht zuerst und ist die Hauptschaltfläche: Wer aus
            Versehen hier gelandet ist, trifft mit der Eingabetaste das
            Harmlose. */}
        <button type="button" className="knopf knopf--haupt" onClick={onNein}>
          Nein, alles behalten
        </button>
        <button type="button" className="knopf knopf--warnung" onClick={onJa}>
          Ja, Lernstand löschen
        </button>
      </div>
    </div>
  );
}
