import { useId } from 'react';

import {
  profilFinden,
  URTEIL_BEZEICHNUNG,
  ZEITMODUS_BEZEICHNUNG,
} from '../../../../shared/pruefung';
import type { KatalogIndex } from '../../hooks/useKatalog';
import { usePruefungsverlauf } from '../../hooks/usePruefungsverlauf';
import type { Pruefungsabschluss } from '../../pruefung/typen';
import { wirksamesProfil, zeitmodusText } from '../../pruefung/auftrag';
import { dauerText } from '../../pruefung/zeit';
import { Fortschritt } from '../lernen/Fortschritt';
import { Hinweis } from '../lernen/Hinweis';
import { useErklaerungen } from '../../hooks/useErklaerungen';
import { useVorlesen } from '../../hooks/useVorlesen';
import { Erklaerungstafel } from '../lernen/Erklaerungstafel';
import { Laufvergleich } from './Laufvergleich';
import { Themenanalyse } from './Themenanalyse';
import { WiederkehrendeSchwaechen } from './WiederkehrendeSchwaechen';
import { URTEIL_SYMBOL } from './urteil';

/**
 * Die gewählte Zeitstufe als Satz – mit Minuten, wo es welche gibt.
 *
 * Beim frei eingestellten Profil zählt die überschriebene Minutenzahl,
 * deshalb der Umweg über {@link wirksamesProfil}. Ist das Profil unbekannt
 * (eine alte Simulation, deren Profil es nicht mehr gibt), bleibt die Angabe
 * ehrlich vage, statt eine Zahl zu erfinden.
 */
function zeitvorgabeText(abschluss: Pruefungsabschluss): string {
  const basis = profilFinden(abschluss.auftrag.profilId);
  if (basis === undefined) {
    return ZEITMODUS_BEZEICHNUNG[abschluss.auftrag.zeitmodus];
  }
  return zeitmodusText(wirksamesProfil(basis, abschluss.auftrag), abschluss.auftrag.zeitmodus);
}
import { Verlaufsliste } from './Verlaufsliste';

export interface PruefungsauswertungProps {
  readonly abschluss: Pruefungsabschluss;
  readonly katalogIndex: KatalogIndex | null;
  readonly profilId: number | null;
  readonly einstiegRef: React.RefObject<HTMLHeadingElement | null>;
  /** Sprachausgabe eingeschaltet (Einstellung „Vorlesen“). */
  readonly vorlesenAktiv?: boolean;
  /** Sprechgeschwindigkeit; Stufen in `shared/sprechtempo.ts`. */
  readonly sprechtempo?: number;
  readonly onFehlerWiederholen: (frageIds: readonly string[]) => void;
  readonly onNeueSimulation: () => void;
  readonly onZumStart: () => void;
}

/**
 * Auswertung einer Simulation.
 *
 * Das Urteil steht groß und dreifach kodiert oben: Symbol, Wort und Farbe. Die
 * Begründung kommt unverändert aus dem Vertrag ({@link urteilBilden}), damit
 * Anwendungskern und Oberfläche nicht verschieden begründen.
 */
