"""
Common schemas used across the API for pagination, responses, filtering, and sorting.
"""

from enum import Enum
from math import ceil
from typing import TypeVar
from uuid import UUID

from pydantic import BaseModel, Field

T = TypeVar("T")


class SortOrder(str, Enum):
    """Sort order options."""

    ASC = "asc"
    DESC = "desc"


class PaginationParams(BaseModel):
    """Parameters for pagination."""

    page: int = Field(default=1, ge=1, description="Page number (1-indexed)")
    limit: int = Field(
        default=20, ge=1, le=100, description="Number of items per page (max 100)"
    )

    @property
    def offset(self) -> int:
        """Calculate the offset for database queries."""
        return (self.page - 1) * self.limit

    @property
    def skip(self) -> int:
        """Alias for offset (compatibility with existing code)."""
        return self.offset

    model_config = {"json_schema_extra": {"example": {"page": 1, "limit": 20}}}


class SortParams(BaseModel):
    """Parameters for sorting."""

    sort_by: str | None = Field(default=None, description="Field name to sort by")
    sort_order: SortOrder = Field(
        default=SortOrder.ASC, description="Sort order (asc or desc)"
    )

    model_config = {
        "json_schema_extra": {
            "example": {"sort_by": "created_at", "sort_order": "desc"}
        }
    }


class PaginationMeta(BaseModel):
    """Metadata for paginated responses."""

    total: int = Field(..., description="Total number of items")
    page: int = Field(..., description="Current page number")
    page_size: int = Field(..., description="Number of items in current page")
    total_pages: int = Field(..., description="Total number of pages")
    has_next: bool = Field(..., description="Whether there is a next page")
    has_prev: bool = Field(..., description="Whether there is a previous page")

    model_config = {
        "json_schema_extra": {
            "example": {
                "total": 150,
                "page": 1,
                "page_size": 20,
                "total_pages": 8,
                "has_next": True,
                "has_prev": False,
            }
        }
    }


class PaginatedResponse[T](BaseModel):
    """Generic paginated response wrapper."""

    data: list[T] = Field(..., description="List of items")
    pagination: PaginationMeta = Field(..., description="Pagination metadata")

    model_config = {
        "json_schema_extra": {
            "example": {
                "data": [{"id": "123", "name": "Example Item"}],
                "pagination": {
                    "total": 150,
                    "page": 1,
                    "page_size": 20,
                    "total_pages": 8,
                    "has_next": True,
                    "has_prev": False,
                },
            }
        }
    }


class MessageResponse(BaseModel):
    """Simple message response."""

    success: bool = Field(default=True, description="Operation success status")
    message: str = Field(..., description="Human-readable message")

    model_config = {
        "json_schema_extra": {
            "example": {"success": True, "message": "Operation completed successfully"}
        }
    }


class BulkActionRequest(BaseModel):
    """Request schema for bulk operations on multiple items."""

    ids: list[UUID] = Field(
        ...,
        min_length=1,
        max_length=100,
        description="List of item IDs to perform action on (max 100)",
    )

    model_config = {
        "json_schema_extra": {
            "example": {
                "ids": [
                    "550e8400-e29b-41d4-a716-446655440000",
                    "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
                ]
            }
        }
    }


class BulkActionResponse(BaseModel):
    """Response schema for bulk operations."""

    success: bool = Field(default=True, description="Operation success status")
    message: str = Field(..., description="Human-readable message")
    affected_count: int = Field(
        ..., description="Number of items affected by the operation"
    )

    model_config = {
        "json_schema_extra": {
            "example": {
                "success": True,
                "message": "Successfully deactivated 5 users",
                "affected_count": 5,
            }
        }
    }


def create_pagination_meta(
    total: int, page: int, limit: int, items_count: int
) -> PaginationMeta:
    """
    Helper function to create pagination metadata.

    Args:
        total: Total number of items
        page: Current page number
        limit: Items per page
        items_count: Number of items in current page

    Returns:
        PaginationMeta object with calculated values
    """
    total_pages = ceil(total / limit) if limit > 0 else 0

    return PaginationMeta(
        total=total,
        page=page,
        page_size=items_count,
        total_pages=total_pages,
        has_next=page < total_pages,
        has_prev=page > 1,
    )
