"""
Pydantic schemas for API v1 endpoints.

These schemas define the structure of request and response data for the REST API.
"""
from datetime import date, datetime
from typing import Optional, List
from decimal import Decimal
from pydantic import BaseModel, Field, field_validator
from uuid import UUID


# ============================================================================
# Base Schemas
# ============================================================================

class TimestampSchema(BaseModel):
    """Base schema with timestamps."""
    created: datetime
    modified: datetime


# ============================================================================
# Company Schemas
# ============================================================================

class CompanyBase(BaseModel):
    """Base company schema with common fields."""
    name: str = Field(..., min_length=1, max_length=255)
    description: Optional[str] = None
    company_types: List[str] = Field(default_factory=list)
    founded_date: Optional[date] = None
    founded_date_precision: str = Field(default='day')
    closed_date: Optional[date] = None
    closed_date_precision: str = Field(default='day')
    website: Optional[str] = None
    logo_image_id: Optional[str] = None
    logo_image_url: Optional[str] = None


class CompanyCreate(CompanyBase):
    """Schema for creating a company."""
    pass


class CompanyUpdate(BaseModel):
    """Schema for updating a company (all fields optional)."""
    name: Optional[str] = Field(None, min_length=1, max_length=255)
    description: Optional[str] = None
    company_types: Optional[List[str]] = None
    founded_date: Optional[date] = None
    founded_date_precision: Optional[str] = None
    closed_date: Optional[date] = None
    closed_date_precision: Optional[str] = None
    website: Optional[str] = None
    logo_image_id: Optional[str] = None
    logo_image_url: Optional[str] = None


class CompanyOut(CompanyBase, TimestampSchema):
    """Schema for company output."""
    id: UUID
    slug: str
    park_count: int
    ride_count: int

    class Config:
        from_attributes = True


# ============================================================================
# RideModel Schemas
# ============================================================================

class RideModelBase(BaseModel):
    """Base ride model schema."""
    name: str = Field(..., min_length=1, max_length=255)
    description: Optional[str] = None
    manufacturer_id: UUID
    model_type: str
    typical_height: Optional[Decimal] = None
    typical_speed: Optional[Decimal] = None
    typical_capacity: Optional[int] = None
    image_id: Optional[str] = None
    image_url: Optional[str] = None


class RideModelCreate(RideModelBase):
    """Schema for creating a ride model."""
    pass


class RideModelUpdate(BaseModel):
    """Schema for updating a ride model (all fields optional)."""
    name: Optional[str] = Field(None, min_length=1, max_length=255)
    description: Optional[str] = None
    manufacturer_id: Optional[UUID] = None
    model_type: Optional[str] = None
    typical_height: Optional[Decimal] = None
    typical_speed: Optional[Decimal] = None
    typical_capacity: Optional[int] = None
    image_id: Optional[str] = None
    image_url: Optional[str] = None


class RideModelOut(RideModelBase, TimestampSchema):
    """Schema for ride model output."""
    id: UUID
    slug: str
    installation_count: int
    manufacturer_name: Optional[str] = None

    class Config:
        from_attributes = True


# ============================================================================
# Park Schemas
# ============================================================================

class ParkBase(BaseModel):
    """Base park schema."""
    name: str = Field(..., min_length=1, max_length=255)
    description: Optional[str] = None
    park_type: str
    status: str = Field(default='operating')
    opening_date: Optional[date] = None
    opening_date_precision: str = Field(default='day')
    closing_date: Optional[date] = None
    closing_date_precision: str = Field(default='day')
    latitude: Optional[Decimal] = None
    longitude: Optional[Decimal] = None
    operator_id: Optional[UUID] = None
    website: Optional[str] = None
    banner_image_id: Optional[str] = None
    banner_image_url: Optional[str] = None
    logo_image_id: Optional[str] = None
    logo_image_url: Optional[str] = None


class ParkCreate(ParkBase):
    """Schema for creating a park."""
    pass