export function Pruefungsauswertung({
  abschluss,
  katalogIndex,
  profilId,
  einstiegRef,
  vorlesenAktiv = false,
  sprechtempo,
  onFehlerWiederholen,
  onNeueSimulation,
  onZumStart,
}: PruefungsauswertungProps): React.JSX.Element {
  const { ergebnis } = abschluss;
  const titelId = useId();
  const fehlerTitelId = useId();
  const kriterienTitelId = useId();
  const verlauf = usePruefungsverlauf(profilId);
  const erklaerungen = useErklaerungen();
  /* Eine Instanz für die ganze Auswertung: Jede aufgeklappte Erklärung
     bekommt dieselbe: Zwei Tafeln, die gleichzeitig sprechen, gäbe es
     ohnehin nicht – die Sprachausgabe hat nur eine Stimme. */
  const stimme = useVorlesen(vorlesenAktiv, 'auswertung', sprechtempo);

  const prozent = Math.round(ergebnis.quote * 100);

  return (
    <section className="pruefungsauswertung abschnitt" aria-labelledby={titelId}>
      <h1 id={titelId} ref={einstiegRef} tabIndex={-1}>
        Auswertung der Prüfungssimulation
      </h1>

      <p className="pruefungsauswertung__profil">Profil: {abschluss.profilName}</p>

      <div className={`urteil urteil--${ergebnis.urteil}`}>
        <p className="urteil__zeile">
          <span className="urteil__symbol" aria-hidden="true">
            {URTEIL_SYMBOL[ergebnis.urteil]}
          </span>
          <span className="urteil__text">{URTEIL_BEZEICHNUNG[ergebnis.urteil]}</span>
        </p>
        <p className="urteil__begruendung">{ergebnis.begruendung}</p>
      </div>

      {ergebnis.verletzteKriterien.length > 0 ? (
        <div className="pruefungsauswertung__kriterien">
          <h2 id={kriterienTitelId}>Verletzte Zusatzbedingungen</h2>
          <ul aria-labelledby={kriterienTitelId}>
            {ergebnis.verletzteKriterien.map((kriterium) => (
              <li key={kriterium}>{kriterium}</li>
            ))}
          </ul>
        </div>
      ) : null}

      {ergebnis.zeitAbgelaufen ? (
        <Hinweis art="hinweis">
          Die Bearbeitungszeit war abgelaufen. Die Simulation wurde daraufhin automatisch abgegeben.
        </Hinweis>
      ) : null}

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

      <p className="pruefungsauswertung__quote">
        {ergebnis.richtig} von {ergebnis.gesamt} Fragen richtig – Trefferquote {prozent} Prozent.
      </p>
      <Fortschritt
        beschriftung="Trefferquote dieser Simulation"
        text={`Trefferquote ${String(prozent)} Prozent`}
        wert={prozent}
        minimum={0}
        maximum={100}
      />

      <dl className="pruefungsauswertung__zahlen">
        <dt>Fragen im Bogen</dt>
        <dd>{ergebnis.gesamt}</dd>

        <dt>Richtig</dt>
        <dd>{ergebnis.richtig}</dd>

        <dt>Falsch</dt>
        <dd>{ergebnis.falsch}</dd>

        <dt>Nicht beantwortet</dt>
        <dd>{ergebnis.unbeantwortet}</dd>

        {/* Ohne diese Zeile stünden eine Simulation ohne Uhr und eine unter
            Zeitdruck mit identischen Spalten nebeneinander – ausdrücklich zum
            Vergleich eingeladen, obwohl sie nicht vergleichbar sind. */}
        <dt>Zeitvorgabe</dt>
        <dd>{zeitvorgabeText(abschluss)}</dd>

        <dt>Bearbeitungsdauer</dt>
        <dd>{dauerText(ergebnis.dauerMs)}</dd>
      </dl>

      {/* Die Einordnung musste der Lernende bis 0.22.0 im Kopf rechnen: Die
          Auswertung nannte die Zahlen des Tages, die Tabelle ganz unten die
          alten. Verglichen wird nur mit demselben Profil und derselben
          Zeitstufe – alles andere wären zwei verschiedene Aufgaben. */}
      <Laufvergleich
        aktuell={{
          profilId: ergebnis.profilId,
          zeitmodus: abschluss.auftrag.zeitmodus,
          gesamt: ergebnis.gesamt,
          quote: ergebnis.quote,
          dauerMs: ergebnis.dauerMs,
          unbeantwortet: ergebnis.unbeantwortet,
          zeitAbgelaufen: ergebnis.zeitAbgelaufen,
          ...(ergebnis.laufId === undefined ? {} : { laufId: ergebnis.laufId }),
        }}
        verlauf={verlauf.eintraege}
      />

      <Themenanalyse bereiche={ergebnis.bereiche} />

      <WiederkehrendeSchwaechen verlauf={verlauf.eintraege} />

      <div className="pruefungsauswertung__fehler">
        {/* „Nicht richtig" statt „falsch": Die Liste enthält auch die Fragen,
            die gar nicht bearbeitet wurden – in der Prüfung bringt eine leere
            Antwort keinen Punkt, und geübt werden sollten sie erst recht. */}
        <h2 id={fehlerTitelId}>Nicht richtig beantwortete Fragen</h2>
        {ergebnis.fehlerIds.length === 0 ? (
          <p>Keine – Sie haben alle Fragen richtig gelöst.</p>
        ) : (
          <ul className="pruefungsauswertung__fehlerliste" aria-labelledby={fehlerTitelId}>
            {ergebnis.fehlerIds.map((frageId) => {
              const frage = katalogIndex?.frage(frageId);
              const erklaerung = erklaerungen.zu(frageId);
              return (
                <li key={frageId}>
                  <span className="pruefungsauswertung__nummer">
                    Frage {frage?.amtliche_nummer ?? frageId}
                  </span>{' '}
                  {frage?.frage.text ?? ''}
                  {/* Zugeklappt, damit die Liste überschaubar bleibt: Nach
                      einer Simulation stehen hier bis zu 80 Fragen. Wer den
                      Grund wissen will, klappt genau die eine auf. */}
                  {erklaerung === null ? null : (
                    <details className="pruefungsauswertung__erklaerung">
                      <summary>
                        Warum war das falsch?
                        {/* Der Bezug muss im zugänglichen Namen stehen: In
                            einer Liste mit 80 Einträgen wäre „Warum war das
                            falsch?" allein nicht unterscheidbar. */}
                        <span className="nur-screenreader">
                          {' '}
                          – Frage {frage?.amtliche_nummer ?? frageId}
                        </span>
                      </summary>
                      {/* Hier fehlte die Stimme ganz: Wer mit der
                          Vorlesefunktion lernt, wurde ausgerechnet in der
                          Nachbereitung der Simulation – dem lernwirksamsten
                          Moment – auf stilles Lesen zurückgeworfen. */}
                      {/* `ebene={3}`: Darüber steht die h2 „Nicht richtig
                          beantwortete Fragen“. Der Standardwert 4 nimmt an,
                          die Tafel liege unter einer h3 – hier gibt es keine,
                          und die Gliederung übersprang bis 0.24.1 eine
                          Ebene. */}
                      <Erklaerungstafel
                        erklaerung={erklaerung}
                        ebene={3}
                        {...(vorlesenAktiv && stimme.moeglich ? { stimme } : {})}
                      />
                    </details>
                  )}
                </li>
              );
            })}
          </ul>
        )}
      </div>

      <div className="pruefungsauswertung__aktionen">
        {ergebnis.fehlerIds.length > 0 ? (
          <button
            type="button"
            className="knopf knopf--haupt"
            onClick={() => {
              onFehlerWiederholen(ergebnis.fehlerIds);
            }}
          >
            Fehler wiederholen ({ergebnis.fehlerIds.length})
          </button>
        ) : null}
        <button type="button" className="knopf" onClick={onNeueSimulation}>
          Neue Simulation vorbereiten
        </button>
        <button type="button" className="knopf knopf--leise" onClick={onZumStart}>
          Zum Start
        </button>
      </div>

      <Verlaufsliste
        laedt={verlauf.laedt}
        eintraege={verlauf.eintraege}
        meldung={verlauf.meldung}
      />

      <Hinweis art="hinweis">
        Dieses Ergebnis ist eine Übung, keine Prognose. Reale Prüfungen unterscheiden sich je nach
        Prüfungsstelle in Fragenzahl, Zeit, Bestehensgrenze und Bewertung offener Antworten. Sie
        umfassen zudem einen praktischen Teil, den diese Anwendung nicht abbildet. Über das Bestehen
        entscheidet allein der zuständige Prüfungsausschuss.
      </Hinweis>
    </section>
  );
}
