"""Pydantic v2 result types returned by Guard.scan_input().

All models are frozen (immutable) — scan results should not be mutated
after creation. Use model_validate() to parse server JSON responses and
model_dump() for serialization.
"""

from __future__ import annotations

from pydantic import BaseModel, ConfigDict

from .enums import Action


class Detection(BaseModel):
    """A single detected entity in the scanned text."""

    model_config = ConfigDict(frozen=True)

    label: str
    text: str
    start: int
    end: int
    confidence: float
    action: Action


class ScannerResult(BaseModel):
    """Per-scanner result from a single guardline evaluation."""

    model_config = ConfigDict(frozen=True)

    triggered: bool
    score: float
    detections: list[Detection]


class ScanResult(BaseModel):
    """Top-level result returned by Guard.scan_input().

    Attributes:
        status: Overall scan outcome — "clean", "secured", or "blocked".
        processed_text: Text after all scanner actions applied (may contain placeholders).
        placeholders: Mapping of placeholder tokens to original values, e.g.
            {"[EMAIL-A1B2]": "user@example.com"}. Used by Guard.deanonymize().
        level: Severity level 0–5 (0 = clean, higher = more severe).
        scanners: Per-scanner results keyed by guardline ID
            (e.g., "sdk_piiscanner_0").
        risk_categories: Risk bundle tags that triggered, e.g. ["PII", "SECRETS"].
    """

    model_config = ConfigDict(frozen=True)

    status: str                         # "clean" | "secured" | "blocked"
    processed_text: str
    placeholders: dict[str, str]
    level: int
    scanners: dict[str, ScannerResult]  # keyed by guardline/scanner ID
    risk_categories: list[str]