class ParkUpdate(BaseModel):
    """Schema for updating a park (all fields optional)."""
    name: Optional[str] = Field(None, min_length=1, max_length=255)
    description: Optional[str] = None
    park_type: Optional[str] = None
    status: Optional[str] = None
    opening_date: Optional[date] = None
    opening_date_precision: Optional[str] = None
    closing_date: Optional[date] = None
    closing_date_precision: Optional[str] = None
    latitude: Optional[Decimal] = None
    longitude: Optional[Decimal] = None
    operator_id: Optional[UUID] = None
    website: Optional[str] = None
    banner_image_id: Optional[str] = None
    banner_image_url: Optional[str] = None
    logo_image_id: Optional[str] = None
    logo_image_url: Optional[str] = None


class ParkOut(ParkBase, TimestampSchema):
    """Schema for park output."""
    id: UUID
    slug: str
    ride_count: int
    coaster_count: int
    operator_name: Optional[str] = None
    coordinates: Optional[tuple[float, float]] = None

    class Config:
        from_attributes = True


# ============================================================================
# Ride Schemas
# ============================================================================

class RideBase(BaseModel):
    """Base ride schema."""
    name: str = Field(..., min_length=1, max_length=255)
    description: Optional[str] = None
    park_id: UUID
    ride_category: str
    ride_type: Optional[str] = None
    is_coaster: bool = Field(default=False)
    status: str = Field(default='operating')
    opening_date: Optional[date] = None
    opening_date_precision: str = Field(default='day')
    closing_date: Optional[date] = None
    closing_date_precision: str = Field(default='day')
    manufacturer_id: Optional[UUID] = None
    model_id: Optional[UUID] = None
    height: Optional[Decimal] = None
    speed: Optional[Decimal] = None
    length: Optional[Decimal] = None
    duration: Optional[int] = None
    inversions: Optional[int] = None
    capacity: Optional[int] = None
    image_id: Optional[str] = None
    image_url: Optional[str] = None


class RideCreate(RideBase):
    """Schema for creating a ride."""
    pass


class RideUpdate(BaseModel):
    """Schema for updating a ride (all fields optional)."""
    name: Optional[str] = Field(None, min_length=1, max_length=255)
    description: Optional[str] = None
    park_id: Optional[UUID] = None
    ride_category: Optional[str] = None
    ride_type: Optional[str] = None
    is_coaster: Optional[bool] = None
    status: Optional[str] = None
    opening_date: Optional[date] = None
    opening_date_precision: Optional[str] = None
    closing_date: Optional[date] = None
    closing_date_precision: Optional[str] = None
    manufacturer_id: Optional[UUID] = None
    model_id: Optional[UUID] = None
    height: Optional[Decimal] = None
    speed: Optional[Decimal] = None
    length: Optional[Decimal] = None
    duration: Optional[int] = None
    inversions: Optional[int] = None
    capacity: Optional[int] = None
    image_id: Optional[str] = None
    image_url: Optional[str] = None


class RideOut(RideBase, TimestampSchema):
    """Schema for ride output."""
    id: UUID
    slug: str
    park_name: Optional[str] = None
    manufacturer_name: Optional[str] = None
    model_name: Optional[str] = None

    class Config:
        from_attributes = True


# ============================================================================
# Pagination Schemas
# ============================================================================

class PaginatedResponse(BaseModel):
    """Generic paginated response schema."""
    items: List
    total: int
    page: int
    page_size: int
    total_pages: int


class CompanyListOut(BaseModel):
    """Paginated company list response."""
    items: List[CompanyOut]
    total: int
    page: int
    page_size: int
    total_pages: int


class RideModelListOut(BaseModel):
    """Paginated ride model list response."""
    items: List[RideModelOut]
    total: int
    page: int
    page_size: int
    total_pages: int


class ParkListOut(BaseModel):
    """Paginated park list response."""
    items: List[ParkOut]
    total: int
    page: int
    page_size: int
    total_pages: int


class RideListOut(BaseModel):
    """Paginated ride list response."""
    items: List[RideOut]
    total: int
    page: int
    page_size: int
    total_pages: int


