import uuid from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, field_validator class PrizeCreate(BaseModel): name: str = Field(..., min_length=1, max_length=255) description: Optional[str] = None quantity: int = Field(1, ge=1, le=1000) class PrizeResponse(BaseModel): id: uuid.UUID name: str description: Optional[str] = None quantity: int sort_order: int model_config = {"from_attributes": True} def _to_naive_utc(v: datetime | None) -> datetime | None: if v is None: return None if v.tzinfo is not None: from datetime import timezone return v.astimezone(timezone.utc).replace(tzinfo=None) return v class LotteryCreate(BaseModel): title: str = Field(..., min_length=1, max_length=255) description: Optional[str] = None contact_info: Optional[str] = None target_chat_id: Optional[int] = None target_chat_title: Optional[str] = None require_membership: bool = False required_chat_ids: list[int] = Field(default_factory=list) required_chat_titles: list[str] = Field(default_factory=list) required_chat_types: list[str] = Field(default_factory=list) required_chat_usernames: list[str] = Field(default_factory=list) allow_multiple_wins: bool = False invite_link_chat_ids: list[int] = Field(default_factory=list) required_chat_passphrases: list[str] = Field(default_factory=list) max_participants: Optional[int] = Field(None, ge=1) draw_at: Optional[datetime] = None auto_draw_count: Optional[int] = Field(None, ge=1) creator_timezone: Optional[str] = Field(None, max_length=64) @field_validator("draw_at", mode="after") @classmethod def normalize_draw_at(cls, v: datetime | None) -> datetime | None: return _to_naive_utc(v) class LotteryUpdate(BaseModel): title: Optional[str] = Field(None, min_length=1, max_length=255) description: Optional[str] = None contact_info: Optional[str] = None target_chat_id: Optional[int] = None target_chat_title: Optional[str] = None require_membership: Optional[bool] = None required_chat_ids: Optional[list[int]] = None required_chat_titles: Optional[list[str]] = None required_chat_types: Optional[list[str]] = None required_chat_usernames: Optional[list[str]] = None allow_multiple_wins: Optional[bool] = None invite_link_chat_ids: Optional[list[int]] = None required_chat_passphrases: Optional[list[str]] = None max_participants: Optional[int] = Field(None, ge=1) draw_at: Optional[datetime] = None auto_draw_count: Optional[int] = Field(None, ge=1) creator_timezone: Optional[str] = Field(None, max_length=64) @field_validator("draw_at", mode="after") @classmethod def normalize_draw_at(cls, v: datetime | None) -> datetime | None: return _to_naive_utc(v) class LotteryResponse(BaseModel): id: uuid.UUID creator_id: int title: str description: Optional[str] = None contact_info: Optional[str] = None status: str target_chat_id: Optional[int] = None target_chat_title: Optional[str] = None require_membership: bool required_chat_ids: list[int] = Field(default_factory=list) required_chat_titles: list[str] = Field(default_factory=list) required_chat_types: list[str] = Field(default_factory=list) required_chat_usernames: list[str] = Field(default_factory=list) announcement_targets: list[dict] = Field(default_factory=list) allow_multiple_wins: bool = False invite_link_chat_ids: list[int] = Field(default_factory=list) required_chat_passphrases: list[str] = Field(default_factory=list) max_participants: Optional[int] = None draw_at: Optional[datetime] = None auto_draw_count: Optional[int] = None creator_timezone: Optional[str] = None participant_count: int = 0 prize_count: int = 0 total_prizes: int = 0 created_at: datetime drawn_at: Optional[datetime] = None draw_trigger: Optional[str] = None prizes: list[PrizeResponse] = Field(default_factory=list) is_winner: Optional[bool] = None model_config = {"from_attributes": True} class ParticipantResponse(BaseModel): user_id: int username: Optional[str] = None first_name: str last_name: Optional[str] = None joined_at: datetime model_config = {"from_attributes": True} class WinnerResponse(BaseModel): user_id: int username: Optional[str] = None first_name: str last_name: Optional[str] = None prize_name: str drawn_at: datetime model_config = {"from_attributes": True} class ChatInfo(BaseModel): id: int title: str username: Optional[str] = None chat_type: str