@startuml participation-참여자목록조회
!theme mono

title Participation Service - 참여자 목록 조회 내부 시퀀스

actor "사장님" as Owner
participant "API Gateway" as Gateway
participant "ParticipationController" as Controller
participant "ParticipationService" as Service
participant "ParticipantRepository" as Repo
database "Participation DB" as DB
database "Redis Cache<<E>>" as Cache

== UFR-PART-020: 참여자 목록 조회 ==

Owner -> Gateway: GET /api/v1/events/{eventId}/participants\n?entryPath={경로}&isWinner={당첨여부}\n&name={이름}&phone={전화번호}\n&page={페이지}&size={크기}
activate Gateway

Gateway -> Gateway: JWT 토큰 검증\n- 토큰 유효성 확인\n- 사장님 권한 확인

alt JWT 검증 실패
    Gateway --> Owner: 401 Unauthorized
    deactivate Gateway
else JWT 검증 성공

    Gateway -> Controller: GET /participants\n{eventId, filters, pagination}
    activate Controller

    Controller -> Controller: 요청 파라미터 유효성 검증\n- eventId 필수\n- page >= 0\n- size: 10~100

    alt 유효성 검증 실패
        Controller --> Gateway: 400 Bad Request
        Gateway --> Owner: 400 Bad Request
        deactivate Controller
        deactivate Gateway
    else 유효성 검증 성공

        Controller -> Service: getParticipantList(eventId, filters, pageable)
        activate Service

        Service -> Service: 캐시 키 생성\n- participant_list:{eventId}:{filters}:{page}

        Service -> Cache: GET participant_list:{key}
        activate Cache
        Cache --> Service: 캐시 조회 결과
        deactivate Cache

        alt 캐시 HIT
            Service --> Controller: ParticipantListResponse\n(캐시된 데이터)
            note right of Service
                캐시된 데이터 반환
                - TTL: 10분
                - 실시간 정확도 vs 성능 트레이드오프
            end note
            Controller --> Gateway: 200 OK\n{participants, totalElements, totalPages}
            Gateway --> Owner: 200 OK\n참여자 목록 표시
            deactivate Service
            deactivate Controller
            deactivate Gateway
        else 캐시 MISS: DB 조회

            Service -> Service: 동적 쿼리 생성\n- 참여 경로 필터\n- 당첨 여부 필터\n- 이름/전화번호 검색

            Service -> Repo: findParticipants(eventId, filters, pageable)
            activate Repo

            Repo -> DB: 참여자 목록 조회\n(이벤트ID, 참여경로, 당첨여부,\n이름/전화번호 검색조건으로 필터링하여\n참여일시 내림차순으로 페이징 조회)
            activate DB

            note right of DB
                동적 쿼리 조건:
                - entryPath 필터 (선택)
                - isWinner 필터 (선택)
                - name/phone 검색 (선택)
                - 페이지네이션 (필수)

                필요 인덱스:
                idx_participants_event_filters
                (event_id, entry_path, is_winner, participated_at DESC)
            end note

            DB --> Repo: 참여자 목록 결과셋
            deactivate DB

            Repo -> DB: 전체 참여자 수 조회\n(동일한 필터 조건 적용)
            activate DB
            DB --> Repo: 전체 건수
            deactivate DB

            Repo --> Service: Page<Participant>
            deactivate Repo

            Service -> Service: DTO 변환\n- 전화번호 마스킹 (010-****-1234)\n- 응모번호 형식화\n- 당첨 여부 라벨 변환

            Service -> Cache: SET participant_list:{key} = data\nTTL: 10분
            activate Cache
            note right of Cache
                캐시 저장:
                - TTL: 10분
                - 실시간 참여 반영과 성능 균형
                - 이벤트 참여 빈도 고려
            end note
            Cache --> Service: 캐시 저장 완료
            deactivate Cache

            Service --> Controller: ParticipantListResponse\n{participants[], totalElements, totalPages, currentPage}
            deactivate Service

            Controller --> Gateway: 200 OK\n{data, pagination}
            deactivate Controller

            Gateway --> Owner: 200 OK
            deactivate Gateway

            Owner -> Owner: 참여자 목록 화면 표시\n- 테이블 형태\n- 페이지네이션\n- 필터/검색 UI
        end
    end
end

@enduml
