import { useId } from 'react';

import type { Lernplan } from '../../../../shared/lernplan';
import type { LernplanZustand } from '../../hooks/useLernplan';
import type { Lernstand } from '../../hooks/useLernstand';
import { Reifeampel } from './Reifeampel';
import { Hinweis } from './Hinweis';

export interface EinstiegProps {
  readonly einstiegRef: React.RefObject<HTMLHeadingElement | null>;
  readonly lernstand: Lernstand;
  readonly lernplan: LernplanZustand;
  readonly katalogBereit: boolean;
  readonly onWeiterlernen: () => void;
  readonly onKapitelWahl: () => void;
  readonly onNurFehler: () => void;
  readonly onGemerkte: () => void;
  readonly onOffeneFragen: () => void;
}

/**
 * Der erste Bildschirm: Wo stehe ich, was ist heute dran, und los.
 *
 * **Warum es diese Karte gibt.** Vorher stand der Weg ins Lernen ganz unten:
 * nachgemessen 2659 Pixel vom Seitenanfang, bei 1063 Pixel sichtbarer Höhe –
 * zweieinhalb Bildschirme Statusbericht, bevor man eine einzige Frage
 * beantworten konnte. Wer täglich lernt, will nicht täglich scrollen.
 *
 * Hier stehen deshalb nur zwei Zahlen: wie weit man ist und was heute
 * ansteht. Alles Weitere – Zahlen je Kapitel, Prognose, Termin – bleibt
 * erhalten, rückt aber unter die Handlung. Nichts ist gestrichen, nur neu
 * geordnet.
 */
/**
 * Was heute ansteht – und was heute schon geschehen ist.
 *
 * ## Warum die Zahl nach der ersten Antwort eine andere wird
 *
 * `pensum.gesamt` ist `neu + fällig`, und `neu` ist keine Menge, sondern eine
 * **Rate, die sich nachfüllt** – gebildet in `einfuehrungsrate()`
 * (`shared/lernplan.ts`) und dort täglich neu: ohne Prüfungstermin
 * `Math.min(nieBeantwortet, SITZUNGSUMFANG)`, mit Termin
 * `Math.ceil(nieBeantwortet / einfuehrungstage(tageBisTermin))`, am Termin und
 * danach 0. Wer zwanzig neue Fragen bearbeitet, las bisher danach erneut
 * „Heute 20 Fragen“ – ein Satz, der als Äußerung falsch ist, weil er nach
 * getaner Arbeit dasselbe verlangt wie davor.
 *
 * Deshalb nennt der Satz, sobald heute etwas geschehen ist, die geleistete
 * Arbeit **und** beide Restgrössen einzeln. Beide, nicht nur die fällige: Wer
 * einen Prüfungstermin hat, entscheidet über die neuen Fragen, ob der Katalog
 * bis dahin überhaupt einmal durchläuft.
 *
 * ## Was hier ausdrücklich nicht steht
 *
 * Kein Ring, kein Bruch, kein Prozentwert, kein Wort „Ziel“ und keine Null.
 * Wer heute nichts getan hat, liest den Satz von vorher – nicht „Heute 0
 * Fragen bearbeitet“. Die Begründung steht in
 * `docs/entscheidung-motivation.md`.
 */
