from __future__ import annotations

from dataclasses import dataclass
from typing import Dict, Optional, Any


@dataclass(frozen=True)
class RefusalSpec:
    code: str
    label: str
    detail_schema: Dict[str, str]
    remediation: Optional[str] = None


REGISTRY: Dict[str, RefusalSpec] = {
    "conformal_ambiguous": RefusalSpec(
        "conformal_ambiguous",
        "Conformal set is ambiguous",
        {"set_size": "int", "expected_set_size": "int"},
        remediation="Increase calibration data or adjust alpha to tighten prediction set.",
    ),
    "interval_too_wide": RefusalSpec(
        "interval_too_wide",
        "Prediction interval too wide",
        {"width": "float", "max_width": "float"},
        remediation="Reduce model variance or retrain with improved coverage control.",
    ),
    "coverage_out_of_bounds": RefusalSpec(
        "coverage_out_of_bounds",
        "Empirical coverage out of bounds",
        {"observed": "float", "lower": "float", "upper": "float"},
        remediation="Recalibrate coverage or widen tolerance band.",
    ),
    "calibration_worst_slice_exceeded": RefusalSpec(
        "calibration_worst_slice_exceeded",
        "Worst-slice calibration exceeded threshold",
        {"ece_worst": "float", "max_ece": "float", "cohort": "str"},
        remediation="Investigate cohort-specific calibration drift and retrain or recalibrate.",
    ),
    "dignity_floor": RefusalSpec(
        "dignity_floor",
        "Dignity weight below floor",
        {"dwf": "float", "min_dwf": "float"},
        remediation="Review dignity weights and regenerate explanation artifacts.",
    ),
    "challenger_disagreement": RefusalSpec(
        "challenger_disagreement",
        "Challenger disagreed beyond tolerance",
        {"delta_pp": "float", "max_pp": "float"},
        remediation="Investigate challenger drift and refresh challenger calibration.",
    ),
    "phi_detected": RefusalSpec(
        "phi_detected",
        "PHI present in payload or attachments",
        {"categories": "list[str]", "count": "int"},
        remediation="Remove PHI artifacts and resubmit once sanitized.",
    ),
    "attachment_quarantine": RefusalSpec(
        "attachment_quarantine",
        "Attachment scan failed or unsafe",
        {"reason": "str"},
        remediation="Provide alternate attachment or remediate flagged file.",
    ),
    "policy_denied": RefusalSpec(
        "policy_denied",
        "Policy engine denied the action",
        {"policy_id": "str", "bundle_sha256": "str", "reason": "str"},
        remediation="Review policy bundle execution trace for remediation steps.",
    ),
    "stand_down_active": RefusalSpec(
        "stand_down_active",
        "System is in stand-down state",
        {"trigger": "str"},
        remediation="Follow the stand-down runbook and restore guardrails before retrying.",
    ),
}


def get_refusal_spec(reason_code: str) -> Optional[RefusalSpec]:
    """Lookup helper that tolerates missing codes."""
    return REGISTRY.get(reason_code)
