"""Room management API endpoints.""" from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from sqlalchemy.orm import selectinload from src.db.postgres.connection import get_db from src.db.postgres.models import Room, ChatMessage from src.middlewares.logging import get_logger, log_execution from pydantic import BaseModel from typing import List from datetime import datetime import uuid logger = get_logger("room_api") router = APIRouter(prefix="/api/v1", tags=["Rooms"]) class ChatMessageResponse(BaseModel): id: str role: str content: str created_at: str class RoomResponse(BaseModel): id: str title: str created_at: str updated_at: str | None messages: List[ChatMessageResponse] = [] class CreateRoomRequest(BaseModel): user_id: str title: str = "New Chat" @router.get("/rooms/{user_id}", response_model=List[RoomResponse]) @log_execution(logger) async def list_rooms( user_id: str, db: AsyncSession = Depends(get_db) ): """List all rooms for a user.""" result = await db.execute( select(Room) .where(Room.user_id == user_id, Room.status == "active") .order_by(Room.updated_at.desc()) ) rooms = result.scalars().all() return [ RoomResponse( id=room.id, title=room.title, created_at=room.created_at.isoformat(), updated_at=room.updated_at.isoformat() if room.updated_at else None ) for room in rooms ] @router.get("/room/{room_id}", response_model=RoomResponse) @log_execution(logger) async def get_room( room_id: str, db: AsyncSession = Depends(get_db) ): """Get a specific room with its chat history.""" result = await db.execute( select(Room) .where(Room.id == room_id) .options(selectinload(Room.messages)) ) room = result.scalars().first() if not room: raise HTTPException( status_code=404, detail="Room not found" ) messages = sorted(room.messages, key=lambda m: m.created_at) return RoomResponse( id=room.id, title=room.title, created_at=room.created_at.isoformat(), updated_at=room.updated_at.isoformat() if room.updated_at else None, messages=[ ChatMessageResponse( id=msg.id, role=msg.role, content=msg.content, created_at=msg.created_at.isoformat() ) for msg in messages ] ) @router.delete("/room/{room_id}") @log_execution(logger) async def delete_room( room_id: str, user_id: str, db: AsyncSession = Depends(get_db) ): """Soft-delete a room by setting its status to inactive.""" result = await db.execute( select(Room).where(Room.id == room_id) ) room = result.scalars().first() if not room: raise HTTPException(status_code=404, detail="Room not found") if room.user_id != user_id: raise HTTPException(status_code=403, detail="Access denied") room.status = "inactive" await db.commit() return {"status": "success", "message": "Room deleted successfully"} @router.post("/room/create") @log_execution(logger) async def create_room( request: CreateRoomRequest, db: AsyncSession = Depends(get_db) ): """Create a new room.""" room = Room( id=str(uuid.uuid4()), user_id=request.user_id, title=request.title ) db.add(room) await db.commit() await db.refresh(room) return { "status": "success", "message": "Room created successfully", "data": RoomResponse( id=room.id, title=room.title, created_at=room.created_at.isoformat(), updated_at=None ) }