from datetime import datetime from typing import Optional, Any, Dict from uuid import UUID from pydantic import BaseModel, EmailStr, ConfigDict from app.models.guest import GuestStatus from app.schemas.rsvp import RSVPSchema, RSVPStatus class GuestBase(BaseModel): event_id: UUID invited_by: UUID user_id: Optional[UUID] = None full_name: str email: Optional[EmailStr] = None phone: Optional[str] = None max_additional_guests: Optional[int] = 10 dietary_restrictions: Optional[str] = None notes: Optional[str] = None custom_fields: Optional[Dict[str, Any]] = None can_bring_guests: Optional[bool] = True class GuestCreate(GuestBase): invitation_code: Optional[str] = None class GuestUpdate(BaseModel): full_name: Optional[str] = None email: Optional[EmailStr] = None phone: Optional[str] = None status: Optional[GuestStatus] = None max_additional_guests: Optional[int] = None actual_additional_guests: Optional[int] = None dietary_restrictions: Optional[str] = None notes: Optional[str] = None custom_fields: Optional[Dict[str, Any]] = None is_blocked: Optional[bool] = None can_bring_guests: Optional[bool] = None class GuestRead(GuestBase): id: UUID status: GuestStatus invitation_sent_at: Optional[datetime] = None response_date: Optional[datetime] = None actual_additional_guests: int is_blocked: bool model_config = ConfigDict(from_attributes=True) invitation_code: str rsvp: Optional[RSVPSchema] = None class GuestWithRSVPResponse(BaseModel): """ Combined response model that includes both guest and RSVP information. This gives the frontend a complete picture of the guest's response in a single object. """ guest: GuestRead rsvp: Optional[RSVPSchema] = None class Config: from_attributes = True def map_rsvp_status_to_guest_status(rsvp_status: RSVPStatus) -> GuestStatus: if rsvp_status == RSVPStatus.ATTENDING: return GuestStatus.CONFIRMED elif rsvp_status == RSVPStatus.NOT_ATTENDING: return GuestStatus.DECLINED elif rsvp_status == RSVPStatus.MAYBE: return GuestStatus.PENDING else: return GuestStatus.INVITED