/**
 * Die Datenschutzerklärung im Bereich „Über diese Software“.
 *
 * ## Warum aufklappbar und nicht ausgeklappt
 *
 * Die Erklärung ist 144 Blöcke lang. Ausgeklappt schöbe sie alles darunter —
 * Lizenz, Rechtslage des Katalogs, Verfahren, Fremdkomponenten,
 * Unterstützung — um mehrere Bildschirmhöhen nach unten, und wer per
 * Tabulator arbeitet, käme nur noch durch das ganze Rechtsdokument dorthin.
 * Genauso hält es der Lizenzblock mit dem EUPL-Volltext.
 *
 * ## Warum ein Sprungmenü darin
 *
 * Aufgeklappt sind es dreizehn Abschnitte. Ohne Sprungziele bliebe einem
 * Bildschirmleser nur, sie der Reihe nach zu hören; das ist die Bauform, die
 * das Handbuch mit seinem Inhaltsverzeichnis längst vermeidet. Angeboten
 * wird nur die zweite Ebene: Ein Verzeichnis über alle 33 Überschriften wäre
 * selbst wieder eine Wand.
 *
 * ## Warum Überschriften ab Ebene 3
 *
 * Der Bereich führt eine `h1` und darunter `h2` je Abschnitt. Die Erklärung
 * beginnt intern bei `h1`; sie wird deshalb um zwei Ebenen versetzt gezeigt,
 * damit kein Sprung entsteht. Ein Sprung in der Überschriftenfolge ist ein
 * Verstoß gegen WCAG 1.3.1, und die Ebenen sind das Inhaltsverzeichnis, das
 * ein Bildschirmleser tatsächlich benutzt.
 */

import { useId, useState } from 'react';

import {
  abschnitte,
  type Datenschutzblock,
  type Datenschutzerklaerung,
  type Datenschutzteil,
} from '../../../../shared/datenschutz';

export interface DatenschutztextProps {
  readonly erklaerung: Datenschutzerklaerung;
}

/** Die Ebenen der Erklärung, um zwei versetzt: 1 → 3, 2 → 3, 3 → 4. */
function ueberschriftsebene(ebene: 1 | 2 | 3): 3 | 4 {
  return ebene === 3 ? 4 : 3;
}

function Teile({ teile }: { readonly teile: readonly Datenschutzteil[] }): React.JSX.Element {
  return (
    <>
      {teile.map((teil, nummer) => {
        const schluessel = `${String(nummer)}-${teil.text.slice(0, 24)}`;
        if (teil.art === 'stark') {
          return <strong key={schluessel}>{teil.text}</strong>;
        }
        if (teil.art === 'kennzeichnung') {
          return <code key={schluessel}>{teil.text}</code>;
        }
        if (teil.art === 'verweis') {
          /* Die Adresse steht als Text daneben und nicht nur im Ziel: Die
             Anwendung öffnet ausschließlich die eine eingetragene Adresse
             (`main/sicherheit.ts`), ein Verweis hier führte also ins Leere.
             Wer die Stelle aufsuchen will, muss sie lesen können. */
          return (
            <span key={schluessel}>
              {teil.text} ({teil.ziel})
            </span>
          );
        }
        return <span key={schluessel}>{teil.text}</span>;
      })}
    </>
  );
}

function Block({ block }: { readonly block: Datenschutzblock }): React.JSX.Element | null {
  switch (block.art) {
    case 'ueberschrift': {
      const ebene = ueberschriftsebene(block.ebene);
      const Tag = ebene === 3 ? 'h3' : 'h4';
      return (
        <Tag id={`datenschutz-${block.kennung}`} className="datenschutz__titel">
          {block.text}
        </Tag>
      );
    }

    case 'absatz':
      return (
        <p>
          <Teile teile={block.teile} />
        </p>
      );

    case 'liste':
      return (
        <ul>
          {block.punkte.map((punkt, nummer) => (
            <li key={`${String(nummer)}-${punkt[0]?.text.slice(0, 24) ?? ''}`}>
              <Teile teile={punkt} />
            </li>
          ))}
        </ul>
      );

    case 'code':
      return (
        <pre className="datenschutz__code">
          <code>{block.text}</code>
        </pre>
      );

    default:
      return null;
  }
}

export function Datenschutztext({ erklaerung }: DatenschutztextProps): React.JSX.Element {
  const [offen, setzeOffen] = useState(false);
  const inhaltId = useId();
  const verzeichnisId = useId();
  const ziele = abschnitte(erklaerung);

  return (
    <div className="datenschutz">
      <p className="datenschutz__stand">
        Fassung {erklaerung.fassung}, Stand {erklaerung.stand}. Sie gilt für diese Anwendung und ist
        hier vollständig enthalten – es wird nichts nachgeladen.
      </p>

      <button
        type="button"
        className="knopf knopf--leise"
        aria-expanded={offen}
        aria-controls={inhaltId}
        onClick={() => {
          setzeOffen((bisher) => !bisher);
        }}
      >
        {offen ? 'Datenschutzerklärung einklappen' : 'Datenschutzerklärung lesen'}
      </button>

      {offen ? (
        <div id={inhaltId} className="datenschutz__inhalt">
          <nav aria-labelledby={verzeichnisId} className="datenschutz__verzeichnis">
            <h3 id={verzeichnisId}>Abschnitte</h3>
            <ol>
              {ziele.map((ziel) => (
                <li key={ziel.kennung}>
                  <a href={`#datenschutz-${ziel.kennung}`}>{ziel.text}</a>
                </li>
              ))}
            </ol>
          </nav>

          {erklaerung.bloecke.map((block, nummer) => (
            <Block key={`${String(nummer)}-${block.art}`} block={block} />
          ))}
        </div>
      ) : null}
    </div>
  );
}
