/**
 * Die Fragenliste – ein Bogen zum Bearbeiten auf Papier.
 *
 * Der Hauptteil weist **nicht** aus, welche Antwort richtig ist; die
 * Antwortmöglichkeiten stehen vollständig da, jede mit einem Kästchen davor.
 * Ein Lösungsanhang lässt sich zuschalten und ist die Voreinstellung – der
 * Fall „ganzer Katalog ohne Lösungen“ ist der einzige, in dem gar keine
 * Auszugserwägung mehr trägt, und solange die Anfrage beim Bundesverwaltungsamt
 * aussteht, ist die vorsichtige Vorgabe die richtige.
 *
 * **Der Umfang, an wirklich gedruckten PDF gemessen:** ganzer Katalog 120
 * Seiten, im Großdruck 216; mit Lösungsanhang im Großdruck 281. Kapitel I
 * ergibt 76 Seiten, Abschnitt I.1 deren 19. Die Oberfläche nennt die
 * geschätzte Zahl vor dem Speichern.
 *
 * **Warum kein Verweis zwischen Bogen und Anhang.** Interne Anker
 * funktionieren im erzeugten PDF nachweislich; der Lesezeichenbaum dagegen
 * ist unbrauchbar – `printToPDF` verdoppelt Beschriftungen und verschluckt
 * Leerzeichen, gemessen bei 20 bis 96 Prozent der Einträge. Die Zuordnung
 * trägt deshalb die Bezeichnung selbst: Sie nennt immer Kapitel **und**
 * Nummer, weil 227 der 575 Fragen sich eine Nummer mit einer anderen teilen.
 */

import type { Kapitel } from '../katalog';
import { absatz, dokumentBauen, maskiert, type Quellenangabe } from './dokument';
import { frageblock, frageKurzbezeichnung, type Papierfrage } from './frageblock';
import type { Schriftgroesse } from './stil';

export interface Fragenlistendaten {
  /** Die Fragen in Katalogreihenfolge, bereits auf die Auswahl eingegrenzt. */
  readonly fragen: readonly Papierfrage[];
  /** Womit die Auswahl überschrieben wird, etwa „Kapitel I – Waffenrecht“. */
  readonly auswahl: string;
  readonly erstelltAm: string;
  readonly mitLoesungen: boolean;
  readonly quelle: Quellenangabe;
  readonly schriftgroesse: Schriftgroesse;
  /** Für die Zwischenüberschriften je Bereich. */
  readonly kapitel: readonly Kapitel[];
}

function datum(iso: string): string {
  const wert = new Date(iso);
  return Number.isNaN(wert.getTime())
    ? 'ohne Datum'
    : wert.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' });
}

function vorspann(anzahl: number, mitLoesungen: boolean): string {
  if (anzahl === 0) {
    return absatz('Zu dieser Auswahl enthält der Katalog keine Frage.');
  }

  const menge =
    anzahl === 1
      ? 'Dieser Bogen enthält eine Frage.'
      : `Dieser Bogen enthält ${String(anzahl)} Fragen.`;

  const loesung = mitLoesungen
    ? 'Welche Antwort richtig ist, steht im Lösungsanhang am Ende – nicht bei der Frage.'
    : 'Welche Antwort richtig ist, steht nirgends in diesem Dokument. Der Lösungsanhang lässt sich beim Erzeugen zuschalten.';

  return absatz(
    `${menge} Kreuzen Sie an, was Sie für richtig halten; offene Fragen beantworten Sie auf den Linien. ${loesung} ` +
      'Wie in der Prüfung ist bei Auswahlfragen nicht angegeben, wie viele Antworten richtig sind.',
  );
}

/**
 * Der Lösungsanhang.
 *
 * Eine Liste, keine Tabelle: Bei 575 Fragen wäre eine Tabelle mit 575 Zeilen
 * für einen Bildschirmleser mühsamer als eine Aufzählung, und mehr als zwei
 * Spalten gibt es hier ohnehin nicht.
 */
