import { useEffect, useState } from 'react';

import type { Pruefungsverlauf } from '../../../shared/pruefung';
import { fehlerMeldung, kanalFehltMeldung, lernBruecke } from '../lernen/bruecke';

export interface Verlaufstand {
  readonly laedt: boolean;
  readonly eintraege: readonly Pruefungsverlauf[];
  /** Erklärt in einfachen Worten, warum der Verlauf fehlt. */
  readonly meldung: string | null;
}

type Geladen =
  | { readonly art: 'laedt' }
  | { readonly art: 'fertig'; readonly eintraege: readonly Pruefungsverlauf[] }
  | { readonly art: 'fehler'; readonly meldung: string };

const LEER: readonly Pruefungsverlauf[] = Object.freeze([]);

const OHNE_KANAL = kanalFehltMeldung(
  'pruefung:verlauf',
  'Frühere Simulationen lassen sich zurzeit nicht anzeigen.',
);

const OHNE_PROFIL =
  'Ohne Lernprofil wird kein Verlauf geführt. Ihre Simulationen werden deshalb nicht gespeichert.';

/**
 * Lädt die früheren Simulationen eines Lernprofils.
 *
 * Fehlender Kanal und fehlendes Profil werden beim Rendern abgeleitet statt in
 * einem Effekt gesetzt: Beides steht ohne Nachfrage fest und braucht keinen
 * zusätzlichen Renderdurchlauf.
 */
export function usePruefungsverlauf(profilId: number | null): Verlaufstand {
  const [geladen, setzeGeladen] = useState<Geladen>({ art: 'laedt' });
  const kanalVorhanden = lernBruecke()?.pruefungVerlauf !== undefined;

  useEffect(() => {
    const verlaufLesen = lernBruecke()?.pruefungVerlauf;
    if (!verlaufLesen || profilId === null) {
      return undefined;
    }

    let abgebrochen = false;

    void verlaufLesen(profilId)
      .then((eintraege) => {
        if (!abgebrochen) {
          setzeGeladen({ art: 'fertig', eintraege });
        }
      })
      .catch((fehler: unknown) => {
        if (!abgebrochen) {
          setzeGeladen({
            art: 'fehler',
            meldung: fehlerMeldung(fehler, 'Der Verlauf konnte nicht geladen werden.'),
          });
        }
      });

    return () => {
      abgebrochen = true;
    };
  }, [profilId]);

  if (!kanalVorhanden) {
    return { laedt: false, eintraege: LEER, meldung: OHNE_KANAL };
  }
  if (profilId === null) {
    return { laedt: false, eintraege: LEER, meldung: OHNE_PROFIL };
  }

  switch (geladen.art) {
    case 'laedt':
      return { laedt: true, eintraege: LEER, meldung: null };
    case 'fertig':
      return { laedt: false, eintraege: geladen.eintraege, meldung: null };
    case 'fehler':
      return { laedt: false, eintraege: LEER, meldung: geladen.meldung };
  }
}
