"""Deklaration-vs-Bibliothek-Diff.

Regroupt die `analyze_cookies`-Findings PRO COOKIE zu Feld-Diffs
(deklariert → Library) — nur für die Library-getroffene Teilmenge, denn nur
dort gibt es eine Ground-Truth. Plus ein ehrlicher Funnel (gesamt → geprüft →
abweichend), damit nie der Eindruck entsteht, ALLE Cookies seien geprüft
(passt zur BreakPilot-Tonalität: nicht-getroffene Cookies = nicht prüfbar,
kein Pass, kein Fail).

Single source of truth bleibt `analyze_cookies` (Erkennung); dieses Modul ist
reine Präsentations-Aggregation und damit isoliert testbar.
"""

from __future__ import annotations

# Finding-Typ → Feld-Label. Nur Typen mit echtem Library-Soll ('expected').
# vague_duration/missing_retention/missing_opt_out haben KEINEN Library-Vergleich
# und third_country/eu_alternative sind Hinweise → bewusst NICHT im Diff.
_FIELD = {
    "tracker_as_necessary": "Kategorie",
    "excessive_lifetime": "Laufzeit",
    "missing_purpose": "Zweck",
}
_SEV_ORDER = {"HIGH": 0, "MEDIUM": 1, "LOW": 2}


def build_declaration_diff(analysis: dict) -> dict:
    """Aus dem `analyze_cookies`-Ergebnis die Diff-Sicht + Funnel bauen."""
    findings = analysis.get("findings") or []
    summary = analysis.get("summary") or {}

    rows: dict[tuple, dict] = {}
    for f in findings:
        field = _FIELD.get(f.get("type"))
        if not field:
            continue
        key = (f.get("vendor") or "", f.get("cookie") or "")
        row = rows.get(key)
        if row is None:
            row = {
                "cookie": f.get("cookie") or "",
                "vendor": f.get("vendor") or "",
                "diffs": [],
                "measures": [],
                "severity": "LOW",
            }
            rows[key] = row
        row["diffs"].append({
            "field": field,
            "declared": str(f.get("declared") or "—"),
            "expected": str(f.get("expected") or f.get("library_purpose") or "—"),
            "severe": f.get("severity") == "HIGH",
        })
        rem = f.get("remediation")
        if rem and rem not in row["measures"]:
            row["measures"].append(rem)
        if _SEV_ORDER.get(f.get("severity"), 3) < _SEV_ORDER.get(row["severity"], 3):
            row["severity"] = f.get("severity") or "LOW"

    out_rows = sorted(rows.values(), key=lambda r: _SEV_ORDER.get(r["severity"], 3))
    total = int(summary.get("checked") or 0)        # alle Cookies
    checked = int(summary.get("in_library") or 0)   # davon mit Library-Treffer
    return {
        "coverage": {
            "total": total,
            "checked": checked,
            "discrepant": len(out_rows),
        },
        "rows": out_rows,
    }
