import uuid from sqlalchemy import Column, String, Boolean, DateTime, ForeignKey, Text, Integer, Float, JSON from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from sqlalchemy.sql import func from app.core.database import Base class User(Base): __tablename__ = "users" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) username = Column(String(50), unique=True, nullable=False) email = Column(String(255), unique=True, nullable=False, index=True) full_name = Column(String(100), nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) is_active = Column(Boolean, default=True) sessions = relationship("ChatSession", back_populates="user", cascade="all, delete-orphan") class ChatSession(Base): __tablename__ = "chat_sessions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) title = Column(String(255), nullable=True) rag_config = Column(JSON, default={}) summary = Column(Text, nullable=True) last_message_at = Column(DateTime(timezone=True), server_default=func.now(), index=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) user = relationship("User", back_populates="sessions") messages = relationship("ChatMessage", back_populates="session", cascade="all, delete-orphan") class ChatMessage(Base): __tablename__ = "chat_messages" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) session_id = Column(UUID(as_uuid=True), ForeignKey("chat_sessions.id", ondelete="CASCADE"), nullable=False) role = Column(String(20), nullable=False) # user, assistant, system content = Column(Text, nullable=False) token_count = Column(Integer, nullable=True) processing_time = Column(Float, nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) session = relationship("ChatSession", back_populates="messages") citations = relationship("MessageCitation", back_populates="message", cascade="all, delete-orphan") class MessageCitation(Base): __tablename__ = "message_citations" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) message_id = Column(UUID(as_uuid=True), ForeignKey("chat_messages.id", ondelete="CASCADE"), nullable=False) source_doc_id = Column(String(255), nullable=False, index=True) file_path = Column(Text, nullable=False) chunk_content = Column(Text, nullable=True) relevance_score = Column(Float, nullable=True) message = relationship("ChatMessage", back_populates="citations")