from typing import Optional, List from sqlmodel import Field, SQLModel, Relationship from datetime import datetime class User(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) email: str = Field(index=True, unique=True) password_hash: str full_name: Optional[str] = None created_at: datetime = Field(default_factory=datetime.utcnow) items: List["WardrobeItem"] = Relationship(back_populates="owner") outfits: List["Outfit"] = Relationship(back_populates="owner") measurements: Optional["UserMeasurements"] = Relationship(back_populates="user") clicks: List["AffiliateClick"] = Relationship(back_populates="user") class Brand(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) name: str = Field(unique=True, index=True) logo_url: Optional[str] = None password_hash: str = "mock_hash" # For B2B login products: List["AffiliateProduct"] = Relationship(back_populates="brand_rel") class AffiliateProduct(SQLModel, table=True): """Represents a product from a brand partner""" id: Optional[int] = Field(default=None, primary_key=True) name: str brand: str price: float commission_rate: float = 0.05 # 5% default original_url: str image_url: str category: str brand_id: Optional[int] = Field(default=None, foreign_key="brand.id") brand_rel: Optional[Brand] = Relationship(back_populates="products") clicks: List["AffiliateClick"] = Relationship(back_populates="product") class AffiliateClick(SQLModel, table=True): """Log of every click on an affiliate link""" id: Optional[int] = Field(default=None, primary_key=True) product_id: int = Field(foreign_key="affiliateproduct.id") user_id: Optional[int] = Field(default=None, foreign_key="user.id") timestamp: datetime = Field(default_factory=datetime.utcnow) converted: bool = False # Mock conversion status commission_earned: float = 0.0 product: Optional[AffiliateProduct] = Relationship(back_populates="clicks") user: Optional[User] = Relationship(back_populates="clicks") class UserMeasurements(SQLModel, table=True): """Store user body measurements for size recommendations""" id: Optional[int] = Field(default=None, primary_key=True) user_id: int = Field(foreign_key="user.id", unique=True) height_cm: Optional[float] = None weight_kg: Optional[float] = None chest_cm: Optional[float] = None waist_cm: Optional[float] = None hip_cm: Optional[float] = None preferred_fit: Optional[str] = "regular" # slim, regular, loose updated_at: datetime = Field(default_factory=datetime.utcnow) user: Optional[User] = Relationship(back_populates="measurements") class BrandSizeMapping(SQLModel, table=True): """Cross-brand size translation mappings""" id: Optional[int] = Field(default=None, primary_key=True) brand_name: str = Field(index=True) category: str # tops, bottoms, shoes, etc. size_label: str # S, M, L, 32, 34, etc. chest_min: Optional[float] = None chest_max: Optional[float] = None waist_min: Optional[float] = None waist_max: Optional[float] = None hip_min: Optional[float] = None hip_max: Optional[float] = None region: str = "US" # US, EU, UK, etc. class SizeRecommendation(SQLModel, table=True): """Store size recommendations for wardrobe items""" id: Optional[int] = Field(default=None, primary_key=True) user_id: int = Field(foreign_key="user.id") wardrobe_item_id: int = Field(foreign_key="wardrobeitem.id") brand_name: str recommended_size: str confidence_score: float # 0.0 to 1.0 alternative_sizes: Optional[str] = None # JSON array of alternatives reasoning: Optional[str] = None # Why this size was recommended created_at: datetime = Field(default_factory=datetime.utcnow) class WardrobeItem(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) owner_id: Optional[int] = Field(default=None, foreign_key="user.id") image_url: str category: str # e.g., 'top', 'bottom', 'shoes' tags: Optional[str] = None created_at: datetime = Field(default_factory=datetime.utcnow) owner: Optional[User] = Relationship(back_populates="items") class Outfit(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) owner_id: Optional[int] = Field(default=None, foreign_key="user.id") items_json: str # JSON string of item IDs created_at: datetime = Field(default_factory=datetime.utcnow) owner: Optional[User] = Relationship(back_populates="outfits")