# -*- coding: utf-8 -*-
"""Erzeugt einen HTML-Prüfbericht für die manuelle Sichtprüfung des Katalogs.

Stellt alle 575 Fragen mit Lösungen, Musterantworten, hervorgehobenen
Kernelementen und Abbildungen dar, damit sie gegen das Original-PDF geprüft
werden können. Der Bericht ist selbst tastaturbedienbar und kontraststark.
"""
from __future__ import annotations

import base64
import html
import io
import json
import sys
from pathlib import Path

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")

BASE = Path(__file__).resolve().parent.parent
KATALOG = BASE / "content" / "katalog"
ZIEL = BASE / "docs" / "katalog-pruefbericht.html"


def bild_tag(bid: str, bilder: dict) -> str:
    meta = bilder.get(bid)
    if not meta:
        return f'<span class="fehlt">Bild {html.escape(bid)} fehlt</span>'
    daten = base64.b64encode((KATALOG / "assets" / meta["datei"]).read_bytes()).decode()
    alt = meta.get("alt") or ""
    return (f'<img src="data:image/png;base64,{daten}" alt="{html.escape(alt)}" '
            f'title="{html.escape(bid)}">')


def segmente_html(feld: dict) -> str:
    teile = []
    for s in feld["segmente"]:
        text = html.escape(s["t"]).replace("\n", "<br>")
        teile.append(f"<mark>{text}</mark>" if s.get("h") else text)
    return "".join(teile) or '<span class="fehlt">(kein Text)</span>'


def main() -> int:
    data = json.loads((KATALOG / "katalog.json").read_text(encoding="utf-8"))
    bilder = {b["id"]: b for b in data["bilder"]}
    meta = data["meta"]

    abschnitt_titel = {}
    for kap in data["kapitel"]:
        for a in kap["abschnitte"]:
            abschnitt_titel[a["id"]] = a["titel"]
        abschnitt_titel[kap["id"]] = kap["titel"]

    zeilen: list[str] = []
    aktuelle_gruppe = None
    for f in data["fragen"]:
        gruppe = f["abschnitt"] or f["kapitel"]
        if gruppe != aktuelle_gruppe:
            aktuelle_gruppe = gruppe
            titel = abschnitt_titel.get(gruppe, gruppe)
            zeilen.append(f'<h2 id="g-{html.escape(gruppe)}">{html.escape(gruppe)} · '
                          f'{html.escape(titel)}</h2>')

        typ_label = {"mc": "Multiple Choice", "freitext": "offene Frage",
                     "lueckentext": "Lückentext"}[f["typ"]]
        kopf = (f'<div class="kopf"><span class="id">{html.escape(f["id"])}</span>'
                f'<span class="amtlich">amtlich {html.escape(f["amtliche_nummer"])}</span>'
                f'<span class="typ typ-{f["typ"]}">{typ_label}</span>'
                f'<span class="seite">PDF-Seite {f["seite"]}</span></div>')

        koerper = [f'<p class="frage">{segmente_html(f["frage"])}</p>']
        for bid in f["bilder"]:
            koerper.append(f'<p class="bilder">{bild_tag(bid, bilder)}</p>')

        if f["typ"] == "mc":
            richtige = sum(1 for o in f["optionen"] if o["korrekt"])
            if richtige > 1:
                koerper.append(f'<p class="mehrfach">{richtige} richtige Antworten</p>')
            koerper.append("<ul class='optionen'>")
            for o in f["optionen"]:
                marke = "richtig" if o["korrekt"] else "falsch"
                zeichen = "✓" if o["korrekt"] else "✗"
                inhalt = segmente_html(o["inhalt"]) if o["inhalt"]["text"].strip() else ""
                bild = "".join(bild_tag(b, bilder) for b in o["bilder"])
                koerper.append(
                    f'<li class="{marke}"><span class="marke" aria-label="'
                    f'{"richtig" if o["korrekt"] else "falsch"}">{zeichen}</span>'
                    f'<span class="label">{html.escape(o["label"])})</span>'
                    f'<span class="text">{inhalt}{bild}</span></li>')
            koerper.append("</ul>")
        else:
            koerper.append(f'<div class="antwort"><span class="ml">Musterantwort</span>'
                           f'{segmente_html(f["musterantwort"])}</div>')

        if f.get("warnungen"):
            hinweise = "; ".join(html.escape(w) for w in f["warnungen"])
            koerper.append(f'<p class="warnung">Hinweis aus der Extraktion: {hinweise}</p>')

        zeilen.append(f'<article class="frage-block" id="{html.escape(f["id"])}">'
                      f'{kopf}{"".join(koerper)}</article>')

    kennzahlen = [
        ("Fragen", len(data["fragen"])),
        ("Multiple Choice", sum(1 for f in data["fragen"] if f["typ"] == "mc")),
        ("offene Fragen", sum(1 for f in data["fragen"] if f["typ"] != "mc")),
        ("Antwortoptionen", sum(len(f.get("optionen", [])) for f in data["fragen"])),
        ("markierte Lösungen", sum(sum(1 for o in f.get("optionen", []) if o["korrekt"])
                                   for f in data["fragen"])),
        ("Abbildungen", len(data["bilder"])),
    ]
    kacheln = "".join(f'<div class="kachel"><span class="wert">{w}</span>'
                      f'<span class="bez">{html.escape(b)}</span></div>'
                      for b, w in kennzahlen)

    nav = "".join(
        f'<li><a href="#g-{html.escape(g)}">{html.escape(g)} · {html.escape(t)}</a></li>'
        for g, t in abschnitt_titel.items()
        if any((f["abschnitt"] or f["kapitel"]) == g for f in data["fragen"]))

    ZIEL.parent.mkdir(parents=True, exist_ok=True)
    ZIEL.write_text(SEITE.format(
        titel="Prüfbericht Fragenkatalog",
        quelle=html.escape(meta["quellenangabe"]),
        stand=html.escape(meta["stand"]),
        kacheln=kacheln, nav=nav, inhalt="\n".join(zeilen),
    # LF wie im Archiv verlangt, nicht das CRLF von Windows.
    ), encoding="utf-8", newline="\n")
    print(f"Prüfbericht geschrieben: {ZIEL}")
    print(f"Größe: {ZIEL.stat().st_size / 1024:.0f} kB")
    return 0