# ============================================================================
# Error Schemas
# ============================================================================

class ErrorResponse(BaseModel):
    """Standard error response schema."""
    detail: str
    code: Optional[str] = None


class ValidationErrorResponse(BaseModel):
    """Validation error response schema."""
    detail: str
    errors: Optional[List[dict]] = None


# ============================================================================
# Moderation Schemas
# ============================================================================

class SubmissionItemBase(BaseModel):
    """Base submission item schema."""
    field_name: str = Field(..., min_length=1, max_length=100)
    field_label: Optional[str] = None
    old_value: Optional[dict] = None
    new_value: Optional[dict] = None
    change_type: str = Field(default='modify')
    is_required: bool = Field(default=False)
    order: int = Field(default=0)


class SubmissionItemCreate(SubmissionItemBase):
    """Schema for creating a submission item."""
    pass


class SubmissionItemOut(SubmissionItemBase, TimestampSchema):
    """Schema for submission item output."""
    id: UUID
    submission_id: UUID
    status: str
    reviewed_by_id: Optional[UUID] = None
    reviewed_by_email: Optional[str] = None
    reviewed_at: Optional[datetime] = None
    rejection_reason: Optional[str] = None
    old_value_display: str
    new_value_display: str

    class Config:
        from_attributes = True


class ContentSubmissionBase(BaseModel):
    """Base content submission schema."""
    submission_type: str
    title: str = Field(..., min_length=1, max_length=255)
    description: Optional[str] = None
    entity_type: str
    entity_id: UUID


class ContentSubmissionCreate(BaseModel):
    """Schema for creating a content submission."""
    entity_type: str = Field(..., description="Entity type (park, ride, company, ridemodel)")
    entity_id: UUID = Field(..., description="ID of entity being modified")
    submission_type: str = Field(..., description="Operation type (create, update, delete)")
    title: str = Field(..., min_length=1, max_length=255, description="Brief description")
    description: Optional[str] = Field(None, description="Detailed description")
    items: List[SubmissionItemCreate] = Field(..., min_items=1, description="List of changes")
    metadata: Optional[dict] = Field(default_factory=dict)
    auto_submit: bool = Field(default=True, description="Auto-submit for review")


class ContentSubmissionOut(TimestampSchema):
    """Schema for content submission output."""
    id: UUID
    status: str
    submission_type: str
    title: str
    description: Optional[str] = None
    entity_type: str
    entity_id: UUID
    user_id: UUID
    user_email: str
    locked_by_id: Optional[UUID] = None
    locked_by_email: Optional[str] = None
    locked_at: Optional[datetime] = None
    reviewed_by_id: Optional[UUID] = None
    reviewed_by_email: Optional[str] = None
    reviewed_at: Optional[datetime] = None
    rejection_reason: Optional[str] = None
    source: str
    metadata: dict
    items_count: int
    approved_items_count: int
    rejected_items_count: int

    class Config:
        from_attributes = True


class ContentSubmissionDetail(ContentSubmissionOut):
    """Detailed submission with items."""
    items: List[SubmissionItemOut]

    class Config:
        from_attributes = True


class StartReviewRequest(BaseModel):
    """Schema for starting a review."""
    pass  # No additional fields needed


class ApproveRequest(BaseModel):
    """Schema for approving a submission."""
    pass  # No additional fields needed


class ApproveSelectiveRequest(BaseModel):
    """Schema for selective approval."""
    item_ids: List[UUID] = Field(..., min_items=1, description="List of item IDs to approve")


class RejectRequest(BaseModel):
    """Schema for rejecting a submission."""
    reason: str = Field(..., min_length=1, description="Reason for rejection")


class RejectSelectiveRequest(BaseModel):
    """Schema for selective rejection."""
    item_ids: List[UUID] = Field(..., min_items=1, description="List of item IDs to reject")
    reason: Optional[str] = Field(None, description="Reason for rejection")


