"""
Erkennt den wahrscheinlichen Doc-Type eines eingefuegten Textes.

Wird genutzt wenn der User Text direkt ins Frontend kopiert. Wenn der
erkannte Typ vom user-deklarierten Typ abweicht, gibt das System einen
Hinweis (oder reklassifiziert automatisch wenn Confidence hoch genug).

Heuristik basiert auf Pflichtangaben-Patterns:
* Impressum: §5 TMG-Bestandteile (Anschrift + Telefon + Email + UStID)
* DSE: Art. 13 DSGVO-Bestandteile (Verantwortlicher + Zweck + Rechtsgrund)
* AGB: Vertragsschluss + Lieferung + Zahlung + Gerichtsstand
* Widerruf: 14-Tage-Frist + Widerrufsformular + Wertersatz
* Cookie-Richtlinie: Cookie-Tabelle / Speicherdauer / Drittanbieter
* Nutzungsbedingungen: Lizenz + Verbot der Vervielfaeltigung + Account
"""

from __future__ import annotations

import logging
import re

logger = logging.getLogger(__name__)

_PATTERNS: dict[str, list[tuple[re.Pattern, int]]] = {
    "impressum": [
        (re.compile(r"§\s*5\s+TMG", re.I), 4),
        (re.compile(r"angaben\s+gem(ä|ae)ß", re.I), 3),
        (re.compile(r"\bUSt[\-\s]?ID[\-\s]?Nr\b", re.I), 4),
        (re.compile(r"vertretungsberechtigt(e|er)", re.I), 3),
        (re.compile(r"registergericht", re.I), 3),
        (re.compile(r"handelsregister(nummer)?", re.I), 3),
        (re.compile(r"\bHRB\s+\d+", re.I), 3),
        (re.compile(r"verantwortlich\s+f(ü|ue)r\s+den\s+inhalt", re.I), 3),
        (re.compile(r"\bRStV\b|Rundfunkstaatsvertrag", re.I), 3),
        (re.compile(r"streitschlichtung", re.I), 2),
        (re.compile(r"OS[\-\s]?plattform", re.I), 2),
    ],
    "dse": [
        (re.compile(r"art(ikel)?\.?\s*13\s+DSGVO", re.I), 5),
        (re.compile(r"art(ikel)?\.?\s*15\s+DSGVO", re.I), 4),
        (re.compile(r"rechtsgrundlage", re.I), 3),
        (re.compile(r"datenschutzbeauftragt", re.I), 4),
        (re.compile(r"berechtigtes\s+interesse", re.I), 3),
        (re.compile(r"betroffenenrechte", re.I), 3),
        (re.compile(r"aufsichtsbeh(ö|oe)rde", re.I), 3),
        (re.compile(r"speicherdauer|aufbewahrungsfrist", re.I), 2),
        (re.compile(r"datenkategorie", re.I), 2),
        (re.compile(r"verantwortliche(r|n)\s+im\s+sinne", re.I), 4),
    ],
    "agb": [
        (re.compile(r"allgemeine\s+gesch(ä|ae)ftsbedingungen", re.I), 5),
        (re.compile(r"\bAGB\b", re.I), 3),
        (re.compile(r"vertragsschluss|vertragsabschluss", re.I), 3),
        (re.compile(r"liefer(bedingungen|zeit|kosten)", re.I), 2),
        (re.compile(r"gew(ä|ae)hrleistung", re.I), 2),
        (re.compile(r"haftungsausschluss", re.I), 2),
        (re.compile(r"gerichtsstand", re.I), 3),
        (re.compile(r"anwendbares\s+recht", re.I), 2),
        (re.compile(r"salvatorische\s+klausel", re.I), 2),
    ],
    "widerruf": [
        (re.compile(r"widerrufsbelehrung", re.I), 5),
        (re.compile(r"14\s+tage", re.I), 3),
        (re.compile(r"widerrufsrecht", re.I), 4),
        (re.compile(r"widerrufsformular", re.I), 3),
        (re.compile(r"wertersatz", re.I), 3),
        (re.compile(r"r(ü|ue)cksende(kosten|gebuehr)", re.I), 3),
        (re.compile(r"muster[\-\s]?widerrufsformular", re.I), 4),
    ],
    "cookie": [
        (re.compile(r"cookie[\-\s]?richtlinie", re.I), 4),
        (re.compile(r"cookie[\-\s]?policy", re.I), 4),
        (re.compile(r"tracking[\-\s]?cookies?", re.I), 3),
        (re.compile(r"funktionale\s+cookies?", re.I), 3),
        (re.compile(r"marketing[\-\s]?cookies?", re.I), 3),
        (re.compile(r"speicherdauer\s*\d+\s*(tag|monat|jahr)", re.I), 3),
        (re.compile(r"drittanbieter[\-\s]?cookies?", re.I), 3),
        (re.compile(r"\b(IDE|_ga|_gid|_fbp|_gcl_au|OptanonConsent)\b"), 3),
        (re.compile(r"opt[\-\s]?out", re.I), 2),
    ],
    "nutzungsbedingungen": [
        (re.compile(r"nutzungsbedingungen", re.I), 5),
        (re.compile(r"terms\s+of\s+(use|service)", re.I), 4),
        (re.compile(r"benutzerkonto|nutzerkonto", re.I), 3),
        (re.compile(r"untersagt|unzul(ä|ae)ssig.{0,30}nutzung", re.I), 2),
        (re.compile(r"sperrung\s+des\s+kontos", re.I), 2),
    ],
    "social_media": [
        (re.compile(r"social[\-\s]?media[\-\s]?(plug[\-\s]?ins?|kanale|kanaele|pr(ä|ae)senz)", re.I), 4),
        (re.compile(r"gemeinsam\s+verantwortlich.{0,100}(facebook|meta|instagram)", re.I), 4),
        (re.compile(r"fanpage|fan[\-\s]?page", re.I), 3),
        (re.compile(r"like[\-\s]?button|share[\-\s]?button", re.I), 2),
    ],
}


