"""
Standardised API response envelope types.

Every endpoint in Munal LMS returns one of three shapes:

    SuccessResponse[T]    → { "success": true,  "data": <T> }
    PaginatedResponse[T]  → { "success": true,  "data": [...], "meta": { ... } }
    ErrorResponse         → { "success": false, "error": { "code": "...", "message": "..." } }

This guarantees the frontend can always check `response.success` first, then
branch on `response.data` or `response.error` — no shape guessing required.
"""

from typing import Generic, TypeVar

from pydantic import BaseModel, Field

T = TypeVar("T")


# ── Pagination Metadata ────────────────────────────────────────────────────────


class PaginationMeta(BaseModel):
    """Metadata attached to every paginated response."""

    total: int = Field(..., description="Total number of records matching the query")
    page: int = Field(..., description="Current page number (1-indexed)")
    limit: int = Field(..., description="Number of records per page")
    pages: int = Field(..., description="Total number of pages")


# ── Success Envelopes ─────────────────────────────────────────────────────────


class SuccessResponse(BaseModel, Generic[T]):
    """
    Standard response envelope for single-object endpoints.

    Usage in route handler:
        return SuccessResponse(data=patient_response)
    """

    success: bool = True
    data: T


class PaginatedResponse(BaseModel, Generic[T]):
    """
    Standard response envelope for list endpoints.

    Usage in route handler:
        return PaginatedResponse(data=items, meta=meta)
    """

    success: bool = True
    data: list[T]
    meta: PaginationMeta


# ── Error Envelope ────────────────────────────────────────────────────────────


class ErrorDetail(BaseModel):
    """Structured error payload inside ErrorResponse."""

    code: str = Field(..., description="Machine-readable error key (e.g. NOT_FOUND)")
    message: str = Field(..., description="Human-readable explanation of the error")


class ErrorResponse(BaseModel):
    """
    Standard error response returned by the global exception handler.

    Never construct this manually in route handlers — raise an AppException
    subclass and let the exception handler produce this shape.
    """

    success: bool = False
    error: ErrorDetail