class ApprovalResponse(BaseModel):
    """Response for approval operations."""
    success: bool
    message: str
    submission: ContentSubmissionOut


class SelectiveApprovalResponse(BaseModel):
    """Response for selective approval."""
    success: bool
    message: str
    approved: int
    total: int
    pending: int
    submission_approved: bool


class SelectiveRejectionResponse(BaseModel):
    """Response for selective rejection."""
    success: bool
    message: str
    rejected: int
    total: int
    pending: int
    submission_complete: bool


class SubmissionListOut(BaseModel):
    """Paginated submission list response."""
    items: List[ContentSubmissionOut]
    total: int
    page: int
    page_size: int
    total_pages: int


# ============================================================================
# Versioning Schemas
# ============================================================================

class EntityVersionSchema(TimestampSchema):
    """Schema for entity version output."""
    id: UUID
    entity_type: str
    entity_id: UUID
    entity_name: str
    version_number: int
    change_type: str
    snapshot: dict
    changed_fields: dict
    changed_by_id: Optional[UUID] = None
    changed_by_email: Optional[str] = None
    submission_id: Optional[UUID] = None
    comment: Optional[str] = None
    diff_summary: str

    class Config:
        from_attributes = True


class VersionHistoryResponseSchema(BaseModel):
    """Response schema for version history."""
    entity_id: str
    entity_type: str
    entity_name: str
    total_versions: int
    versions: List[EntityVersionSchema]


class VersionDiffSchema(BaseModel):
    """Schema for version diff response."""
    entity_id: str
    entity_type: str
    entity_name: str
    version_number: int
    version_date: datetime
    differences: dict
    changed_field_count: int


class VersionComparisonSchema(BaseModel):
    """Schema for comparing two versions."""
    version1: EntityVersionSchema
    version2: EntityVersionSchema
    differences: dict
    changed_field_count: int


# ============================================================================
# Generic Utility Schemas
# ============================================================================

class MessageSchema(BaseModel):
    """Generic message response."""
    message: str
    success: bool = True


class ErrorSchema(BaseModel):
    """Standard error response."""
    error: str
    detail: Optional[str] = None


# ============================================================================
# Authentication Schemas
# ============================================================================

class UserBase(BaseModel):
    """Base user schema."""
    email: str = Field(..., description="Email address")
    username: Optional[str] = Field(None, description="Username")
    first_name: Optional[str] = Field(None, max_length=150)
    last_name: Optional[str] = Field(None, max_length=150)


class UserRegisterRequest(BaseModel):
    """Schema for user registration."""
    email: str = Field(..., description="Email address")
    password: str = Field(..., min_length=8, description="Password (min 8 characters)")
    password_confirm: str = Field(..., description="Password confirmation")
    username: Optional[str] = Field(None, description="Username (auto-generated if not provided)")
    first_name: Optional[str] = Field(None, max_length=150)
    last_name: Optional[str] = Field(None, max_length=150)
    
    @field_validator('password_confirm')
    def passwords_match(cls, v, info):
        if 'password' in info.data and v != info.data['password']:
            raise ValueError('Passwords do not match')
        return v


class UserLoginRequest(BaseModel):
    """Schema for user login."""
    email: str = Field(..., description="Email address")
    password: str = Field(..., description="Password")
    mfa_token: Optional[str] = Field(None, description="MFA token if enabled")


class TokenResponse(BaseModel):
    """Schema for token response."""
    access: str = Field(..., description="JWT access token")
    refresh: str = Field(..., description="JWT refresh token")
    token_type: str = Field(default="Bearer")


class TokenRefreshRequest(BaseModel):
    """Schema for token refresh."""
    refresh: str = Field(..., description="Refresh token")


class UserProfileOut(BaseModel):
    """Schema for user profile output."""
    id: UUID
    email: str
    username: str
    first_name: str
    last_name: str
    display_name: str
    avatar_url: Optional[str] = None
    bio: Optional[str] = None
    reputation_score: int
    mfa_enabled: bool
    banned: bool
    date_joined: datetime
    last_login: Optional[datetime] = None
    oauth_provider: str
    
    class Config:
        from_attributes = True