def classify(text: str, top_n: int = 3) -> list[tuple[str, int]]:
    """Returns list of (doc_type, score) sorted by score desc.

    Score >= 6 = high confidence, 3-5 = medium, < 3 = low.
    """
    if not text or len(text) < 200:
        return []
    scores: dict[str, int] = {}
    for dt, pats in _PATTERNS.items():
        s = 0
        for pat, weight in pats:
            if pat.search(text):
                s += weight
        if s > 0:
            scores[dt] = s
    ranked = sorted(scores.items(), key=lambda x: x[1], reverse=True)
    return ranked[:top_n]


def best_match(text: str) -> tuple[str, int] | None:
    """Returns (doc_type, score) of best match or None."""
    ranked = classify(text, top_n=1)
    return ranked[0] if ranked else None


def detect_mismatch(
    declared_doc_type: str,
    text: str,
    min_confidence: int = 6,
) -> dict | None:
    """If the text scores higher for a different doc_type than declared,
    return a hint dict {detected, declared, scores, action}.

    action='reclassify' if confidence is very high (>= min_confidence * 1.5)
    action='warn' if medium (>= min_confidence)
    action=None / no return otherwise.
    """
    ranked = classify(text, top_n=3)
    if not ranked:
        return None
    detected, detected_score = ranked[0]
    declared_canon = (declared_doc_type or "").lower().strip()
    # Aliase normalisieren
    alias = {"datenschutz": "dse", "privacy": "dse",
             "terms": "nutzungsbedingungen",
             "terms_of_use": "nutzungsbedingungen"}
    declared_canon = alias.get(declared_canon, declared_canon)

    if detected == declared_canon:
        return None
    if detected_score < min_confidence:
        return None
    declared_score = next((s for dt, s in ranked if dt == declared_canon), 0)
    # Nur wenn detected DEUTLICH besser ist (Faktor >= 2 oder declared = 0)
    if declared_score and detected_score < declared_score * 2:
        return None

    action = "reclassify" if detected_score >= min_confidence * 1.5 else "warn"
    return {
        "detected":       detected,
        "declared":       declared_doc_type,
        "detected_score": detected_score,
        "declared_score": declared_score,
        "action":         action,
        "all_scores":     dict(ranked),
    }
