"""Mail-V2 label normalizer — turn MC questions into statements.

Historic MC labels read like compliance-officer checklists:
  "Dokumentiert die Datenschutzinformation alle Datenübermittlungen
   gemäß Art. 49 Abs. 1 Unterabs. 2 DS-GVO?"

In the audit mail that looks like "we don't know" — unhelpful.
This module rewrites the label as a statement of WHAT WAS CHECKED
so the reader gets a topic, not a question:
  "Drittland-Übermittlungen Art. 49 Abs. 1 Unterabs. 2 DS-GVO"

The transformation is purely textual; the underlying MC stays as is.
"""

from __future__ import annotations

import re

# Question-stem → topic-prefix rewrites, applied in order.
_REWRITES: list[tuple[re.Pattern, str]] = [
    (re.compile(r"^Dokumentiert\s+die\s+(.+?)\s+(.+?)\?$", re.IGNORECASE),
     r"\2"),
    (re.compile(r"^Werden\s+(.+?)\s+dokumentiert\?$", re.IGNORECASE),
     r"\1 dokumentieren"),
    (re.compile(r"^Wird\s+(.+?)\s+benannt\?$", re.IGNORECASE),
     r"\1 benennen"),
    (re.compile(r"^Ist\s+(.+?)\s+angegeben\?$", re.IGNORECASE),
     r"\1 angeben"),
    (re.compile(r"^Enthält\s+(?:die\s+)?(.+?)\s+(.+?)\?$", re.IGNORECASE),
     r"\2 in \1"),
    (re.compile(r"^Sind\s+(.+?)\s+vorhanden\?$", re.IGNORECASE),
     r"\1 prüfen"),
    (re.compile(r"^Gibt\s+es\s+(.+?)\?$", re.IGNORECASE),
     r"\1 prüfen"),
]


def label_as_statement(label: str) -> str:
    """Rewrite a question-form label as a topic statement."""
    if not label:
        return label
    s = label.strip()
    if not s.endswith("?"):
        return s
    for pat, repl in _REWRITES:
        m = pat.match(s)
        if m:
            out = pat.sub(repl, s).strip()
            # First word capitalised
            return out[:1].upper() + out[1:] if out else s
    # Generic fallback: drop the question mark + leading "Wird/Sind/Ist"
    s2 = re.sub(r"^\s*(Wird|Sind|Ist|Werden|Gibt es|Enthält|Hat)\s+",
                "", s, flags=re.IGNORECASE).rstrip("?")
    return s2[:1].upper() + s2[1:] if s2 else s


def has_evidence(check) -> bool:
    """Decide whether an MC check has real evidence backing the FAIL.

    A FAIL with non-empty `matched_text` (the regex/LLM did find a
    string and judged it insufficient) is a hard fail. A FAIL with
    empty matched_text is more like 'we could not confirm' → that
    belongs in the manual-review bucket, not in critical findings.
    """
    matched = getattr(check, "matched_text", "") or ""
    return bool(matched.strip())


# Keywords that indicate a check is about an INTERNAL process the
# auditor cannot observe from outside (TOM, DSFA, AVV, training,
# incident response, risk analysis, deletion concept). These are
# never findings — they are reminders that the DPO/DSB must verify
# the document/process exists internally.
_INTERNAL_KEYWORDS = (
    "tom", "technisch-organisatorische", "technisch organisatorische",
    "dsfa", "datenschutz-folgenabschätzung",
    "datenschutzfolgenabschätzung",
    "schulung", "training", "awareness",
    "avv", "auftragsverarbeitungsvertrag", "auftragsverarbeitung",
    "incident", "vorfall", "meldepflicht intern",
    "risikoanalyse", "risikobewertung", "risk assessment",
    "löschkonzept", "löschfristen-konzept",
    "vvt", "verzeichnis der verarbeitungstätigkeiten",
    "dsb-bestellung", "dsb bestellung",
    "verfahrensverzeichnis", "berichtigungskonzept",
    "betroffenenrechte-prozess", "dsr-prozess",
)


def is_internal_process(check) -> bool:
    """Decide whether the MC check is about an internal process."""
    label = (getattr(check, "label", "") or "").lower()
    cid = (getattr(check, "id", "") or "").lower()
    hint = (getattr(check, "hint", "") or "").lower()
    # mc_audit_type module may have annotated the check
    audit_type = getattr(check, "audit_type", "")
    if audit_type and audit_type in ("internal", "process", "documentation"):
        return True
    hay = f"{label} {cid} {hint}"
    return any(k in hay for k in _INTERNAL_KEYWORDS)


def classify_check(check) -> str:
    """Return one of: 'hard_fail' | 'manual_review' | 'internal_reminder'.

    Only call on FAIL checks (passed=False, skipped=False). Drives
    which bucket the check renders into.
    """
    if is_internal_process(check):
        return "internal_reminder"
    if has_evidence(check):
        return "hard_fail"
    return "manual_review"
