"""Sessions resource — KYC verification session management."""

from __future__ import annotations

from dataclasses import asdict
from typing import Any, Dict, Optional, Union, TYPE_CHECKING

if TYPE_CHECKING:
    from ..http_client import AsyncHttpClient, HttpClient

__all__ = ["Sessions", "AsyncSessions"]


class Sessions:
    """KYC verification sessions (synchronous).

    Example::

        session = verilock.sessions.create(
            CreateSessionParams(
                applicant_email="john@example.com",
                redirect_url="https://example.com/callback",
            )
        )
        print(session["session_url"])
    """

    def __init__(self, http: HttpClient) -> None:
        self._http = http

    def create(
        self,
        params: Any,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Create a new verification session.

        Args:
            params: A :class:`~verilock.types.sessions.CreateSessionParams` instance
                or a dict with session parameters.
            idempotency_key: Optional idempotency key for the request.

        Returns:
            Session creation response with ``id``, ``session_token``, and ``session_url``.
        """
        body = asdict(params) if hasattr(params, "__dataclass_fields__") else params
        body = {k: v for k, v in body.items() if v is not None}
        return self._http.post("/v1/sessions", body, idempotency_key=idempotency_key)

    def list(
        self,
        params: Optional[Any] = None,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """List verification sessions with optional filters.

        Args:
            params: A :class:`~verilock.types.sessions.ListSessionsParams` instance,
                a dict, or ``None`` for defaults.

        Returns:
            Paginated response with ``data`` and ``meta`` keys.
        """
        query: Optional[Dict[str, Any]] = None
        if params is not None:
            query = params.to_dict() if hasattr(params, "to_dict") else params
        return self._http.get("/v1/sessions", query, idempotency_key=idempotency_key)

    def retrieve(
        self,
        session_id: str,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Retrieve a single session by ID with full details.

        Args:
            session_id: The session ID to retrieve.

        Returns:
            Full session detail with documents, selfie, and AML screening data.
        """
        return self._http.get(
            f"/v1/sessions/{session_id}", idempotency_key=idempotency_key
        )

    def submit(
        self,
        session_id: str,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Submit a session for final evaluation.

        Call this after all documents and selfie have been uploaded.

        Args:
            session_id: The session ID to submit.

        Returns:
            Response with ``id``, ``status``, and ``message``.
        """
        return self._http.post(
            f"/v1/sessions/{session_id}/submit", idempotency_key=idempotency_key
        )

    def upload_document(
        self,
        params: Any,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Upload an identity document to a session.

        Args:
            params: A :class:`~verilock.types.sessions.UploadDocumentParams` instance
                with ``session_id``, ``file``, ``side``, and optionally
                ``document_type`` and ``filename``.

        Returns:
            Upload response with ``id``, ``side``, ``ocr_status``, and ``message``.

        Example::

            verilock.sessions.upload_document(
                UploadDocumentParams(
                    session_id="sess_123",
                    file=open("id_front.jpg", "rb").read(),
                    side="front",
                    document_type="passport",
                )
            )
        """
        fields: Dict[str, str] = {"side": params.side}
        if params.document_type:
            fields["document_type"] = params.document_type

        return self._http.upload(
            f"/v1/sessions/{params.session_id}/documents",
            params.file,
            params.filename or "document.jpg",
            fields,
            idempotency_key=idempotency_key,
        )

    def upload_selfie(
        self,
        params: Any,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Upload a selfie to a session for face matching.

        Args:
            params: A :class:`~verilock.types.sessions.UploadSelfieParams` instance
                with ``session_id``, ``file``, and optionally ``filename``.

        Returns:
            Upload response with ``id`` and ``message``.
        """
        return self._http.upload(
            f"/v1/sessions/{params.session_id}/selfie",
            params.file,
            params.filename or "selfie.jpg",
            idempotency_key=idempotency_key,
        )

    def upload_address_proof(
        self,
        params: Any,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Upload an address proof document to a session.

        Args:
            params: A :class:`~verilock.types.sessions.UploadAddressProofParams` instance.

        Returns:
            Upload response with ``id``, ``ocr_status``, and ``message``.
        """
        fields: Dict[str, str] = {}
        if params.document_type:
            fields["document_type"] = params.document_type

        return self._http.upload(
            f"/v1/sessions/{params.session_id}/address-proof",
            params.file,
            params.filename or "address_proof.jpg",
            fields if fields else None,
            idempotency_key=idempotency_key,
        )


class AsyncSessions:
    """KYC verification sessions (asynchronous)."""

    def __init__(self, http: AsyncHttpClient) -> None:
        self._http = http

    async def create(
        self,
        params: Any,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Create a new verification session."""
        body = asdict(params) if hasattr(params, "__dataclass_fields__") else params
        body = {k: v for k, v in body.items() if v is not None}
        return await self._http.post("/v1/sessions", body, idempotency_key=idempotency_key)

    async def list(
        self,
        params: Optional[Any] = None,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """List verification sessions with optional filters."""
        query: Optional[Dict[str, Any]] = None
        if params is not None:
            query = params.to_dict() if hasattr(params, "to_dict") else params
        return await self._http.get("/v1/sessions", query, idempotency_key=idempotency_key)

    async def retrieve(
        self,
        session_id: str,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Retrieve a single session by ID with full details."""
        return await self._http.get(
            f"/v1/sessions/{session_id}", idempotency_key=idempotency_key
        )

    async def submit(
        self,
        session_id: str,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Submit a session for final evaluation."""
        return await self._http.post(
            f"/v1/sessions/{session_id}/submit", idempotency_key=idempotency_key
        )

    async def upload_document(
        self,
        params: Any,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Upload an identity document to a session."""
        fields: Dict[str, str] = {"side": params.side}
        if params.document_type:
            fields["document_type"] = params.document_type

        return await self._http.upload(
            f"/v1/sessions/{params.session_id}/documents",
            params.file,
            params.filename or "document.jpg",
            fields,
            idempotency_key=idempotency_key,
        )

    async def upload_selfie(
        self,
        params: Any,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Upload a selfie to a session for face matching."""
        return await self._http.upload(
            f"/v1/sessions/{params.session_id}/selfie",
            params.file,
            params.filename or "selfie.jpg",
            idempotency_key=idempotency_key,
        )

    async def upload_address_proof(
        self,
        params: Any,
        *,
        idempotency_key: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Upload an address proof document to a session."""
        fields: Dict[str, str] = {}
        if params.document_type:
            fields["document_type"] = params.document_type

        return await self._http.upload(
            f"/v1/sessions/{params.session_id}/address-proof",
            params.file,
            params.filename or "address_proof.jpg",
            fields if fields else None,
            idempotency_key=idempotency_key,
        )
