""" Pydantic schemas for photos """ from pydantic import BaseModel, Field from typing import Optional, List, Dict, Any from datetime import datetime class PhotoBase(BaseModel): """Base photo schema""" filename: str media_type: str original_format: Optional[str] = None width: Optional[int] = None height: Optional[int] = None file_size: Optional[int] = None taken_at: Optional[datetime] = None taken_at_source: Optional[str] = None user_title: Optional[str] = None user_notes: Optional[str] = None rating: int = 0 color_label: Optional[str] = None class PhotoResponse(PhotoBase): """Photo response schema""" id: str filepath: str folder_id: Optional[str] = None file_hash: Optional[str] = None added_at: datetime updated_at: Optional[datetime] = None is_discarded: bool = False discarded_at: Optional[datetime] = None thumb_small: Optional[str] = None thumb_medium: Optional[str] = None thumb_large: Optional[str] = None processing_status: str = 'pending' processing_error: Optional[str] = None exif_json: Optional[str] = None latitude: Optional[float] = None longitude: Optional[float] = None is_duplicate: bool = False live_photo_video_id: Optional[str] = None # tags: List[Dict[str, Any]] = [] # TODO: Enable when using eager loading class Config: orm_mode = True from_attributes = True class PhotoUpdate(BaseModel): """Photo update schema""" filename: Optional[str] = None user_title: Optional[str] = None user_notes: Optional[str] = None rating: Optional[int] = Field(None, ge=0, le=5) color_label: Optional[str] = None is_discarded: Optional[bool] = None taken_at: Optional[datetime] = None class PhotoListResponse(BaseModel): """Photo list response with pagination""" photos: List[PhotoResponse] total: int page: int per_page: int pages: int class BulkAction(BaseModel): """Bulk action on photos""" ids: List[str] action: str # 'discard', 'restore', 'delete_permanent', 'move', 'copy', 'add_tag', 'remove_tag', 'set_rating', 'set_color' value: Optional[Any] = None # For actions that need a value (rating, color, tag_id, folder_id)