import re from pydantic import BaseModel, ConfigDict, Field, field_validator from datetime import datetime from typing import Optional, Literal _EMAIL_RE = re.compile(r'^[^@\s]+@[^@\s]+\.[^@\s]+$') class LocationSearchResult(BaseModel): source: Literal["local", "nominatim"] location_id: Optional[int] = None name: str address: str class LocationCreate(BaseModel): model_config = ConfigDict(extra="forbid") name: str = Field(min_length=1, max_length=255) address: str = Field(min_length=1, max_length=2000) category: str = Field("other", max_length=100) notes: Optional[str] = Field(None, max_length=5000) is_frequent: bool = False contact_number: Optional[str] = Field(None, max_length=50) email: Optional[str] = Field(None, max_length=255) @field_validator('email') @classmethod def validate_email(cls, v: str | None) -> str | None: if v and not _EMAIL_RE.match(v): raise ValueError('Invalid email address') return v class LocationUpdate(BaseModel): model_config = ConfigDict(extra="forbid") name: Optional[str] = Field(None, min_length=1, max_length=255) address: Optional[str] = Field(None, min_length=1, max_length=2000) category: Optional[str] = Field(None, max_length=100) notes: Optional[str] = Field(None, max_length=5000) is_frequent: Optional[bool] = None contact_number: Optional[str] = Field(None, max_length=50) email: Optional[str] = Field(None, max_length=255) @field_validator('email') @classmethod def validate_email(cls, v: str | None) -> str | None: if v and not _EMAIL_RE.match(v): raise ValueError('Invalid email address') return v class LocationResponse(BaseModel): id: int name: str address: str category: str notes: Optional[str] is_frequent: bool contact_number: Optional[str] email: Optional[str] created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True)