"""Pruefer-Library — gemeinsames Interface. Siehe docs platform_checker_matrix.md.

Ein Checker prueft EINEN Control gegen EIN Dokument und liefert: vorhanden / fehlt
/ unklar (+ Evidence). Module (DSE/Impressum/AGB/...) liefern nur Control-Metadaten
ueber `ControlSpec` (verification_method + decision_method + checker-spezifische
Config); die Engine routet method-agnostisch zum passenden Checker.

Ziel der Plattform: 14k Controls -> 7 Pruefertypen -> wenige Pruefer. Ein neues
Modul wird damit ein Klassifizierungs-, kein Forschungsproblem.
"""
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Optional, Protocol, runtime_checkable


class VerificationMethod:
    """Achse 1 — WELCHER Pruefer-Typ (Kategorie)."""
    FIELD = "FIELD"
    REFERENCE = "REFERENCE"
    BEHAVIOR = "BEHAVIOR"
    PRESENTATION = "PRESENTATION"
    CONTENT = "CONTENT"
    PROCESS = "PROCESS"
    TECHNICAL = "TECHNICAL"
    CONTRACTUAL = "CONTRACTUAL"


class DecisionMethod:
    """Achse 2 — WIE entschieden wird (konkreter Mechanismus)."""
    REGEX = "REGEX"
    EMBEDDING = "EMBEDDING"
    LLM = "LLM"
    LINK_RESOLVER = "LINK_RESOLVER"
    PLAYWRIGHT = "PLAYWRIGHT"
    AUDIT = "AUDIT"
    SCANNER = "SCANNER"


@dataclass
class ControlSpec:
    """Routing-Metadaten + checker-spezifische Config eines Controls. Module fuellen
    nur die fuer ihren decision_method relevanten Felder."""
    control_id: str
    verification_method: str
    decision_method: str
    label: str = ""
    severity: str = "MEDIUM"
    patterns: list[str] = field(default_factory=list)       # FIELD/REGEX, REFERENCE
    paraphrases: list[str] = field(default_factory=list)    # CONTENT (EMBEDDING/LLM)
    embed_threshold: Optional[float] = None                 # EMBEDDING (per-Control)
    topic_regex: str = ""                                   # LLM: Section-Retrieval
    question: str = ""                                      # LLM: Pruef-Frage
    extra: dict[str, Any] = field(default_factory=dict)


@dataclass
class DocContext:
    """Das zu pruefende Artefakt. `text` = Volltext; `url`/`rendered` fuer
    PRESENTATION/BEHAVIOR (Playwright) — spaeter."""
    text: str = ""
    url: str = ""
    rendered: Any = None


@dataclass
class CheckResult:
    present: Optional[bool]        # True=erfuellt, False=fehlt, None=unklar (fail-safe)
    evidence: str = ""
    confidence: float = 0.0
    source: str = ""              # welcher Pruefer/Tier geantwortet hat
    detail: dict[str, Any] = field(default_factory=dict)


@runtime_checkable
class Checker(Protocol):
    """Alle Pruefer haben dieselbe Signatur -> die Engine ist method-agnostisch und
    routet nur ueber ctrl.verification_method / ctrl.decision_method."""
    verification_method: str

    async def check(self, ctrl: ControlSpec, doc: DocContext) -> CheckResult:
        ...