class UserProfileUpdate(BaseModel):
    """Schema for updating user profile."""
    first_name: Optional[str] = Field(None, max_length=150)
    last_name: Optional[str] = Field(None, max_length=150)
    username: Optional[str] = Field(None, max_length=150)
    bio: Optional[str] = Field(None, max_length=500)
    avatar_url: Optional[str] = None


class ChangePasswordRequest(BaseModel):
    """Schema for password change."""
    old_password: str = Field(..., description="Current password")
    new_password: str = Field(..., min_length=8, description="New password")
    new_password_confirm: str = Field(..., description="New password confirmation")
    
    @field_validator('new_password_confirm')
    def passwords_match(cls, v, info):
        if 'new_password' in info.data and v != info.data['new_password']:
            raise ValueError('Passwords do not match')
        return v


class ResetPasswordRequest(BaseModel):
    """Schema for password reset."""
    email: str = Field(..., description="Email address")


class ResetPasswordConfirm(BaseModel):
    """Schema for password reset confirmation."""
    token: str = Field(..., description="Reset token")
    password: str = Field(..., min_length=8, description="New password")
    password_confirm: str = Field(..., description="Password confirmation")
    
    @field_validator('password_confirm')
    def passwords_match(cls, v, info):
        if 'password' in info.data and v != info.data['password']:
            raise ValueError('Passwords do not match')
        return v


class UserRoleOut(BaseModel):
    """Schema for user role output."""
    role: str
    is_moderator: bool
    is_admin: bool
    granted_at: datetime
    granted_by_email: Optional[str] = None
    
    class Config:
        from_attributes = True


class UserPermissionsOut(BaseModel):
    """Schema for user permissions."""
    can_submit: bool
    can_moderate: bool
    can_admin: bool
    can_edit_own: bool
    can_delete_own: bool


class UserStatsOut(BaseModel):
    """Schema for user statistics."""
    total_submissions: int
    approved_submissions: int
    reputation_score: int
    member_since: datetime
    last_active: Optional[datetime] = None


class UserProfilePreferencesOut(BaseModel):
    """Schema for user preferences."""
    email_notifications: bool
    email_on_submission_approved: bool
    email_on_submission_rejected: bool
    profile_public: bool
    show_email: bool
    
    class Config:
        from_attributes = True


class UserProfilePreferencesUpdate(BaseModel):
    """Schema for updating user preferences."""
    email_notifications: Optional[bool] = None
    email_on_submission_approved: Optional[bool] = None
    email_on_submission_rejected: Optional[bool] = None
    profile_public: Optional[bool] = None
    show_email: Optional[bool] = None


class TOTPEnableResponse(BaseModel):
    """Schema for TOTP enable response."""
    secret: str = Field(..., description="TOTP secret key")
    qr_code_url: str = Field(..., description="QR code URL for authenticator apps")
    backup_codes: List[str] = Field(default_factory=list, description="Backup codes")


class TOTPConfirmRequest(BaseModel):
    """Schema for TOTP confirmation."""
    token: str = Field(..., min_length=6, max_length=6, description="6-digit TOTP token")


class TOTPVerifyRequest(BaseModel):
    """Schema for TOTP verification."""
    token: str = Field(..., min_length=6, max_length=6, description="6-digit TOTP token")


class BanUserRequest(BaseModel):
    """Schema for banning a user."""
    user_id: UUID = Field(..., description="User ID to ban")
    reason: str = Field(..., min_length=1, description="Reason for ban")


class UnbanUserRequest(BaseModel):
    """Schema for unbanning a user."""
    user_id: UUID = Field(..., description="User ID to unban")


class AssignRoleRequest(BaseModel):
    """Schema for assigning a role."""
    user_id: UUID = Field(..., description="User ID")
    role: str = Field(..., description="Role to assign (user, moderator, admin)")


