File size: 4,959 Bytes
69f2337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a08f988
69f2337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a08f988
69f2337
 
 
 
 
 
 
 
 
 
a08f988
69f2337
 
 
 
 
a08f988
69f2337
 
 
 
a08f988
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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
        ],
    }