from datetime import datetime from typing import TYPE_CHECKING, Optional from pydantic import BaseModel, Field, validator # Use forward references for type annotations from app.schemas.genre import Genre # Import types for type checking only if TYPE_CHECKING: from app.schemas.author import Author from app.schemas.publisher import Publisher # Shared properties class MangaBase(BaseModel): title: str = Field(..., min_length=1, max_length=255, description="Title of the manga") original_title: str | None = Field( None, max_length=255, description="Original title in Japanese or other language" ) isbn: str | None = Field(None, max_length=20, description="ISBN of the manga volume") description: str | None = Field(None, description="Description of the manga") volume_number: int | None = Field(None, ge=1, description="Volume number in the series") total_volumes: int | None = Field( None, ge=1, description="Total number of volumes in the series" ) publication_date: datetime | None = Field(None, description="Publication date of the manga") page_count: int | None = Field(None, ge=1, description="Number of pages") price: float | None = Field(None, ge=0, description="Price of the manga") quantity: int = Field(0, ge=0, description="Quantity in inventory") in_stock: bool = Field(True, description="Whether the manga is in stock") rating: float | None = Field(None, ge=0, le=10, description="Rating of the manga (0-10)") language: str | None = Field(None, max_length=50, description="Language of the manga") cover_image_url: str | None = Field(None, max_length=255, description="URL to the cover image") @validator("total_volumes") def validate_total_volumes(self, v, values): if v is not None and "volume_number" in values and values["volume_number"] is not None: if v < values["volume_number"]: raise ValueError("Total volumes must be greater than or equal to volume number") return v # Properties to receive on manga creation class MangaCreate(MangaBase): author_id: int | None = Field(None, description="ID of the author") publisher_id: int | None = Field(None, description="ID of the publisher") genre_ids: list[int] | None = Field(None, description="IDs of the genres") # Properties to receive on manga update class MangaUpdate(MangaBase): title: str | None = Field(None, min_length=1, max_length=255, description="Title of the manga") author_id: int | None = Field(None, description="ID of the author") publisher_id: int | None = Field(None, description="ID of the publisher") genre_ids: list[int] | None = Field(None, description="IDs of the genres") # Properties shared by models stored in DB class MangaInDBBase(MangaBase): id: int author_id: int | None publisher_id: int | None created_at: datetime updated_at: datetime class Config: orm_mode = True # Properties to return to client class Manga(MangaInDBBase): pass # Properties properties stored in DB class MangaInDB(MangaInDBBase): pass # Additional properties for response with relationships class MangaWithRelations(Manga): author: Optional["Author"] = None publisher: Optional["Publisher"] = None genres: list[Genre] = []