from fastapi import APIRouter, Depends, status from sqlalchemy.ext.asyncio import AsyncSession from app.auth.service import get_current_user from app.chats.schemas import ( ChatCreateRequest, ChatDetailRead, ChatDiscoverRead, ChatDeleteRequest, ChatMemberAddRequest, ChatMemberRead, ChatMemberRoleUpdateRequest, ChatPinMessageRequest, ChatRead, ChatTitleUpdateRequest, ) from app.chats.service import ( add_chat_member_for_user, create_chat_for_user, clear_chat_for_user, delete_chat_for_user, discover_public_chats_for_user, ensure_saved_messages_chat, get_chat_for_user, get_chats_for_user, join_public_chat_for_user, leave_chat_for_user, pin_chat_message_for_user, remove_chat_member_for_user, serialize_chat_for_user, serialize_chats_for_user, update_chat_member_role_for_user, update_chat_title_for_user, ) from app.database.session import get_db from app.users.models import User router = APIRouter(prefix="/chats", tags=["chats"]) @router.get("", response_model=list[ChatRead]) async def list_chats( limit: int = 50, before_id: int | None = None, query: str | None = None, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> list[ChatRead]: chats = await get_chats_for_user(db, user_id=current_user.id, limit=limit, before_id=before_id, query=query) return await serialize_chats_for_user(db, user_id=current_user.id, chats=chats) @router.get("/saved", response_model=ChatRead) async def get_saved_messages_chat( db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> ChatRead: chat = await ensure_saved_messages_chat(db, user_id=current_user.id) return await serialize_chat_for_user(db, user_id=current_user.id, chat=chat) @router.get("/discover", response_model=list[ChatDiscoverRead]) async def discover_chats( query: str | None = None, limit: int = 30, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> list[ChatDiscoverRead]: return await discover_public_chats_for_user(db, user_id=current_user.id, query=query, limit=limit) @router.post("", response_model=ChatRead) async def create_chat( payload: ChatCreateRequest, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> ChatRead: chat = await create_chat_for_user(db, creator_id=current_user.id, payload=payload) return await serialize_chat_for_user(db, user_id=current_user.id, chat=chat) @router.post("/{chat_id}/join", response_model=ChatRead) async def join_chat( chat_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> ChatRead: chat = await join_public_chat_for_user(db, chat_id=chat_id, user_id=current_user.id) return await serialize_chat_for_user(db, user_id=current_user.id, chat=chat) @router.get("/{chat_id}", response_model=ChatDetailRead) async def get_chat( chat_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> ChatDetailRead: chat, members = await get_chat_for_user(db, chat_id=chat_id, user_id=current_user.id) return ChatDetailRead( id=chat.id, type=chat.type, title=chat.title, pinned_message_id=chat.pinned_message_id, created_at=chat.created_at, members=members, ) @router.patch("/{chat_id}/title", response_model=ChatRead) async def update_chat_title( chat_id: int, payload: ChatTitleUpdateRequest, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> ChatRead: chat = await update_chat_title_for_user(db, chat_id=chat_id, user_id=current_user.id, payload=payload) return await serialize_chat_for_user(db, user_id=current_user.id, chat=chat) @router.get("/{chat_id}/members", response_model=list[ChatMemberRead]) async def list_chat_members( chat_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> list[ChatMemberRead]: _chat, members = await get_chat_for_user(db, chat_id=chat_id, user_id=current_user.id) return members @router.post("/{chat_id}/members", response_model=ChatMemberRead, status_code=status.HTTP_201_CREATED) async def add_chat_member( chat_id: int, payload: ChatMemberAddRequest, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> ChatMemberRead: return await add_chat_member_for_user(db, chat_id=chat_id, actor_user_id=current_user.id, target_user_id=payload.user_id) @router.patch("/{chat_id}/members/{user_id}/role", response_model=ChatMemberRead) async def update_chat_member_role( chat_id: int, user_id: int, payload: ChatMemberRoleUpdateRequest, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> ChatMemberRead: return await update_chat_member_role_for_user( db, chat_id=chat_id, actor_user_id=current_user.id, target_user_id=user_id, role=payload.role, ) @router.delete("/{chat_id}/members/{user_id}", status_code=status.HTTP_204_NO_CONTENT) async def remove_chat_member( chat_id: int, user_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> None: await remove_chat_member_for_user(db, chat_id=chat_id, actor_user_id=current_user.id, target_user_id=user_id) @router.post("/{chat_id}/leave", status_code=status.HTTP_204_NO_CONTENT) async def leave_chat( chat_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> None: await leave_chat_for_user(db, chat_id=chat_id, user_id=current_user.id) @router.delete("/{chat_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_chat( chat_id: int, for_all: bool = False, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> None: await delete_chat_for_user(db, chat_id=chat_id, user_id=current_user.id, payload=ChatDeleteRequest(for_all=for_all)) @router.post("/{chat_id}/clear", status_code=status.HTTP_204_NO_CONTENT) async def clear_chat( chat_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> None: await clear_chat_for_user(db, chat_id=chat_id, user_id=current_user.id) @router.post("/{chat_id}/pin", response_model=ChatRead) async def pin_chat_message( chat_id: int, payload: ChatPinMessageRequest, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ) -> ChatRead: chat = await pin_chat_message_for_user(db, chat_id=chat_id, user_id=current_user.id, payload=payload) return await serialize_chat_for_user(db, user_id=current_user.id, chat=chat)