"""
Erzeugt eine gzip-komprimierte JSON-Datei mit Strukturdaten (Demografie) je
Briefwahlbezirk aus dem amtlichen Strukturdaten-XLSX (Statistik Berlin).

Die Strukturdaten liegen je Urnenwahlbezirk (UWB) vor. Die Wahlbezirke-Ansicht
der Karte zeigt aber bereits zu Briefwahlbezirken (BWB) zusammengefasste
Polygone (siehe briefwahlbezirke.geojson.gz, Feld "UWBs"). Die UWB-Werte
werden daher einwohnergewichtet je BWB aggregiert:

    bwb_wert = Summe(uwb_wert * uwb_einwohner) / Summe(uwb_einwohner)

Ausgabedatei: data/STRUKTURDATEN_2023.json.gz
  {"kategorien": [<label>, ...], "bwb": {<bwb-id>: {<label>: <prozent>, ...}}}

Bei neuen Strukturdaten: XLSX in Rohdaten/ ablegen, Dateiname unten anpassen,
Skript erneut ausfuehren: python local/build_strukturdaten.py
"""
import gzip
import json
from pathlib import Path

import openpyxl

BASE = Path(__file__).parent.parent
XLSX = BASE / "Rohdaten" / "AGH2023_Strukturdaten.xlsx"
SHEET = "Strukturdaten"
BWB_GEOJSON = BASE / "data" / "briefwahlbezirke.geojson.gz"
OUT = BASE / "data" / "STRUKTURDATEN_2023.json.gz"

EINWOHNER_SPALTE = "Einwohner Anzahl"

# (Spaltenname im XLSX, Anzeige-Label). Nur Prozent-Kennzahlen, eine je
# thematischer Kategorie (zugehoerige "Anzahl"-Spalte wird nicht aufgenommen).
KATEGORIEN = [
    ("Einwohner unter 6 Jahre Prozent", "Einwohner unter 6 Jahre"),
    ("Einwohner 6 - 18 Prozent", "Einwohner 6–18 Jahre"),
    ("Einwohner 18 - 65 Prozent", "Einwohner 18–65 Jahre"),
    ("Einwohner 65 und älter Prozent", "Einwohner 65+ Jahre"),
    ("Ausländer Prozent", "Ausländer"),
    ("EU-Bürger Prozent", "EU-Bürger"),
    ("EU-Bürger 16 + Prozent", "EU-Bürger 16+"),
    ("EU-Bürger 18 + Prozent", "EU-Bürger 18+"),
    ("Deutsche Prozent", "Deutsche"),
    ("Deutsche unter 6 Prozent", "Deutsche unter 6 Jahre"),
    ("Deutsche 6 - 18 Prozentl", "Deutsche 6–18 Jahre"),
    ("Deutsche 16 + Prozent", "Deutsche 16+"),
    ("Deutsche 18 + Prozent", "Deutsche 18+"),
    ("Deutsche 18 - 25 Prozent", "Deutsche 18–25 Jahre"),
    ("Deutsche 25 - 35 Prozent", "Deutsche 25–35 Jahre"),
    ("Deutsche 35 - 45 Prozent", "Deutsche 35–45 Jahre"),
    ("Deutsche 45 - 60 Prozent", "Deutsche 45–60 Jahre"),
    ("Deutsche 60 - 70 Prozent", "Deutsche 60–70 Jahre"),
    ("Deutsche 70 + Prozent", "Deutsche 70+ Jahre"),
    ("Deutsche 16 + weiblich Prozent", "Deutsche 16+ weiblich"),
    ("Deutsche 18 + weiblich Prozent", "Deutsche 18+ weiblich"),
    ("Deutsche 16 + Migrationshintergrund Prozent", "Deutsche 16+ mit Migrationshintergrund"),
    ("Deutsche 18 + Migrationshintergrund Prozent", "Deutsche 18+ mit Migrationshintergrund"),
    ("Deutsche 18 + Familienstand ledig Prozent", "Deutsche 18+ ledig"),
    ("Deutsche 18 + Familienstand verheiratet Prozent", "Deutsche 18+ verheiratet"),
    ("Deutsche 18 + Familienstand verwitwet Prozent", "Deutsche 18+ verwitwet"),
    ("Deutsche 18 + Familienstand geschieden Prozent", "Deutsche 18+ geschieden"),
    ("Deutsche 18 + Familienstand ELP Prozent", "Deutsche 18+ Lebenspartnerschaft"),
    ("Deutsche 18 + evangelisch Prozent", "Deutsche 18+ evangelisch"),
    ("Deutsche 18 + katholisch Prozent", "Deutsche 18+ katholisch"),
    ("Deutsche 18+  Veränderung zum 31.12.2021 in Prozent", "Deutsche 18+ Veränderung zu 2021"),
    ("Einwohner unter 65 in SGB II 2021 Prozent", "Einwohner unter 65 in SGB II (2021)"),
]


def load_uwb_rows():
    wb = openpyxl.load_workbook(XLSX, read_only=True, data_only=True)
    ws = wb[SHEET]
    rows_iter = ws.iter_rows(values_only=True)
    header = [str(h).strip() if h is not None else "" for h in next(rows_iter)]
    idx = {name: i for i, name in enumerate(header)}
    rows = []
    for r in rows_iter:
        if r[0] is None:
            continue
        uwb = str(r[idx["Bezirksnummer"]]) + str(r[idx["Wahlbezirk"]])
        werte = {}
        for col, label in KATEGORIEN:
            v = r[idx[col]]
            werte[label] = v if isinstance(v, (int, float)) else None
        rows.append({"uwb": uwb, "einwohner": r[idx[EINWOHNER_SPALTE]] or 0, "werte": werte})
    wb.close()
    return rows


def main():
    print(f"Lese {XLSX} ...")
    uwb_rows = load_uwb_rows()
    uwb_by_id = {r["uwb"]: r for r in uwb_rows}

    with gzip.open(BWB_GEOJSON, "rb") as f:
        bwb_gj = json.load(f)

    bwb_out = {}
    fehlende_uwb = 0
    for feat in bwb_gj["features"]:
        p = feat["properties"]
        bwb_id = p["BWB"]
        uwbs = [uwb_by_id[u] for u in p.get("UWBs", []) if u in uwb_by_id]
        fehlende_uwb += len(p.get("UWBs", [])) - len(uwbs)
        if not uwbs:
            continue
        werte = {}
        for _, label in KATEGORIEN:
            gueltig = [r for r in uwbs if r["werte"][label] is not None]
            gewicht = sum((r["einwohner"] or 0) for r in gueltig)
            if gewicht <= 0:
                continue
            summe = sum(r["werte"][label] * (r["einwohner"] or 0) for r in gueltig)
            werte[label] = round(summe / gewicht, 1)
        bwb_out[bwb_id] = werte

    out = {
        "kategorien": [label for _, label in KATEGORIEN],
        "bwb": bwb_out,
    }
    raw = json.dumps(out, ensure_ascii=False, separators=(",", ":")).encode()
    with gzip.open(OUT, "wb", compresslevel=9) as f:
        f.write(raw)

    print(f"BWBs mit Strukturdaten: {len(bwb_out)} / {len(bwb_gj['features'])}")
    if fehlende_uwb:
        print(f"Warnung: UWBs ohne Strukturdaten-Zeile (uebersprungen): {fehlende_uwb}")
    print(f"Geschrieben: {OUT} ({OUT.stat().st_size / 1024:.1f} KB)")


if __name__ == "__main__":
    main()