function pensumSatz(plan: Lernplan, heuteBearbeitet: number): string {
  const { neu, wiederholung, gesamt, minuten } = plan.pensum;

  /*
    Am Prüfungstag selbst zuerst, vor allem anderen: Neue Fragen kommen keine
    mehr dazu (siehe `lernplan.ts`), und wer heute geprüft wird, will keine
    Empfehlung, sondern eine Auskunft. Wiederholungen bleiben sinnvoll – wer
    um 18 Uhr antritt, darf morgens auffrischen.
  */
  if (plan.tageBisTermin === 0) {
    return wiederholung === 0
      ? 'Heute ist Ihr Prüfungstermin. Es steht nichts mehr an.'
      : `Heute ist Ihr Prüfungstermin. Neue Fragen kommen keine mehr dazu; zum Auffrischen ` +
          `stehen ${fragen(wiederholung)} zur Wiederholung bereit.`;
  }

  /* Nach dem Termin setzt der Lernplan `neu` auf 0 – nicht weil alles gesehen
     wäre, sondern weil es nichts mehr zu verteilen gibt. „Auf dem Laufenden“
     wäre dann eine Behauptung über den Katalog, die nicht stimmt. */
  const terminVorbei = plan.machbarkeit === 'termin_vorbei';

  if (heuteBearbeitet === 0) {
    if (gesamt === 0) {
      return terminVorbei
        ? 'Der eingetragene Prüfungstermin ist verstrichen. Tragen Sie einen neuen ein, dann plant das Programm wieder.'
        : 'Heute steht nichts an – Sie sind auf dem Laufenden.';
    }
    return `Heute ${String(gesamt)} Fragen, etwa ${String(minuten)} Minuten.`;
  }

  const geleistet = `Heute ${fragen(heuteBearbeitet)} bearbeitet`;
  const offen: string[] = [];
  if (wiederholung > 0) {
    offen.push(`${String(wiederholung)} zur Wiederholung`);
  }
  if (neu > 0) {
    offen.push(`${String(neu)} neue`);
  }

  if (offen.length === 0) {
    return terminVorbei
      ? `${geleistet}. Der eingetragene Prüfungstermin ist verstrichen.`
      : `${geleistet} – Sie sind auf dem Laufenden.`;
  }
  return `${geleistet}; offen sind noch ${offen.join(' und ')}.`;
}

function fragen(anzahl: number): string {
  return anzahl === 1 ? '1 Frage' : `${String(anzahl)} Fragen`;
}

