""" Pagination models for server-side pagination, sorting, and filtering. All models use camelStyle naming convention for consistency with frontend. """ from typing import List, Dict, Any, Optional, Generic, TypeVar from pydantic import BaseModel, Field import math T = TypeVar('T') class SortField(BaseModel): """ Single sort field configuration. """ field: str = Field(..., description="Field name to sort by") direction: str = Field(..., description="Sort direction: 'asc' or 'desc'") class PaginationParams(BaseModel): """ Complete pagination state including page, sorting, and filters. """ page: int = Field(ge=1, description="Current page number (1-based)") pageSize: int = Field(ge=1, le=1000, description="Number of items per page") sort: List[SortField] = Field(default_factory=list, description="List of sort fields in priority order") filters: Optional[Dict[str, Any]] = Field(default=None, description="Filter criteria (structure TBD for future implementation)") class PaginationRequest(BaseModel): """ Pagination request parameters sent from frontend to backend. All fields are optional. If pagination=None, no pagination is applied. """ pagination: Optional[PaginationParams] = None class PaginatedResult(BaseModel): """ Internal result structure from interface layer. Used when pagination is requested. """ items: List[Any] totalItems: int totalPages: int # Calculated as: math.ceil(totalItems / pageSize) class PaginationMetadata(BaseModel): """ Pagination metadata returned to frontend for rendering controls. Contains all information needed to render pagination UI and handle user interactions. """ currentPage: int = Field(..., description="Current page number (1-based)") pageSize: int = Field(..., description="Number of items per page") totalItems: int = Field(..., description="Total number of items across all pages (after filters)") totalPages: int = Field(..., description="Total number of pages (calculated from totalItems / pageSize)") sort: List[SortField] = Field(..., description="Current sort configuration applied") filters: Optional[Dict[str, Any]] = Field(default=None, description="Current filters applied (for future use)") class PaginatedResponse(BaseModel, Generic[T]): """ Response containing paginated data and metadata. """ items: List[T] = Field(..., description="Array of items for current page") pagination: Optional[PaginationMetadata] = Field(..., description="Pagination metadata (None if pagination not applied)") class Config: arbitrary_types_allowed = True