"""SQLModel database models for caching PIM data.""" from datetime import datetime, timezone from typing import Optional from sqlmodel import SQLModel, Field def utc_now() -> datetime: """Return timezone-aware UTC datetime.""" return datetime.now(timezone.utc) class CacheMeta(SQLModel, table=True): """Generic key-value cache metadata.""" __tablename__ = "cache_meta" key: str = Field(primary_key=True) value: Optional[str] = None expires_at: Optional[int] = None class EmailCache(SQLModel, table=True): """Cached email data.""" __tablename__ = "email_cache" id: str = Field(primary_key=True) mailbox: str = Field(index=True) subject: Optional[str] = None from_address: Optional[str] = None date: Optional[datetime] = Field(default=None, index=True) is_read: bool = False is_flagged: bool = False snippet: Optional[str] = None full_data: Optional[str] = Field(default=None, description="JSON blob of full email data") cached_at: datetime = Field(default_factory=utc_now) class EventCache(SQLModel, table=True): """Cached calendar event data.""" __tablename__ = "event_cache" id: str = Field(primary_key=True) calendar_id: str = Field(index=True) title: Optional[str] = None start_time: Optional[datetime] = Field(default=None, index=True) end_time: Optional[datetime] = None full_data: Optional[str] = Field(default=None, description="JSON blob of full event data") cached_at: datetime = Field(default_factory=utc_now) class ContactCache(SQLModel, table=True): """Cached contact data.""" __tablename__ = "contact_cache" id: str = Field(primary_key=True) addressbook_id: str = Field(index=True) display_name: Optional[str] = Field(default=None, index=True) primary_email: Optional[str] = None full_data: Optional[str] = Field(default=None, description="JSON blob of full contact data") cached_at: datetime = Field(default_factory=utc_now) class SyncState(SQLModel, table=True): """Track sync state for incremental updates.""" __tablename__ = "sync_state" resource_type: str = Field(primary_key=True, description="Type: mailbox, calendar, addressbook") resource_id: str = Field(primary_key=True) last_sync: Optional[datetime] = None sync_token: Optional[str] = None class SeenEmail(SQLModel, table=True): """Track emails that have been processed for notifications.""" __tablename__ = "seen_emails" id: Optional[int] = Field(default=None, primary_key=True) email_uid: str = Field(index=True, description="IMAP UID of the email") mailbox: str = Field(index=True, description="Mailbox path (e.g., INBOX)") message_id: Optional[str] = Field( default=None, index=True, description="RFC 2822 Message-ID header for cross-server dedup" ) from_address: Optional[str] = Field(default=None, description="Sender email for logging") subject: Optional[str] = Field(default=None, description="Subject for logging") email_date: Optional[datetime] = Field(default=None, description="Email date") seen_at: datetime = Field(default_factory=utc_now) notification_sent: bool = Field(default=False) notification_sent_at: Optional[datetime] = None notification_error: Optional[str] = Field( default=None, description="Last error if notification failed" )