"""PROTOTYP — wegwerfen. Lässt extraktion.py gegen die Testseiten laufen und
schreibt ergebnis.json sowie bericht.html."""
import html
import json
import os
import sys
from concurrent.futures import ThreadPoolExecutor

import requests

from extraktion import als_jpeg_b64, extrahieren

MODELL = "gpt-5.4-mini"
KEY = os.environ.get("OPENAI_API_KEY", "")
SEITEN = {
    "CER Container, Rostock": "https://cer-container.de/",
    "WUD Entsorgung, Saarland": "https://www.wud-entsorgung.de/",
    "Buhrfeind": "https://buhrfeind.de/",
    "Gieske Container": "https://containerdienst-gieske.de/",
    "Hildebrandt Container": "https://hildebrandt-containerdienst.de/",
    "Johann Schröder": "https://www.johann-schroeder.de/container/",
}


def frage(inhalt, schema):
    r = requests.post("https://api.openai.com/v1/chat/completions", timeout=180,
                      headers={"Authorization": f"Bearer {KEY}"},
                      json={"model": MODELL, "messages": [{"role": "user", "content": inhalt}],
                            "response_format": {"type": "json_schema", "json_schema": {"name": "antwort", "strict": True, "schema": schema}}})
    r.raise_for_status()
    return json.loads(r.json()["choices"][0]["message"]["content"])


def bildteil(b64):
    return {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}", "detail": "low"}}


CONTAINER_SCHEMA = {"type": "object", "additionalProperties": False, "required": ["bilder"], "properties": {"bilder": {"type": "array", "items": {
    "type": "object", "additionalProperties": False,
    "required": ["nr", "ist_container", "typ", "farbe_hex", "sicherheit", "begruendung"],
    "properties": {
        "nr": {"type": "integer"},
        "ist_container": {"type": "boolean"},
        "typ": {"type": "string", "enum": ["absetzcontainer", "abrollcontainer", "anderer", "keiner"]},
        "farbe_hex": {"type": "string"},
        "sicherheit": {"type": "number"},
        "begruendung": {"type": "string"},
    }}}}}

CONTAINER_PROMPT = """Du prüfst Fotos von der Website eines deutschen Containerdienstes.
Für jedes Bild (nummeriert in Reihenfolge ab 0): Zeigt es einen echten Entsorgungscontainer
(Absetzcontainer/Mulde oder Abrollcontainer), dessen lackierte Außenwand gut sichtbar ist?
Illustrationen, Icons, Grafiken, Mülltonnen, Seecontainer und Baucontainer zählen nicht.
Wenn ja: gib die Lackfarbe der Containerwand als Hex an – so wie sie bei neutralem Tageslicht aussähe,
nicht Schatten, Rost, Schmutz oder Ladung. Sicherheit 0 bis 1. Sonst farbe_hex leer lassen."""


def vision_container(fotos):
    urteile = []
    for i in range(0, len(fotos), 8):
        paket = fotos[i:i + 8]
        inhalt = [{"type": "text", "text": CONTAINER_PROMPT}] + [bildteil(als_jpeg_b64(f["bild"])) for f in paket]
        for u in frage(inhalt, CONTAINER_SCHEMA)["bilder"]:
            if 0 <= u["nr"] < len(paket):
                urteile.append({**u, "url": paket[u["nr"]]["url"], "seite": paket[u["nr"]]["seite"]})
    return urteile


LOGO_SCHEMA = {"type": "object", "additionalProperties": False, "required": ["nr", "farbe_hex", "begruendung"], "properties": {
    "nr": {"type": "integer"}, "farbe_hex": {"type": "string"}, "begruendung": {"type": "string"}}}


def vision_logo(kandidaten):
    from PIL import Image
    import io, subprocess, tempfile
    teile = [{"type": "text", "text": "Welches dieser Bilder (nummeriert ab 0) ist das Firmenlogo des Containerdienstes – das vollständige Logo, nicht ein Siegel, Partnerlogo oder Social-Media-Icon? Gib -1, wenn keins passt. farbe_hex: die markanteste Markenfarbe im Logo (nicht Schwarz/Weiß/Grau, außer es gibt keine andere)."}]
    brauchbar = []
    for k in kandidaten:
        if k["svg"]:
            # SVG über macOS-QuickLook rastern
            with tempfile.TemporaryDirectory() as d:
                p = os.path.join(d, "l.svg")
                open(p, "wb").write(k["bytes"])
                subprocess.run(["qlmanage", "-t", "-s", "512", "-o", d, p], capture_output=True)
                png = p + ".png"
                if not os.path.exists(png):
                    continue
                bild = Image.open(png); bild.load()
        else:
            bild = k["bild"]
        brauchbar.append(k)
        teile.append(bildteil(als_jpeg_b64(bild, 400)))
    if not brauchbar:
        return None
    a = frage(teile, LOGO_SCHEMA)
    if not 0 <= a["nr"] < len(brauchbar):
        return None
    return {"url": brauchbar[a["nr"]]["url"], "farbe_hex": a["farbe_hex"] or None, "begruendung": a["begruendung"]}


