from typing import List from uuid import UUID from fastapi import APIRouter from app.api.messages.schemas import Message from app.api.messages.services import MessageService from app.api.participants.schemas import Participant from app.api.participants.services import ParticipantService from app.api.topics.schemas import ( AddMessageRequest, Topic, TopicCreate, TopicMessageResponse, TopicResponse, ) from app.api.topics.services import TopicService from app.core.config import ( HTTP_STATUS_CREATED, MESSAGES_FILE, PARTICIPANTS_FILE, TOPICS_FILE, UNKNOWN_PARTICIPANT_NAME, ) from app.core.file_manager import FileManager from app.core.link import Link, TopicLink router = APIRouter() message_service = MessageService(FileManager(MESSAGES_FILE), FileManager(TOPICS_FILE), FileManager(PARTICIPANTS_FILE)) topic_service = TopicService(FileManager(TOPICS_FILE), message_service=message_service) participant_service = ParticipantService(FileManager(PARTICIPANTS_FILE)) def _resolve_participant_name(participant_id: Link, participants: List[Participant]) -> str: for participant in participants: if participant.id == participant_id.value: return f"{participant.first_name} {participant.last_name}".strip() return UNKNOWN_PARTICIPANT_NAME def _topic_to_response(topic: Topic, participants: List[Participant], messages: List[Message]) -> TopicResponse: message_responses = [] for message in sorted(messages, key=lambda item: item.order_in_topic): message_responses.append( TopicMessageResponse( participant_id=message.participant_id, content=message.content, participant_name=_resolve_participant_name(message.participant_id, participants), order_in_topic=message.order_in_topic, ) ) return TopicResponse( id=topic.id, title=topic.title, description=topic.description, created_at=topic.created_at, participants=topic.participants, messages=message_responses, ) @router.get("/", response_model=List[TopicResponse]) async def list_topics() -> List[TopicResponse]: topics = topic_service.list_topics() participants = participant_service.list_participants() messages = message_service.list_messages() messages_by_topic: dict[UUID, List[Message]] = {} for message in messages: messages_by_topic.setdefault(message.topic_id.value, []).append(message) return [ _topic_to_response(topic, participants, messages_by_topic.get(topic.id, [])) for topic in topics ] @router.get("/{topic_id}", response_model=TopicResponse) async def get_topic(topic_id: UUID) -> TopicResponse: topic_link = TopicLink(value=topic_id) topic = topic_service.get_topic(topic_link) participants = participant_service.list_participants() topic_messages = message_service.list_messages_by_topic(topic_link) return _topic_to_response(topic, participants, topic_messages) @router.post("/", response_model=TopicResponse, status_code=HTTP_STATUS_CREATED) async def create_topic(payload: TopicCreate) -> TopicResponse: topic = topic_service.create_topic(payload) participants = participant_service.list_participants() topic_messages = message_service.list_messages_by_topic(TopicLink(value=topic.id)) return _topic_to_response(topic, participants, topic_messages) @router.post("/{topic_id}/messages", response_model=TopicResponse, status_code=HTTP_STATUS_CREATED) async def add_message(topic_id: UUID, payload: AddMessageRequest) -> TopicResponse: topic_link = TopicLink(value=topic_id) topic = topic_service.add_message(topic_link, payload) participants = participant_service.list_participants() topic_messages = message_service.list_messages_by_topic(topic_link) return _topic_to_response(topic, participants, topic_messages) @router.get("/{topic_id}/download") async def download_topic(topic_id: UUID) -> dict: topic_link = TopicLink(value=topic_id) topic = topic_service.get_topic(topic_link) participants = participant_service.list_participants() topic_messages = message_service.list_messages_by_topic(topic_link) response = _topic_to_response(topic, participants, topic_messages) return { "id": str(response.id), "title": response.title, "description": response.description, "created_at": response.created_at.isoformat(), "participants": [{"table": p.table, "value": str(p.value)} for p in response.participants], "messages": [ { "participant_id": {"table": m.participant_id.table, "value": str(m.participant_id.value)}, "content": m.content, "participant_name": m.participant_name, "order_in_topic": m.order_in_topic, } for m in response.messages ], }