function loesungsanhang(fragen: readonly Papierfrage[]): string {
  const zeilen = fragen.map((papier) => {
    const { frage } = papier;
    const bezeichnung = maskiert(frageKurzbezeichnung(frage));
    if (frage.typ !== 'mc') {
      const text = frage.musterantwort?.text ?? 'Keine Musterantwort hinterlegt.';
      return `<li><strong>${bezeichnung}:</strong> ${maskiert(text)}</li>`;
    }
    const richtige = (frage.optionen ?? []).filter((o) => o.korrekt).map((o) => o.label);
    const wort = richtige.length > 1 ? 'Richtig sind' : 'Richtig ist';
    return `<li><strong>${bezeichnung}:</strong> ${wort} ${maskiert(richtige.join(', '))}</li>`;
  });

  return (
    `<div class="anhang">\n<h2>Lösungsanhang</h2>\n` +
    absatz(
      'Die Zuordnung läuft über Kapitel und Nummer – beides zusammen, weil sich im ' +
        'amtlichen Katalog mehrere Fragen dieselbe Nummer teilen.',
      'hinweis',
    ) +
    `\n<ul>\n${zeilen.join('\n')}\n</ul>\n</div>`
  );
}

/** Fasst die Fragen unter Zwischenüberschriften je Bereich. */
function bereiche(daten: Fragenlistendaten): string {
  const titel = new Map<string, string>();
  for (const kapitel of daten.kapitel) {
    titel.set(kapitel.id, kapitel.titel);
    for (const abschnitt of kapitel.abschnitte) {
      titel.set(abschnitt.id, abschnitt.titel);
    }
  }

  const form = { loesungZeigen: false, erklaerung: 'keine' } as const;
  const gruppen: { bereich: string; bloecke: string[] }[] = [];

  for (const papier of daten.fragen) {
    const bereich = papier.frage.abschnitt ?? papier.frage.kapitel;
    let letzte = gruppen[gruppen.length - 1];
    if (letzte?.bereich !== bereich) {
      letzte = { bereich, bloecke: [] };
      gruppen.push(letzte);
    }
    letzte.bloecke.push(frageblock(papier, form, 3));
  }

  return gruppen
    .map(
      (g) =>
        `<h2>${maskiert(g.bereich)}${titel.has(g.bereich) ? ` – ${maskiert(titel.get(g.bereich) ?? '')}` : ''}</h2>\n` +
        g.bloecke.join('\n'),
    )
    .join('\n');
}

export function fragenlisteBauen(daten: Fragenlistendaten): string {
  const abschnitte = [
    `<h2>Zu diesem Bogen</h2>\n${vorspann(daten.fragen.length, daten.mitLoesungen)}`,
    bereiche(daten),
  ];

  if (daten.mitLoesungen && daten.fragen.length > 0) {
    abschnitte.push(loesungsanhang(daten.fragen));
  }

  return dokumentBauen({
    titel: `Fragenliste – ${daten.auswahl}`,
    augenbraue: `erstellt am ${datum(daten.erstelltAm)}`,
    quelle: daten.quelle,
    schriftgroesse: daten.schriftgroesse,
    abschnitte,
  });
}

/** Vorschlag für den Dateinamen. */
export function fragenlisteDateiname(auswahl: string, erstelltAm: string): string {
  const tag = Number.isNaN(Date.parse(erstelltAm))
    ? 'ohne-datum'
    : new Date(erstelltAm).toISOString().slice(0, 10);
  const name = auswahl
    .normalize('NFKD')
    .replace(/[̀-ͯ]/gu, '')
    .replace(/[^A-Za-z0-9]+/gu, '-')
    .replace(/^-+|-+$/gu, '')
    .slice(0, 40);

  return `Fragenliste${name === '' ? '' : `-${name}`}-${tag}.pdf`;
}
