"""Service layer for CoordMessage.""" from datetime import datetime, timezone from typing import Optional from uuid import UUID from fastapi import HTTPException, status from sqlalchemy.orm import Session from api.models.coord_message import CoordMessage from api.schemas.coord_message import CoordMessageCreate def get_messages( db: Session, to_session: Optional[str] = None, unread_only: bool = False, skip: int = 0, limit: int = 100, ) -> tuple[list[CoordMessage], int]: """Return paginated messages with optional filters.""" q = db.query(CoordMessage) if to_session: q = q.filter(CoordMessage.to_session == to_session) if unread_only: q = q.filter(CoordMessage.read_at.is_(None)) total = q.count() messages = q.order_by(CoordMessage.created_at.desc()).offset(skip).limit(limit).all() return messages, total def get_unread_count(db: Session, session_id: str) -> int: """Return the number of unread messages addressed to a session.""" return ( db.query(CoordMessage) .filter(CoordMessage.to_session == session_id, CoordMessage.read_at.is_(None)) .count() ) def get_message_by_id(db: Session, message_id: UUID) -> CoordMessage: """Return a single message or raise 404.""" msg = db.query(CoordMessage).filter(CoordMessage.id == str(message_id)).first() if not msg: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Message {message_id} not found" ) return msg def send_message(db: Session, data: CoordMessageCreate) -> CoordMessage: """Persist a new message.""" try: msg = CoordMessage(**data.model_dump()) db.add(msg) db.commit() db.refresh(msg) return msg except Exception as e: db.rollback() raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to send message: {e}" ) def mark_read(db: Session, message_id: UUID) -> CoordMessage: """Mark a message as read at the current time.""" msg = get_message_by_id(db, message_id) try: msg.read_at = datetime.now(timezone.utc).replace(tzinfo=None) db.commit() db.refresh(msg) return msg except Exception as e: db.rollback() raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to mark message read: {e}" ) def delete_message(db: Session, message_id: UUID) -> dict: """Delete a message by ID.""" msg = get_message_by_id(db, message_id) try: db.delete(msg) db.commit() return {"message": "Message deleted", "message_id": str(message_id)} except Exception as e: db.rollback() raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to delete message: {e}" )