from __future__ import annotations

from typing import Any, Dict, List, Literal, Optional

from pydantic import AliasChoices

from receipts.compat.pyd import Field, model_validator

from receipts.base import BaseReceipt, Domain, PADenialReasonPayload


class LegacyPAReceipt(BaseReceipt):
    """Base class for deprecated prior authorisation receipts."""

    domain_namespace: Domain = Field(default=Domain.LEGACY_PA, exclude=True)
    deprecated: Literal[True] = Field(
        default=True,
        validation_alias=AliasChoices("deprecated", "is_deprecated"),
        description="Legacy PA receipts are read-only and retained for replay compatibility.",
    )

    @model_validator(mode="after")
    def _reject_live_writes(self) -> "LegacyPAReceipt":
        mode_token = str(getattr(self, "mode", "") or "").upper()
        if mode_token in {"", "LIVE"} and self.receipt_hash is None:
            raise ValueError("Legacy PA receipts may only be loaded from historical replays")
        if self.deprecated is not True:
            raise ValueError("Legacy PA receipts must set deprecated flag to true")
        return self


class SanityReadReceipt(LegacyPAReceipt):
    """Receipt documenting PIH/PHI sanity checks performed prior to scoring."""

    receipt_type: str = "SanityReadReceipt"
    domain: Literal["claims", "prior_auth"]
    payload_digest: Dict[str, Any] = Field(default_factory=dict)
    fields_scanned: List[str] = Field(default_factory=list)
    attachments_requested: List[str] = Field(default_factory=list)
    findings: List[str] = Field(default_factory=list)


class EvidenceAttachmentReceipt(LegacyPAReceipt):
    """Receipt documenting attachment scans linked to a scoring transaction."""

    receipt_type: str = "EvidenceAttachmentReceipt"
    domain: Literal["claims", "prior_auth"]
    attachment_id: str
    locator: str
    payload_digest: Dict[str, Any] = Field(default_factory=dict)
    scan_summary: Dict[str, Any] = Field(default_factory=dict)


class ClaimAppealScoreReceipt(LegacyPAReceipt):
    """Receipt capturing claim appeal scoring outputs."""

    receipt_type: str = "ClaimAppealScoreReceipt"
    claim_id: str
    model_tag: str
    p_win_raw: float
    p_win_calibrated: float
    challenger_agreement: Optional[float] = None
    challenger_votes: Dict[str, float] = Field(default_factory=dict)
    disagreement_reason: Optional[str] = None
    features_digest: Dict[str, Any] = Field(default_factory=dict)
    triage_bucket: Optional[str] = None
    uplift: Optional[float] = None
    run_card_id: Optional[str] = None
    latency_breakdown: Dict[str, float] = Field(default_factory=dict)
    evidence_uri: List[str] = Field(default_factory=list)


class PATimeToDecisionReceipt(LegacyPAReceipt):
    """Receipt capturing prior authorisation time-to-decision estimates."""

    receipt_type: str = "PATimeToDecisionReceipt"
    pa_id: str
    model_tag: str
    predicted_median_hours: float
    c_index_eval_window: Optional[float] = None
    features_digest: Dict[str, Any] = Field(default_factory=dict)
    latency_breakdown: Dict[str, float] = Field(default_factory=dict)
    evidence_uri: List[str] = Field(default_factory=list)


class PAApprovalScoreReceipt(LegacyPAReceipt):
    """Receipt capturing prior authorisation approval scores."""

    receipt_type: str = "PAApprovalScoreReceipt"
    pa_id: str
    model_tag: str
    p_approve_raw: float
    p_approve_calibrated: float
    challenger_agreement: Optional[float] = None
    challenger_votes: Dict[str, float] = Field(default_factory=dict)
    disagreement_reason: Optional[str] = None
    features_digest: Dict[str, Any] = Field(default_factory=dict)
    latency_breakdown: Dict[str, float] = Field(default_factory=dict)
    evidence_uri: List[str] = Field(default_factory=list)
    claims: List[str] = Field(default_factory=list)
    conformal: Optional[Dict[str, Any]] = None
    refusal: Optional[Any] = None
    denial_reasons: List[PADenialReasonPayload] = Field(default_factory=list)


class PADecisionReceipt(LegacyPAReceipt):
    """Receipt documenting prior authorisation decision outcomes."""

    receipt_type: str = "PADecisionReceipt"
    pa_id: str
    model_tag: str
    decision: Literal["approve", "deny", "manual_review"]
    p_approve: float
    refusal_reasons: List[str] = Field(default_factory=list)
    features_digest: Dict[str, Any] = Field(default_factory=dict)
    evidence_uri: List[str] = Field(default_factory=list)


class DenialRiskScoreReceipt(LegacyPAReceipt):
    """Receipt documenting the denial risk score emitted for PA audit triage."""

    receipt_type: str = "DenialRiskScoreReceipt"
    request_id: str
    model_tag: str
    p_deny: float
    reasons: List[str] = Field(default_factory=list)
    features_digest: Dict[str, Any] = Field(default_factory=dict)
    latency_breakdown: Dict[str, float] = Field(default_factory=dict)
    claims: List[str] = Field(default_factory=list)
    evidence_uri: List[str] = Field(default_factory=list)
    denial_reasons: List[PADenialReasonPayload] = Field(default_factory=list)


__all__ = [
    "LegacyPAReceipt",
    "SanityReadReceipt",
    "EvidenceAttachmentReceipt",
    "ClaimAppealScoreReceipt",
    "PATimeToDecisionReceipt",
    "PAApprovalScoreReceipt",
    "PADecisionReceipt",
    "DenialRiskScoreReceipt",
]