SEITE = """<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{titel}</title>
<style>
  :root {{
    --bg: #fbfcfb; --flaeche: #f1f5f2; --rand: #d9e0db;
    --text: #161c18; --gedaempft: #4f5a53;
    --akzent: #2c5c4c; --richtig: #1c6b4a; --falsch: #8a3324;
    --markierung: #f7edc9;
  }}
  @media (prefers-color-scheme: dark) {{
    :root:not([data-theme="light"]) {{
      --bg: #12160f; --flaeche: #1b211c; --rand: #2d352f;
      --text: #e8eee9; --gedaempft: #9daaa2;
      --akzent: #8ac7ab; --richtig: #7fc9a3; --falsch: #e2957f;
      --markierung: #3a3520;
    }}
  }}
  * {{ box-sizing: border-box; }}
  body {{
    margin: 0; background: var(--bg); color: var(--text);
    font: 16px/1.6 -apple-system, "Segoe UI", system-ui, sans-serif;
  }}
  a {{ color: var(--akzent); }}
  :focus-visible {{ outline: 3px solid var(--akzent); outline-offset: 2px; }}
  .huelle {{ max-width: 62rem; margin: 0 auto; padding: 0 1.25rem 5rem; }}
  header {{ padding: 2.5rem 0 1.25rem; border-bottom: 2px solid var(--text); }}
  h1 {{ font-size: 1.9rem; margin: 0 0 .4rem; letter-spacing: -.01em; }}
  .quelle {{ color: var(--gedaempft); font-size: .9rem; margin: 0; max-width: 46rem; }}
  .kacheln {{ display: flex; flex-wrap: wrap; gap: .6rem; margin: 1.4rem 0; }}
  .kachel {{
    background: var(--flaeche); border: 1px solid var(--rand); border-radius: 8px;
    padding: .6rem .9rem; min-width: 8.5rem;
  }}
  .kachel .wert {{ display: block; font-size: 1.4rem; font-weight: 700;
                   color: var(--akzent); font-variant-numeric: tabular-nums; }}
  .kachel .bez {{ display: block; font-size: .8rem; color: var(--gedaempft); }}
  nav ul {{ list-style: none; padding: 0; margin: 0 0 2rem;
            display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: .3rem; }}
  nav a {{ text-decoration: none; }}
  nav a:hover {{ text-decoration: underline; }}
  h2 {{ font-size: 1.25rem; margin: 2.5rem 0 1rem; padding-top: 1rem;
        border-top: 1px solid var(--rand); }}
  .frage-block {{
    border: 1px solid var(--rand); border-radius: 10px; background: var(--flaeche);
    padding: 1rem 1.2rem; margin: 0 0 1rem;
  }}
  .kopf {{ display: flex; flex-wrap: wrap; gap: .5rem 1rem; align-items: baseline;
           font-size: .8rem; color: var(--gedaempft); margin-bottom: .5rem; }}
  .kopf .id {{ font-weight: 700; color: var(--text); font-size: .95rem; }}
  .typ {{ border: 1px solid var(--rand); border-radius: 99px; padding: .05rem .55rem; }}
  .typ-mc {{ border-color: var(--akzent); color: var(--akzent); }}
  .frage {{ margin: 0 0 .7rem; font-size: 1.02rem; }}
  .mehrfach {{ margin: 0 0 .5rem; font-size: .8rem; color: var(--akzent); font-weight: 600; }}
  ul.optionen {{ list-style: none; margin: 0; padding: 0; display: flex;
                 flex-direction: column; gap: .35rem; }}
  ul.optionen li {{ display: grid; grid-template-columns: 1.4rem 1.4rem 1fr;
                    gap: .4rem; align-items: start; }}
  .marke {{ font-weight: 700; }}
  li.richtig .marke {{ color: var(--richtig); }}
  li.falsch .marke {{ color: var(--falsch); }}
  li.richtig .text {{ font-weight: 600; }}
  .label {{ color: var(--gedaempft); }}
  .antwort {{ border-left: 3px solid var(--akzent); padding: .3rem 0 .3rem .8rem; }}
  .antwort .ml {{ display: block; font-size: .75rem; text-transform: uppercase;
                  letter-spacing: .08em; color: var(--gedaempft); }}
  mark {{ background: var(--markierung); color: var(--text);
          padding: 0 .15em; border-radius: 3px; font-weight: 600; }}
  img {{ max-height: 3.2rem; width: auto; vertical-align: middle; margin: .15rem .4rem .15rem 0;
         background: #fff; border-radius: 3px; padding: 2px; }}
  .warnung {{ font-size: .82rem; color: var(--falsch); margin: .6rem 0 0; }}
  .fehlt {{ color: var(--falsch); font-style: italic; }}
  footer {{ margin-top: 3rem; padding-top: 1rem; border-top: 1px solid var(--rand);
            font-size: .85rem; color: var(--gedaempft); }}
</style>
</head>
<body>
<div class="huelle">
<header>
  <h1>Prüfbericht Fragenkatalog</h1>
  <p class="quelle">{quelle} — Katalogstand {stand}. Grün markierte Antworten sind
  im Original angekreuzt; <mark>hervorgehobene</mark> Stellen sind die Kernelemente
  der Musterantworten.</p>
</header>
<div class="kacheln">{kacheln}</div>
<nav aria-label="Abschnitte"><ul>{nav}</ul></nav>
<main>
{inhalt}
</main>
<footer>Automatisch erzeugt aus dem amtlichen Katalog-PDF. Dient der Sichtprüfung
der Extraktion, nicht dem Lernen.</footer>
</div>
</body>
</html>
"""


if __name__ == "__main__":
    raise SystemExit(main())
