"""Types for the Sessions resource."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, BinaryIO, Dict, List, Literal, Optional, Union

__all__ = [
    "SessionStatus",
    "SessionDecision",
    "DocumentSide",
    "DocumentType",
    "OcrStatus",
    "AddressProofDocType",
    "CreateSessionParams",
    "CreateSessionResponse",
    "SessionDocument",
    "SessionSelfie",
    "SessionAmlMatch",
    "SessionAmlScreening",
    "Session",
    "SessionListItem",
    "ListSessionsParams",
    "SubmitSessionResponse",
    "UploadDocumentParams",
    "UploadDocumentResponse",
    "UploadSelfieParams",
    "UploadSelfieResponse",
    "UploadAddressProofParams",
    "UploadAddressProofResponse",
]

# ── Literal types ─────────────────────────────────────────────────────────────

SessionStatus = Literal["created", "in_progress", "processing", "completed", "expired"]
SessionDecision = Literal["approved", "declined", "review"]
DocumentSide = Literal["front", "back"]
DocumentType = Literal["passport", "id_card", "driving_license", "residence_permit"]
OcrStatus = Literal["pending", "processing", "completed", "failed"]
AddressProofDocType = Literal["utility_bill", "bank_statement", "tax_document", "government_letter"]


# ── Create session ────────────────────────────────────────────────────────────


@dataclass
class CreateSessionParams:
    """Parameters for creating a new verification session."""

    profile_id: Optional[str] = None
    external_id: Optional[str] = None
    redirect_url: Optional[str] = None
    applicant_name: Optional[str] = None
    applicant_email: Optional[str] = None
    metadata: Optional[Dict[str, Any]] = None
    expires_in: Optional[int] = None


@dataclass
class CreateSessionResponse:
    """Response from creating a verification session."""

    id: str
    session_token: str
    session_url: str
    status: Literal["created"]
    expires_at: str


# ── Session detail ────────────────────────────────────────────────────────────


@dataclass
class SessionDocument:
    """A document attached to a verification session."""

    id: str
    side: DocumentSide
    document_type: Optional[DocumentType] = None
    ocr_status: OcrStatus = "pending"
    ocr_confidence: Optional[float] = None
    extracted_data: Optional[Dict[str, Any]] = None


@dataclass
class SessionSelfie:
    """Selfie data for a verification session."""

    id: str
    face_match_score: Optional[float] = None
    liveness_score: Optional[float] = None
    liveness_passed: Optional[bool] = None


@dataclass
class SessionAmlMatch:
    """An AML match found during session screening."""

    matched_name: str
    match_score: float
    datasets: List[str] = field(default_factory=list)
    topics: List[str] = field(default_factory=list)


@dataclass
class SessionAmlScreening:
    """AML screening results for a session."""

    id: str
    status: str
    highest_score: Optional[float] = None
    matches_found: int = 0
    matches: List[SessionAmlMatch] = field(default_factory=list)


@dataclass
class Session:
    """Full session detail with documents, selfie, and AML data."""

    id: str
    external_id: Optional[str] = None
    status: SessionStatus = "created"
    decision: Optional[SessionDecision] = None
    risk_score: Optional[float] = None
    decline_reason: Optional[str] = None
    applicant_name: Optional[str] = None
    extracted_data: Optional[Dict[str, Any]] = None
    created_at: str = ""
    completed_at: Optional[str] = None
    expires_at: Optional[str] = None
    documents: Optional[List[SessionDocument]] = None
    selfie: Optional[SessionSelfie] = None
    aml_screening: Optional[SessionAmlScreening] = None


@dataclass
class SessionListItem:
    """Summary session item returned by the list endpoint."""

    id: str
    external_id: Optional[str] = None
    status: SessionStatus = "created"
    decision: Optional[SessionDecision] = None
    risk_score: Optional[float] = None
    applicant_name: Optional[str] = None
    created_at: str = ""
    completed_at: Optional[str] = None
    expires_at: Optional[str] = None


@dataclass
class ListSessionsParams:
    """Parameters for listing verification sessions."""

    per_page: Optional[int] = None
    page: Optional[int] = None
    from_date: Optional[str] = None
    to_date: Optional[str] = None
    status: Optional[SessionStatus] = None
    decision: Optional[SessionDecision] = None
    external_id: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        d: Dict[str, Any] = {}
        if self.per_page is not None:
            d["per_page"] = self.per_page
        if self.page is not None:
            d["page"] = self.page
        if self.from_date is not None:
            d["from"] = self.from_date
        if self.to_date is not None:
            d["to"] = self.to_date
        if self.status is not None:
            d["status"] = self.status
        if self.decision is not None:
            d["decision"] = self.decision
        if self.external_id is not None:
            d["external_id"] = self.external_id
        return d


@dataclass
class SubmitSessionResponse:
    """Response from submitting a session for evaluation."""

    id: str
    status: Literal["processing"]
    message: str


# ── Document upload ───────────────────────────────────────────────────────────


@dataclass
class UploadDocumentParams:
    """Parameters for uploading an identity document.

    ``file`` can be ``bytes``, a file-like ``BinaryIO`` object, or a
    ``(filename, data)`` tuple.
    """

    session_id: str
    file: Union[bytes, BinaryIO]
    side: DocumentSide
    filename: Optional[str] = None
    document_type: Optional[DocumentType] = None


@dataclass
class UploadDocumentResponse:
    """Response from uploading a document."""

    id: str
    side: DocumentSide
    ocr_status: Literal["pending"]
    message: str


# ── Selfie upload ─────────────────────────────────────────────────────────────


@dataclass
class UploadSelfieParams:
    """Parameters for uploading a selfie."""

    session_id: str
    file: Union[bytes, BinaryIO]
    filename: Optional[str] = None


@dataclass
class UploadSelfieResponse:
    """Response from uploading a selfie."""

    id: str
    message: str


# ── Address proof upload ──────────────────────────────────────────────────────


@dataclass
class UploadAddressProofParams:
    """Parameters for uploading address proof."""

    session_id: str
    file: Union[bytes, BinaryIO]
    filename: Optional[str] = None
    document_type: Optional[AddressProofDocType] = None


@dataclass
class UploadAddressProofResponse:
    """Response from uploading address proof."""

    id: str
    ocr_status: Literal["pending"]
    message: str
