from __future__ import annotations import uuid from datetime import datetime from typing import Any from sqlalchemy import JSON, DateTime, Float, ForeignKey, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.db.base import Base, TimestampMixin, UUIDPrimaryKeyMixin class SourceDocument(Base, UUIDPrimaryKeyMixin, TimestampMixin): """A single piece of collected content. Kept lean on purpose - raw HTML is not stored, only extracted text - per the "avoid saving unnecessary full HTML indefinitely" rule in the spec.""" __tablename__ = "source_documents" source_id: Mapped[uuid.UUID] = mapped_column( ForeignKey("sources.id", ondelete="CASCADE"), index=True ) company_id: Mapped[uuid.UUID] = mapped_column( ForeignKey("companies.id", ondelete="CASCADE"), index=True ) url: Mapped[str] = mapped_column(String(1000)) canonical_url: Mapped[str] = mapped_column(String(1000), index=True) title: Mapped[str | None] = mapped_column(String(500), nullable=True) author: Mapped[str | None] = mapped_column(String(200), nullable=True) publication_date: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) retrieved_date: Mapped[datetime] = mapped_column(DateTime(timezone=True)) content_text: Mapped[str] = mapped_column(Text) content_hash: Mapped[str] = mapped_column(String(64), index=True) metadata_json: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict) language: Mapped[str | None] = mapped_column(String(16), nullable=True) http_status: Mapped[int | None] = mapped_column(Integer, nullable=True) extraction_method: Mapped[str] = mapped_column(String(50)) trust_score: Mapped[float] = mapped_column(Float, default=0.7)