from __future__ import annotations from datetime import datetime from sqlalchemy.orm import Session from db.models import Contact, Conversation, Message def get_all(db: Session, channel: str | None = None, archived: bool = False) -> list[Conversation]: q = db.query(Conversation).filter(Conversation.is_archived == archived) if channel: q = q.filter(Conversation.channel == channel) return q.order_by(Conversation.last_message_at.desc().nullslast()).all() def get_by_id(db: Session, conv_id: str) -> Conversation | None: return db.query(Conversation).filter(Conversation.id == conv_id).first() def get_by_channel_id(db: Session, channel: str, channel_conversation_id: str) -> Conversation | None: return ( db.query(Conversation) .filter( Conversation.channel == channel, Conversation.channel_conversation_id == channel_conversation_id, ) .first() ) def get_or_create( db: Session, channel: str, channel_conversation_id: str, contact: Contact, title: str | None = None, ) -> Conversation: conv = get_by_channel_id(db, channel, channel_conversation_id) if not conv: conv = Conversation( channel=channel, channel_conversation_id=channel_conversation_id, title=title or contact.name, ) conv.participants.append(contact) db.add(conv) db.commit() db.refresh(conv) return conv def get_messages( db: Session, conv_id: str, limit: int = 50, offset: int = 0 ) -> list[Message]: return ( db.query(Message) .filter(Message.conversation_id == conv_id) .order_by(Message.created_at.asc()) .offset(offset) .limit(limit) .all() ) def unread_count(db: Session, conv_id: str) -> int: return ( db.query(Message) .filter( Message.conversation_id == conv_id, Message.direction == "inbound", Message.read_at.is_(None), ) .count() ) def mark_all_read(db: Session, conv_id: str) -> None: now = datetime.utcnow() db.query(Message).filter( Message.conversation_id == conv_id, Message.direction == "inbound", Message.read_at.is_(None), ).update({"read_at": now, "status": "read"}) db.commit()