export function Einstieg({
  einstiegRef,
  lernstand,
  lernplan,
  katalogBereit,
  onWeiterlernen,
  onKapitelWahl,
  onNurFehler,
  onGemerkte,
  onOffeneFragen,
}: EinstiegProps): React.JSX.Element {
  const uebersicht = lernstand.uebersicht;
  const plan = lernplan.plan;
  const gemerkteAnzahl = uebersicht?.gemerkt ?? null;
  const offeneAnzahl = uebersicht?.offen ?? null;
  const grundId = useId();

  /*
    Gesperrt heißt hier: erreichbar, aber wirkungslos. Alle fünf Knöpfe melden
    sich über `aria-disabled` (Projektregel, docs/stand.md 7.13) und kehren
    früh zurück. Ein natives `disabled` nähme ihnen den Fokus – und wer sich
    gerade auf „Weiterlernen“ befand, als der Katalogfehler eintraf, säße
    danach auf `<body>` am Seitenanfang.
  */
  const nurWennBereit = (handeln: () => void) => (): void => {
    if (katalogBereit) {
      handeln();
    }
  };
  const gesperrtBeschreibung = katalogBereit ? {} : { 'aria-describedby': grundId };

  /*
    Bei mehreren Profilen muss ohne Nachsehen erkennbar sein, wessen Zahlen
    hier stehen. Wer allein lernt, sieht die Zeile nicht: Sein eigener Name
    über seinem eigenen Fortschritt ist keine Auskunft, sondern Beiwerk.
  */
  const aktuellesProfil =
    lernstand.profile.length > 1
      ? (lernstand.profile.find((profil) => profil.id === lernstand.profilId)?.name ?? null)
      : null;

  return (
    <section className="karte abschnitt einstieg" aria-labelledby="einstieg-titel">
      <h2 id="einstieg-titel" ref={einstiegRef} tabIndex={-1}>
        Heute lernen
      </h2>

      {aktuellesProfil === null ? null : (
        <p className="einstieg__profil">
          Lernstand von <strong>{aktuellesProfil}</strong>
        </p>
      )}

      {/* Nur Stufe, Satz und Balken. Die Erläuterung „Was heißt das?“ und die
          Zahlen je Bereich stehen weiter unten in „Ihr Lernstand im
          Einzelnen“ – diese Karte hat ein gemessenes Höhenbudget, damit der
          Weg ins Lernen im ersten Bildschirm bleibt (e2e/blickfeld.spec.ts). */}
      {uebersicht === null ? null : (
        <Reifeampel
          belegt={uebersicht.belegt}
          fragenGesamt={uebersicht.fragenGesamt}
          stufe={uebersicht.stufe}
          deckelnd={uebersicht.deckelnd}
          beschriftung="Prüfungsreife insgesamt"
        />
      )}

      {plan === null ? null : (
        <p className="einstieg__pensum">{pensumSatz(plan, uebersicht?.heuteBearbeitet ?? 0)}</p>
      )}

      {lernstand.meldung !== null ? <Hinweis art="hinweis">{lernstand.meldung}</Hinweis> : null}

      {/* Die Erklärung steht vor den Schaltflächen: Wer nicht weiterkommt,
          soll sie gelesen haben, bevor er den gesperrten Knopf erreicht. Die
          Knöpfe verweisen zusätzlich über `aria-describedby` darauf. */}
      {katalogBereit ? null : (
        <p className="startwahl__gesperrt" id={grundId}>
          Solange der Fragenkatalog nicht geladen ist, lässt sich keine Lernsitzung starten.
        </p>
      )}

      <div className="startwahl">
        <button
          type="button"
          className="knopf knopf--haupt startwahl__knopf"
          aria-disabled={!katalogBereit}
          {...gesperrtBeschreibung}
          onClick={nurWennBereit(onWeiterlernen)}
        >
          <span className="startwahl__name">Weiterlernen</span>
          <span className="startwahl__erklaerung">20 Fragen, vom Programm zusammengestellt</span>
        </button>

        <button
          type="button"
          className="knopf startwahl__knopf"
          aria-disabled={!katalogBereit}
          {...gesperrtBeschreibung}
          onClick={nurWennBereit(onKapitelWahl)}
        >
          <span className="startwahl__name">Kapitel wählen</span>
          <span className="startwahl__erklaerung">Gezielt ein Kapitel oder einen Abschnitt</span>
        </button>

        <button
          type="button"
          className="knopf startwahl__knopf"
          aria-disabled={!katalogBereit}
          {...gesperrtBeschreibung}
          onClick={nurWennBereit(onNurFehler)}
        >
          <span className="startwahl__name">Nur Fehler</span>
          <span className="startwahl__erklaerung">
            Fragen, die zuletzt falsch beantwortet wurden
          </span>
        </button>

        <button
          type="button"
          className="knopf startwahl__knopf"
          aria-disabled={!katalogBereit}
          {...gesperrtBeschreibung}
          onClick={nurWennBereit(onGemerkte)}
        >
          <span className="startwahl__name">Gemerkte Fragen</span>
          <span className="startwahl__erklaerung">
            {gemerkteAnzahl === null
              ? 'Ihre Merkliste'
              : `Ihre Merkliste: ${fragen(gemerkteAnzahl)}`}
          </span>
        </button>

        {/*
          Offene Fragen sind der Teil der Prüfung, den ein Mensch bewertet –
          und der einzige, den sich niemand durch Ankreuzen erschließen kann.
          Sie machen 104 der 575 Fragen aus, verteilen sich aber sehr ungleich
          (Kapitel I 61, II 13, III 1, IV 29). Wer sie gezielt üben will,
          bekam sie bisher nur zufällig zwischen den Auswahlfragen vorgelegt:
          Bei zwanzig Fragen im Mittel dreieinhalb.

          Die Zahl steht an der Schaltfläche, weil sie sich mit dem Zielprofil
          ändert – ohne Kapitel IV sind es 75 statt 104.
        */}
        <button
          type="button"
          className="knopf startwahl__knopf"
          aria-disabled={!katalogBereit}
          {...gesperrtBeschreibung}
          onClick={nurWennBereit(onOffeneFragen)}
        >
          <span className="startwahl__name">Offene Fragen</span>
          <span className="startwahl__erklaerung">
            {offeneAnzahl === null
              ? 'Fragen zum Ausformulieren'
              : `Zum Ausformulieren: ${fragen(offeneAnzahl)}`}
          </span>
        </button>
      </div>
    </section>
  );
}
