@startuml meeting-Todo완료처리
!theme mono

title Meeting Service - Todo완료처리 내부 시퀀스

participant "TodoController" as Controller
participant "TodoService" as Service
participant "TodoRepository" as TodoRepo
participant "MinutesRepository" as MinutesRepo
participant "CollaborationService" as CollabService
database "Meeting DB<<E>>" as DB
database "Redis Cache<<E>>" as Cache
queue "Azure Event Hubs<<E>>" as EventHub
participant "WebSocket<<E>>" as WebSocket

[-> Controller: PATCH /todos/{todoId}/complete
activate Controller

note over Controller
경로 변수: todoId
사용자 정보: userId, userName, email
end note

Controller -> Controller: todoId 유효성 검증

Controller -> Service: completeTodo(todoId, userId)
activate Service

' Todo 정보 조회
Service -> TodoRepo: findById(todoId)
activate TodoRepo
TodoRepo -> DB: Todo 정보 조회
activate DB
DB --> TodoRepo: Todo 정보
deactivate DB
TodoRepo --> Service: Todo
deactivate TodoRepo

note over Service
비즈니스 규칙 검증:
- Todo 존재 확인
- 완료 권한 확인 (담당자만)
- 상태 확인 (이미 완료된 경우 처리)
end note

Service -> Service: Todo 존재 확인

Service -> Service: 완료 권한 검증\n(담당자만 가능)

alt 권한 없음
    Service --> Controller: 403 Forbidden\n담당자만 완료 가능
    note right
      에러 응답 형식:
      {
        "error": {
          "code": "INSUFFICIENT_PERMISSION",
          "message": "Todo 완료 권한이 없습니다",
          "details": "담당자만 Todo를 완료할 수 있습니다",
          "timestamp": "2025-10-23T12:00:00Z",
          "path": "/api/todos/{todoId}/complete"
        }
      }
    end note
    return 403 Forbidden
else 권한 있음
    alt Todo가 이미 완료됨
        Service --> Controller: 409 Conflict\n이미 완료된 Todo
        note right
          에러 응답 형식:
          {
            "error": {
              "code": "TODO_ALREADY_COMPLETED",
              "message": "이미 완료된 Todo입니다",
              "details": "해당 Todo는 이미 완료 처리되었습니다",
              "timestamp": "2025-10-23T12:00:00Z",
              "path": "/api/todos/{todoId}/complete"
            }
          }
        end note
        return 409 Conflict
    else 완료 처리 가능
        ' 완료 확인 다이얼로그 (프론트엔드에서 처리됨)

        ' Todo 완료 처리
        Service -> TodoRepo: markAsCompleted(todoId, userId)
        activate TodoRepo
        TodoRepo -> DB: Todo 완료 상태 업데이트
        activate DB
        DB --> TodoRepo: 업데이트 완료
        deactivate DB
        TodoRepo --> Service: 업데이트 성공
        deactivate TodoRepo

        note over Service
        회의록 실시간 반영:
        - 관련 회의록 섹션 자동 업데이트
        - 완료 표시 추가
        - 완료 시간 및 완료자 정보 기록
        end note

        ' 회의록 섹션 업데이트
        Service -> MinutesRepo: updateTodoStatus(todoId, "COMPLETED")
        activate MinutesRepo
        MinutesRepo -> DB: 회의록 섹션의 Todo 상태 업데이트
        activate DB
        DB --> MinutesRepo: 업데이트 완료
        deactivate DB
        MinutesRepo --> Service: 업데이트 성공
        deactivate MinutesRepo

        ' 회의록의 모든 Todo 완료 여부 확인
        Service -> TodoRepo: countPendingTodos(minutesId)
        activate TodoRepo
        TodoRepo -> DB: 미완료 Todo 개수 조회
        activate DB
        DB --> TodoRepo: 미완료 Todo 개수
        deactivate DB
        TodoRepo --> Service: int pendingCount
        deactivate TodoRepo

        ' 캐시 무효화
        Service -> Cache: DELETE dashboard:{assigneeId}
        activate Cache
        Cache --> Service: 삭제 완료
        deactivate Cache

        Service -> Cache: DELETE minutes:detail:{minutesId}
        activate Cache
        Cache --> Service: 삭제 완료
        deactivate Cache

        note over Service
        실시간 협업:
        - WebSocket으로 회의록 업데이트 전송
        - 모든 참석자에게 완료 상태 동기화
        end note

        ' 실시간 동기화
        Service -> CollabService: broadcastTodoUpdate(minutesId, todoId, status)
        activate CollabService

        note over CollabService
        WebSocket 메시지 형식:
        {
          "type": "TODO_COMPLETED",
          "todoId": "uuid",
          "minutesId": "uuid",
          "completedBy": {
            "userId": "...",
            "userName": "..."
          },
          "completedAt": "...",
          "timestamp": "..."
        }
        end note

        CollabService -> WebSocket: broadcast to room:{minutesId}
        activate WebSocket
        WebSocket --> CollabService: 전송 완료
        deactivate WebSocket
        CollabService --> Service: 동기화 완료
        deactivate CollabService

        note over Service
        비동기 이벤트 발행:
        - 완료 알림 발송
        - 모든 Todo 완료 시 전체 완료 알림
        end note

        alt 모든 Todo 완료됨
            Service -> EventHub: publish(AllTodosCompleted)\n{\n  minutesId, meetingId,\n  completedAt, totalTodos\n}
            activate EventHub
            EventHub --> Service: 발행 완료
            deactivate EventHub
        else 일부 Todo만 완료
            Service -> EventHub: publish(TodoCompleted)\n{\n  todoId, minutesId,\n  completedBy, completedAt\n}
            activate EventHub
            EventHub --> Service: 발행 완료
            deactivate EventHub
        end

        Service --> Controller: TodoCompleteResponse
        deactivate Service

        note over Controller
        응답 데이터:
        {
          "todoId": "uuid",
          "status": "COMPLETED",
          "completedAt": "2025-01-24T10:00:00",
          "completedBy": "userId",
          "minutesId": "uuid",
          "allTodosCompleted": true/false
        }
        end note

        return 200 OK\nTodoCompleteResponse
    end
end

deactivate Controller

@enduml
