from fastapi import HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.chats import repository from app.chats.models import Chat, ChatMemberRole, ChatType from app.chats.schemas import ChatCreateRequest from app.users.repository import get_user_by_id async def create_chat_for_user(db: AsyncSession, *, creator_id: int, payload: ChatCreateRequest) -> Chat: member_ids = list(dict.fromkeys(payload.member_ids)) member_ids = [member_id for member_id in member_ids if member_id != creator_id] if payload.type == ChatType.PRIVATE and len(member_ids) != 1: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Private chat requires exactly one target user.", ) if payload.type in {ChatType.GROUP, ChatType.CHANNEL} and not payload.title: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Group and channel chats require title.", ) for member_id in member_ids: user = await get_user_by_id(db, member_id) if not user: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"User {member_id} not found") chat = await repository.create_chat(db, chat_type=payload.type, title=payload.title) await repository.add_chat_member(db, chat_id=chat.id, user_id=creator_id, role=ChatMemberRole.OWNER) default_role = ChatMemberRole.MEMBER for member_id in member_ids: await repository.add_chat_member(db, chat_id=chat.id, user_id=member_id, role=default_role) await db.commit() return chat async def get_chats_for_user(db: AsyncSession, *, user_id: int, limit: int = 50, before_id: int | None = None) -> list[Chat]: safe_limit = max(1, min(limit, 100)) return await repository.list_user_chats(db, user_id=user_id, limit=safe_limit, before_id=before_id) async def get_chat_for_user(db: AsyncSession, *, chat_id: int, user_id: int) -> tuple[Chat, list]: chat = await repository.get_chat_by_id(db, chat_id) if not chat: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Chat not found") membership = await repository.get_chat_member(db, chat_id=chat_id, user_id=user_id) if not membership: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="You are not a member of this chat") members = await repository.list_chat_members(db, chat_id=chat_id) return chat, members async def ensure_chat_membership(db: AsyncSession, *, chat_id: int, user_id: int) -> None: membership = await repository.get_chat_member(db, chat_id=chat_id, user_id=user_id) if not membership: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="You are not a member of this chat")