"""Pydantic schemas for API requests and responses.""" from datetime import datetime from typing import Optional from pydantic import BaseModel, EmailStr, Field from app.domain.models import AssetStatus, AssetType # Auth schemas class UserRegister(BaseModel): """User registration request.""" email: EmailStr password: str = Field(min_length=8, max_length=100) class UserLogin(BaseModel): """User login request.""" email: EmailStr password: str class Token(BaseModel): """JWT token response.""" access_token: str refresh_token: str token_type: str = "bearer" class UserResponse(BaseModel): """User information response.""" id: str email: str is_active: bool created_at: datetime model_config = {"from_attributes": True} # Asset schemas class AssetResponse(BaseModel): """Asset information response.""" id: str user_id: str type: AssetType status: AssetStatus original_filename: str content_type: str size_bytes: int sha256: Optional[str] = None captured_at: Optional[datetime] = None width: Optional[int] = None height: Optional[int] = None duration_sec: Optional[float] = None storage_key_original: str storage_key_thumb: Optional[str] = None created_at: datetime deleted_at: Optional[datetime] = None model_config = {"from_attributes": True} class AssetListResponse(BaseModel): """Paginated list of assets.""" items: list[AssetResponse] next_cursor: Optional[str] = None has_more: bool class CreateUploadRequest(BaseModel): """Request to create an upload.""" original_filename: str = Field(max_length=512) content_type: str = Field(max_length=100) size_bytes: int = Field(gt=0, le=21474836480) # Max 20GB class CreateUploadResponse(BaseModel): """Response with upload credentials.""" asset_id: str upload_url: str upload_method: str = "presigned_post" fields: Optional[dict] = None class FinalizeUploadRequest(BaseModel): """Request to finalize an upload.""" etag: Optional[str] = None sha256: Optional[str] = Field(None, max_length=64) # Download URLs class DownloadUrlResponse(BaseModel): """Pre-signed download URL.""" url: str expires_in: int # Share schemas class CreateShareRequest(BaseModel): """Request to create a share link.""" asset_id: Optional[str] = None album_id: Optional[str] = None expires_in_seconds: Optional[int] = Field(None, gt=0) password: Optional[str] = Field(None, min_length=6, max_length=100) class ShareResponse(BaseModel): """Share link information.""" id: str owner_user_id: str asset_id: Optional[str] = None album_id: Optional[str] = None token: str expires_at: Optional[datetime] = None created_at: datetime revoked_at: Optional[datetime] = None model_config = {"from_attributes": True} class ShareAccessRequest(BaseModel): """Request to access a shared resource.""" password: Optional[str] = None class ShareWithAssetResponse(BaseModel): """Share with asset information.""" share: ShareResponse asset: Optional[AssetResponse] = None # Error response class ErrorResponse(BaseModel): """Standard error response.""" error: dict[str, str | dict]