def lauf(item):
    name, url = item
    print(f"{name}: {url}", flush=True)
    try:
        return name, extrahieren(url, vision_container, vision_logo, protokoll=lambda m: print(f"[{name}] {m}", flush=True))
    except Exception as e:
        return name, {"website": url, "fehler": repr(e)}


def bericht(ergebnisse):
    e = html.escape
    karten = []
    for name, r in ergebnisse.items():
        if "fehler" in r:
            karten.append(f"<section><h2>{e(name)}</h2><p class=fehler>{e(r['fehler'])}</p></section>")
            continue
        logo = r["logo"]
        treffer = "".join(
            f"<figure><a href='{e(t['url'])}' target=_blank><img src='{e(t['url'])}' loading=lazy></a>"
            f"<figcaption><span class=chip style='background:{e(t['farbe_hex'])}'></span>{e(t['farbe_hex'])} · {e(t['typ'])} · {t['sicherheit']:.2f}<br><small>{e(t['begruendung'])}</small></figcaption></figure>"
            for t in r["container_treffer"]) or "<p class=leer>Kein Containerfoto erkannt.</p>"
        import re
        from bilder import ANSICHTEN
        slug = re.sub(r"[^a-z0-9]+", "-", name.lower()).strip("-")
        hier = os.path.dirname(os.path.abspath(__file__))

        def lade(datei):
            p = os.path.join(hier, datei)
            return (json.load(open(p)) if os.path.exists(p) else {}).get(slug, {})

        varianten = [("gen", "1 · KI: Farbe und Logo", lade("bilder.json")),
                     ("gen3", "3 · Code, Logo flach", lade("bilder3.json")),
                     ("gen3s", "3 · Code, Aufkleber mit Struktur", lade("bilder-gen3s.json"))]
        erzeugt = varianten[0][2]

        def zelle(ordner, titel, daten, d):
            eintrag = daten.get(d)
            ok = isinstance(eintrag, str) and not eintrag.startswith("Fehler") or isinstance(eintrag, dict) and eintrag.get("pfad")
            inhalt = f"<a href={ordner}/{slug}/{d}.png target=_blank><img src={ordner}/{slug}/{d}.png loading=lazy></a>" if ok else "<p class=leer>–</p>"
            return f"<figure>{inhalt}<figcaption>{e(titel)}</figcaption></figure>"

        if erzeugt:
            zeilen = "".join(
                f"<h4>{e(label)} · {'Farbe + Logo' if mit_logo else 'nur Farbe'}</h4><div class=reihe>"
                f"<figure><img src='ev/{d}.webp' loading=lazy><figcaption>EV-Vorlage</figcaption></figure>"
                + "".join(zelle(o, t, dd, d) for o, t, dd in varianten) + "</div>"
                for d, label, mit_logo in ANSICHTEN)
            generiert = f"<h3>Erzeugte Containerbilder</h3>{zeilen}"
            stufen_ordner = os.path.join(hier, "gen3k", slug)
            if os.path.isdir(stufen_ordner):
                from stufen import ANSICHTEN as ST_ANSICHTEN, STUFEN
                reihen = "".join(
                    f"<div class=reihe6><figure><img src=gen/{slug}/{d}.png loading=lazy><figcaption>Variante 1 (KI)</figcaption></figure>"
                    + "".join(f"<figure><img src=gen3k/{slug}/{d}-{kurz}.png loading=lazy><figcaption>Code · Kontrast ×{k:.1f}" + (f", Wand −{ab}" if ab else "") + "</figcaption></figure>" for kurz, k, ab in STUFEN)
                    + "</div>" for d in ST_ANSICHTEN)
                generiert += f"<h3>Kontraststufen (Variante 3) neben Variante 1</h3>{reihen}"
        elif r.get("farbe_quelle") != "container":
            generiert = "<h3>Erzeugte Containerbilder</h3><p class=leer>Keine erzeugt: Ohne Containerfoto muss die Farbe erst ein Mensch prüfen.</p>"
        else:
            generiert = ""
        verworfen = "".join(f"<li><a href='{e(t['url'])}' target=_blank>{e(t['url'].rsplit('/',1)[-1][:50])}</a> – {t['sicherheit']:.2f}, {e(t['begruendung'])}</li>" for t in r["container_verworfen"])
        karten.append(f"""<section>
<h2>{e(name)} <a href="{e(r['website'])}" target=_blank>{e(r['website'])}</a></h2>
<div class=kopf>
  <div><h3>Logo</h3>{f"<img class=logo src='{e(logo['url'])}'><p><small>{e(logo['begruendung'])}</small></p>" if logo else "<p class=leer>Kein Logo gefunden.</p>"}</div>
  <div><h3>Containerfarbe</h3>{f"<div class=swatch style='background:{e(r['farbe'])}'></div><p><b>{e(r['farbe'])}</b> aus {e(r['farbe_quelle'])}" + (f", {int(r['farbe_anteil']*100)} % der Treffer" if r['farbe_anteil'] else "") + "</p>" if r['farbe'] else "<p class=leer>Keine Farbe.</p>"}</div>
  <div><h3>Durchsucht</h3><p>{r['seiten']} Seiten · {r['bilder']} Bilder · {r['fotos_geprueft']} Fotos geprüft · {len(r['container_treffer'])} Containertreffer</p></div>
</div>
{generiert}
<h3>Containerfotos, aus denen die Farbe stammt</h3><div class=raster>{treffer}</div>
{f"<details><summary>{len(r['container_verworfen'])} unsichere Containertreffer</summary><ul>{verworfen}</ul></details>" if verworfen else ""}
</section>""")
    return f"""<!doctype html><html lang=de><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<title>Logo und Containerfarbe</title>
<style>
:root{{--bg:#f6f6f4;--karte:#fff;--text:#1d1d1b;--leise:#6b6b66;--linie:#e3e3de}}
@media (prefers-color-scheme:dark){{:root{{--bg:#161615;--karte:#20201f;--text:#ecece8;--leise:#9a9a94;--linie:#34342f}}}}
body{{margin:0;background:var(--bg);color:var(--text);font:15px/1.5 system-ui,sans-serif;padding:24px 16px}}
main{{max-width:1100px;margin:auto}} h1{{margin:0 0 4px}} .intro{{color:var(--leise);margin:0 0 24px}}
section{{background:var(--karte);border:1px solid var(--linie);border-radius:12px;padding:20px;margin-bottom:20px}}
h2{{margin:0 0 12px;font-size:20px}} h2 a{{font-size:13px;font-weight:400;color:var(--leise)}} h3{{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--leise);margin:16px 0 8px}}
.kopf{{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px}}
.logo{{max-width:220px;max-height:90px;background:#fff;padding:8px;border-radius:8px;border:1px solid var(--linie)}}
.swatch{{width:100%;max-width:220px;height:70px;border-radius:8px;border:1px solid var(--linie)}}
.raster{{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}}
.reihe{{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;align-items:start;margin-bottom:8px}}
@media (max-width:700px){{.reihe{{grid-template-columns:1fr 1fr}}}}
.reihe img{{aspect-ratio:1400/933;object-fit:contain;background:#ececec}}
h4{{margin:14px 0 6px;font-size:14px}}
.reihe6{{display:grid;grid-template-columns:repeat(6,1fr);gap:8px;margin-bottom:8px}}
@media (max-width:900px){{.reihe6{{grid-template-columns:repeat(3,1fr)}}}}
.reihe6 img{{width:100%;aspect-ratio:1400/933;object-fit:contain;background:#ececec;border-radius:8px}}
figure{{margin:0}} figure img{{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:8px}}
figcaption{{font-size:13px}} .chip{{display:inline-block;width:12px;height:12px;border-radius:3px;vertical-align:-1px;margin-right:6px;border:1px solid var(--linie)}}
.leer,.fehler{{color:var(--leise)}} small{{color:var(--leise)}} details{{margin-top:12px;font-size:13px}}
</style><main><h1>Logo und Containerfarbe</h1>
<p class=intro>Prototyp: Das Skript durchsucht jede Website, wählt das Logo und leitet die Containerfarbe aus den erkannten Containerfotos ab. Findet es kein Containerfoto, nimmt es die Markenfarbe des Logos.</p>
{''.join(karten)}</main></html>"""


if __name__ == "__main__":
    auswahl = {k: v for k, v in SEITEN.items() if len(sys.argv) < 2 or any(a.lower() in k.lower() for a in sys.argv[1:])}
    with ThreadPoolExecutor(6) as pool:
        ergebnisse = dict(pool.map(lauf, auswahl.items()))
    ergebnisse = {k: ergebnisse[k] for k in auswahl}
    hier = os.path.dirname(os.path.abspath(__file__))
    json.dump(ergebnisse, open(os.path.join(hier, "ergebnis.json"), "w"), ensure_ascii=False, indent=2)
    open(os.path.join(hier, "bericht.html"), "w").write(bericht(ergebnisse))
    for name, r in ergebnisse.items():
        print(f"{name}: Logo={(r.get('logo') or {}).get('url')} Farbe={r.get('farbe')} ({r.get('farbe_quelle')}) Treffer={len(r.get('container_treffer', []))} {r.get('fehler','')}")
