from datetime import datetime from typing import Literal, Optional from uuid import UUID from pydantic import BaseModel, EmailStr, Field, model_validator class InviteCodeCreate(BaseModel): """Schema for creating a new invite code.""" expires_at: Optional[datetime] = Field(None, description="Optional expiration time") note: Optional[str] = Field(None, max_length=255, description="Note about who this code is for") email: Optional[EmailStr] = Field(None, description="Recipient email for invite delivery") assigned_plan: Literal["free", "pro", "starter", "enterprise"] = Field("free", description="Plan to assign on registration") trial_duration_days: Optional[int] = Field(None, ge=1, le=90, description="Trial duration in days (1-90)") @model_validator(mode="after") def free_plan_no_trial(self): if self.assigned_plan == "free" and self.trial_duration_days is not None: raise ValueError("Free plan cannot have a trial duration") return self class InviteCodeResponse(BaseModel): """Schema for invite code response.""" id: UUID code: str created_by_id: UUID used_by_id: Optional[UUID] = None expires_at: Optional[datetime] = None note: Optional[str] = None created_at: datetime used_at: Optional[datetime] = None is_used: bool is_expired: bool is_valid: bool email: Optional[str] = None assigned_plan: str = "free" trial_duration_days: Optional[int] = None email_sent_at: Optional[datetime] = None has_trial: bool = False email_sent: bool = False class Config: from_attributes = True class InviteCodeValidation(BaseModel): """Schema for invite code validation response.""" valid: bool message: str