class UserListOut(BaseModel):
    """Paginated user list response."""
    items: List[UserProfileOut]
    total: int
    page: int
    page_size: int
    total_pages: int


# ============================================================================
# Photo/Media Schemas
# ============================================================================

class PhotoBase(BaseModel):
    """Base photo schema."""
    title: Optional[str] = Field(None, max_length=255)
    description: Optional[str] = None
    credit: Optional[str] = Field(None, max_length=255, description="Photo credit/attribution")
    photo_type: str = Field(default='gallery', description="Type: main, gallery, banner, logo, thumbnail, other")
    is_visible: bool = Field(default=True)


class PhotoUploadRequest(PhotoBase):
    """Schema for photo upload request (form data)."""
    entity_type: Optional[str] = Field(None, description="Entity type to attach to")
    entity_id: Optional[UUID] = Field(None, description="Entity ID to attach to")


class PhotoUpdate(BaseModel):
    """Schema for updating photo metadata."""
    title: Optional[str] = Field(None, max_length=255)
    description: Optional[str] = None
    credit: Optional[str] = Field(None, max_length=255)
    photo_type: Optional[str] = None
    is_visible: Optional[bool] = None
    display_order: Optional[int] = None


class PhotoOut(PhotoBase, TimestampSchema):
    """Schema for photo output."""
    id: UUID
    cloudflare_image_id: str
    cloudflare_url: str
    uploaded_by_id: UUID
    uploaded_by_email: Optional[str] = None
    moderation_status: str
    moderated_by_id: Optional[UUID] = None
    moderated_by_email: Optional[str] = None
    moderated_at: Optional[datetime] = None
    moderation_notes: Optional[str] = None
    entity_type: Optional[str] = None
    entity_id: Optional[str] = None
    entity_name: Optional[str] = None
    width: int
    height: int
    file_size: int
    mime_type: str
    display_order: int
    
    # Generated URLs for different variants
    thumbnail_url: Optional[str] = None
    banner_url: Optional[str] = None
    
    class Config:
        from_attributes = True


class PhotoListOut(BaseModel):
    """Paginated photo list response."""
    items: List[PhotoOut]
    total: int
    page: int
    page_size: int
    total_pages: int


class PhotoUploadResponse(BaseModel):
    """Response for photo upload."""
    success: bool
    message: str
    photo: PhotoOut


class PhotoModerateRequest(BaseModel):
    """Schema for moderating a photo."""
    status: str = Field(..., description="Status: approved, rejected, flagged")
    notes: Optional[str] = Field(None, description="Moderation notes")


class PhotoReorderRequest(BaseModel):
    """Schema for reordering photos."""
    photo_ids: List[int] = Field(..., min_items=1, description="Ordered list of photo IDs")
    photo_type: Optional[str] = Field(None, description="Optional photo type filter")


class PhotoAttachRequest(BaseModel):
    """Schema for attaching photo to entity."""
    photo_id: UUID = Field(..., description="Photo ID to attach")
    photo_type: Optional[str] = Field('gallery', description="Photo type")


class PhotoStatsOut(BaseModel):
    """Statistics about photos."""
    total_photos: int
    pending_photos: int
    approved_photos: int
    rejected_photos: int
    flagged_photos: int
    total_size_mb: float


# ============================================================================
# Search Schemas
# ============================================================================

class SearchResultBase(BaseModel):
    """Base schema for search results."""
    id: UUID
    name: str
    slug: str
    entity_type: str
    description: Optional[str] = None
    image_url: Optional[str] = None


class CompanySearchResult(SearchResultBase):
    """Company search result."""
    company_types: List[str] = Field(default_factory=list)
    park_count: int = 0
    ride_count: int = 0


class RideModelSearchResult(SearchResultBase):
    """Ride model search result."""
    manufacturer_name: str
    model_type: str
    installation_count: int = 0


class ParkSearchResult(SearchResultBase):
    """Park search result."""
    park_type: str
    status: str
    operator_name: Optional[str] = None
    ride_count: int = 0
    coaster_count: int = 0
    coordinates: Optional[tuple[float, float]] = None


