"""Domain models for the application.""" import enum from datetime import datetime from typing import Optional from uuid import uuid4 from sqlalchemy import BigInteger, Boolean, DateTime, Enum, Float, Integer, String, Text, func from sqlalchemy.orm import Mapped, mapped_column from app.infra.database import Base def generate_uuid() -> str: """Generate UUID as string for SQLite compatibility.""" return str(uuid4()) class AssetType(str, enum.Enum): """Type of media asset.""" PHOTO = "photo" VIDEO = "video" class AssetStatus(str, enum.Enum): """Status of media asset.""" UPLOADING = "uploading" READY = "ready" FAILED = "failed" class User(Base): """User account.""" __tablename__ = "users" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=generate_uuid) email: Mapped[str] = mapped_column(String(255), unique=True, nullable=False, index=True) password_hash: Mapped[str] = mapped_column(String(255), nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False ) class Folder(Base): """Folder for organizing assets.""" __tablename__ = "folders" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=generate_uuid) user_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) name: Mapped[str] = mapped_column(String(255), nullable=False) parent_folder_id: Mapped[Optional[str]] = mapped_column( String(36), nullable=True, index=True ) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False ) class Asset(Base): """Media asset (photo or video).""" __tablename__ = "assets" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=generate_uuid) user_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) folder_id: Mapped[Optional[str]] = mapped_column(String(36), nullable=True, index=True) type: Mapped[AssetType] = mapped_column(Enum(AssetType), nullable=False) status: Mapped[AssetStatus] = mapped_column( Enum(AssetStatus), default=AssetStatus.UPLOADING, nullable=False, index=True ) original_filename: Mapped[str] = mapped_column(String(512), nullable=False) content_type: Mapped[str] = mapped_column(String(100), nullable=False) size_bytes: Mapped[int] = mapped_column(BigInteger, nullable=False) sha256: Mapped[Optional[str]] = mapped_column(String(64), nullable=True) # Metadata captured_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) width: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) height: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) duration_sec: Mapped[Optional[float]] = mapped_column(Float, nullable=True) # Storage storage_key_original: Mapped[str] = mapped_column(String(512), nullable=False) storage_key_thumb: Mapped[Optional[str]] = mapped_column(String(512), nullable=True) # Timestamps created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False, index=True ) class Share(Base): """Public share link for assets or albums.""" __tablename__ = "shares" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=generate_uuid) owner_user_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True) asset_id: Mapped[Optional[str]] = mapped_column(String(36), nullable=True, index=True) album_id: Mapped[Optional[str]] = mapped_column(String(36), nullable=True, index=True) token: Mapped[str] = mapped_column(String(64), unique=True, nullable=False, index=True) expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) password_hash: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False ) revoked_at: Mapped[Optional[datetime]] = mapped_column( DateTime(timezone=True), nullable=True, index=True )