/**
 * Die Datenschutzerklärung, wie die Anwendung sie zeigt.
 *
 * ## Warum sie überhaupt in der Anwendung steht
 *
 * Bis Fassung 0.24.2 war sie **nirgends** erreichbar. Das Wort
 * „Datenschutzerklärung“ kam in der ganzen Oberfläche kein einziges Mal als
 * sichtbarer Text vor; `docs/datenschutz.html` wurde nicht mitgeliefert
 * (`electron-builder.yml` führte kein `docs/`), und der einzige Weg nach
 * außen führt zur Unterstützungsseite. Zugleich sagt „Über diese Software“
 * zu, die Anwendung übertrage keine Daten — die weitreichendste Zusage nach
 * der Offline-Zusage, und ihr Beleg war für den Nutzenden unerreichbar.
 *
 * ## Warum ein Blockmodell und kein HTML
 *
 * Dieselbe Überlegung wie bei {@link Hilfeblock} in `hilfe.ts`: In den
 * Zeichenketten steht kein Markup, und nichts davon wird über
 * `dangerouslySetInnerHTML` gerendert. Der Renderer kennt
 * `dangerouslySetInnerHTML` an keiner Stelle, und das soll so bleiben — die
 * Inhaltssicherheitsrichtlinie (`shared/csp.ts`) verbietet ohnehin fremde
 * Skripte, aber ein Blockmodell braucht die Frage gar nicht erst zu stellen.
 *
 * ## Warum erzeugt und nicht geschrieben
 *
 * `content/datenschutz.json` entsteht aus `docs/datenschutz.md` über
 * `tools/datenschutz_anwendung.py`, und zwar über **denselben** Umsetzer,
 * der auch die veröffentlichte HTML-Fassung erzeugt. Es gibt genau einen
 * Parser für dieses Dokument.
 *
 * Der Grund ist nicht Bequemlichkeit: Die veröffentlichte Seite stand am
 * 30.08.2026 auf Fassung 1.1, während die Quelldatei bei 1.5 war — vier
 * Revisionen Abstand in vier Tagen, bei vorhandenem Erzeuger und vorhandener
 * Prüfliste. Ausgelaufen ist der Schritt, den nur ein Mensch tut. Deshalb
 * trägt die erzeugte Datei die Prüfsumme ihrer Quelle, und
 * `tests/datenschutz.test.ts` rechnet sie nach.
 */

/** Ein ausgezeichneter Teil innerhalb eines Absatzes oder Listenpunkts. */
export type Datenschutzteil =
  | { readonly art: 'text'; readonly text: string }
  /** Hervorhebung – im Markdown `**fett**`. */
  | { readonly art: 'stark'; readonly text: string }
  /** Datei-, Feld- oder Spaltenname – im Markdown `` `so` ``. */
  | { readonly art: 'kennzeichnung'; readonly text: string }
  /** Verweis mit Ziel; die Anwendung zeigt ihn als Text samt Adresse. */
  | { readonly art: 'verweis'; readonly text: string; readonly ziel: string };

/**
 * Ein Baustein der Erklärung.
 *
 * Genau die vier Formen, die der Erzeuger hervorbringt. Nachgezählt am
 * Dokument vom 30.08.2026: 93 Absätze, 34 Überschriften, 11 Listen und
 * 6 Codeblöcke. Was hier nicht vorgesehen ist, lässt den Erzeuger abbrechen,
 * statt es stillschweigend wegzulassen.
 */
export type Datenschutzblock =
  | {
      readonly art: 'ueberschrift';
      readonly ebene: 1 | 2 | 3;
      readonly text: string;
      /** Sprungziel, gebildet wie in der HTML-Fassung. */
      readonly kennung: string;
    }
  | { readonly art: 'absatz'; readonly teile: readonly Datenschutzteil[] }
  | { readonly art: 'liste'; readonly punkte: readonly (readonly Datenschutzteil[])[] }
  | { readonly art: 'code'; readonly text: string };

export interface Datenschutzerklaerung {
  /** SHA-256 des Veröffentlichungsteils von `docs/datenschutz.md`. */
  readonly quellpruefsumme: string;
  /** Fassung der Erklärung, aus ihrer Standtabelle gelesen. */
  readonly fassung: string;
  /** Stand der Erklärung, aus ihrer Standtabelle gelesen. */
  readonly stand: string;
  readonly bloecke: readonly Datenschutzblock[];
}

export interface Datenschutzangaben {
  /** Die Erklärung; `null`, wenn die Datei fehlt oder unlesbar ist. */
  readonly erklaerung: Datenschutzerklaerung | null;
  /**
   * Warum sie fehlt – für die Anzeige, nicht fürs Protokoll.
   *
   * Ein leerer Bereich ohne Begründung wäre die schlechteste Auskunft: Der
   * Nutzende hielte die Erklärung für nicht vorhanden statt für nicht
   * ladbar.
   */
  readonly warnung: string | null;
}

/** Ohne Datei: die Anwendung läuft weiter und sagt, was fehlt. */
export const DATENSCHUTZ_LEER: Datenschutzangaben = Object.freeze({
  erklaerung: null,
  warnung: null,
});

/**
 * Die Überschriften, die ein Sprungmenü anbietet.
 *
 * Nur die zweite Ebene: Die Erklärung hat 13 Abschnitte und 20
 * Unterabschnitte; ein Verzeichnis über alle 33 wäre selbst wieder eine
 * Wand aus Text. Die erste Ebene ist der Titel und braucht kein Sprungziel.
 */
export function abschnitte(
  erklaerung: Datenschutzerklaerung,
): readonly { readonly text: string; readonly kennung: string }[] {
  return erklaerung.bloecke
    .filter(
      (block): block is Extract<Datenschutzblock, { art: 'ueberschrift' }> =>
        block.art === 'ueberschrift' && block.ebene === 2,
    )
    .map((block) => ({ text: block.text, kennung: block.kennung }));
}