class RideSearchResult(SearchResultBase):
    """Ride search result."""
    park_name: str
    park_slug: str
    manufacturer_name: Optional[str] = None
    ride_category: str
    status: str
    is_coaster: bool


class GlobalSearchResponse(BaseModel):
    """Response for global search across all entities."""
    query: str
    total_results: int
    companies: List[CompanySearchResult] = Field(default_factory=list)
    ride_models: List[RideModelSearchResult] = Field(default_factory=list)
    parks: List[ParkSearchResult] = Field(default_factory=list)
    rides: List[RideSearchResult] = Field(default_factory=list)


class AutocompleteItem(BaseModel):
    """Single autocomplete suggestion."""
    id: UUID
    name: str
    slug: str
    entity_type: str
    park_name: Optional[str] = None  # For rides
    manufacturer_name: Optional[str] = None  # For ride models


class AutocompleteResponse(BaseModel):
    """Response for autocomplete suggestions."""
    query: str
    suggestions: List[AutocompleteItem]


class SearchFilters(BaseModel):
    """Base filters for search operations."""
    q: str = Field(..., min_length=2, max_length=200, description="Search query")
    entity_types: Optional[List[str]] = Field(None, description="Filter by entity types")
    limit: int = Field(20, ge=1, le=100, description="Maximum results per entity type")


class CompanySearchFilters(BaseModel):
    """Filters for company search."""
    q: str = Field(..., min_length=2, max_length=200, description="Search query")
    company_types: Optional[List[str]] = Field(None, description="Filter by company types")
    founded_after: Optional[date] = Field(None, description="Founded after date")
    founded_before: Optional[date] = Field(None, description="Founded before date")
    limit: int = Field(20, ge=1, le=100)


class RideModelSearchFilters(BaseModel):
    """Filters for ride model search."""
    q: str = Field(..., min_length=2, max_length=200, description="Search query")
    manufacturer_id: Optional[UUID] = Field(None, description="Filter by manufacturer")
    model_type: Optional[str] = Field(None, description="Filter by model type")
    limit: int = Field(20, ge=1, le=100)


class ParkSearchFilters(BaseModel):
    """Filters for park search."""
    q: str = Field(..., min_length=2, max_length=200, description="Search query")
    status: Optional[str] = Field(None, description="Filter by status")
    park_type: Optional[str] = Field(None, description="Filter by park type")
    operator_id: Optional[UUID] = Field(None, description="Filter by operator")
    opening_after: Optional[date] = Field(None, description="Opened after date")
    opening_before: Optional[date] = Field(None, description="Opened before date")
    latitude: Optional[float] = Field(None, description="Search center latitude")
    longitude: Optional[float] = Field(None, description="Search center longitude")
    radius: Optional[float] = Field(None, ge=0, le=500, description="Search radius in km")
    limit: int = Field(20, ge=1, le=100)


class RideSearchFilters(BaseModel):
    """Filters for ride search."""
    q: str = Field(..., min_length=2, max_length=200, description="Search query")
    park_id: Optional[UUID] = Field(None, description="Filter by park")
    manufacturer_id: Optional[UUID] = Field(None, description="Filter by manufacturer")
    model_id: Optional[UUID] = Field(None, description="Filter by model")
    status: Optional[str] = Field(None, description="Filter by status")
    ride_category: Optional[str] = Field(None, description="Filter by category")
    is_coaster: Optional[bool] = Field(None, description="Filter coasters only")
    opening_after: Optional[date] = Field(None, description="Opened after date")
    opening_before: Optional[date] = Field(None, description="Opened before date")
    min_height: Optional[Decimal] = Field(None, description="Minimum height in feet")
    max_height: Optional[Decimal] = Field(None, description="Maximum height in feet")
    min_speed: Optional[Decimal] = Field(None, description="Minimum speed in mph")
    max_speed: Optional[Decimal] = Field(None, description="Maximum speed in mph")
    limit: int = Field(20, ge=1, le=100)
