from typing import Optional, List, TYPE_CHECKING, ForwardRef from datetime import date from pydantic import BaseModel, Field from app.schemas.genre import Genre if TYPE_CHECKING: from app.schemas.character import Character else: Character = ForwardRef("Character") class AnimeBase(BaseModel): title: str alternative_titles: Optional[str] = None synopsis: Optional[str] = None episodes: Optional[int] = None status: Optional[str] = None aired_from: Optional[date] = None aired_to: Optional[date] = None duration: Optional[str] = None rating: Optional[str] = None score: Optional[float] = Field(None, ge=0, le=10) ranked: Optional[int] = None popularity: Optional[int] = None studio: Optional[str] = None source: Optional[str] = None image_url: Optional[str] = None # Season information season: Optional[str] = None season_year: Optional[int] = None # Rating details score_count: Optional[int] = None favorites_count: Optional[int] = None # Additional metadata broadcast_day: Optional[str] = None broadcast_time: Optional[str] = None is_airing: Optional[bool] = None licensors: Optional[str] = None producers: Optional[str] = None # Related anime info related_anime: Optional[dict] = None # Content tags themes: Optional[str] = None demographics: Optional[str] = None class AnimeCreate(AnimeBase): genre_ids: Optional[List[int]] = [] class AnimeUpdate(AnimeBase): title: Optional[str] = None genre_ids: Optional[List[int]] = None class Anime(AnimeBase): id: int genres: Optional[List[Genre]] = [] class Config: from_attributes = True class AnimeWithCharacters(Anime): characters: Optional[List[Character]] = [] class Config: from_attributes = True class AnimeSearchResults(BaseModel): results: List[Anime] total: int page: int size: int pages: Optional[int] = None has_next: Optional[bool] = None has_prev: Optional[bool] = None next_page: Optional[int] = None prev_page: Optional[int] = None class GenreCount(BaseModel): id: int name: str count: int class DistributionItem(BaseModel): name: str count: int class YearDistribution(BaseModel): year: int count: int class ScoreDistribution(BaseModel): score_range: str count: int class AnimeStatistics(BaseModel): total_anime: int avg_score: Optional[float] = None avg_episodes: Optional[float] = None status_distribution: List[DistributionItem] source_distribution: List[DistributionItem] studio_distribution: List[DistributionItem] year_distribution: List[YearDistribution] score_distribution: List[ScoreDistribution] top_genres: List[GenreCount]