@startuml 고객참여플로우
!theme mono

title 고객 참여 플로우 - 외부 시퀀스 다이어그램

actor "고객" as Customer
participant "Frontend\n(고객용)" as CustomerFE
participant "API Gateway" as Gateway
participant "Participation\nService" as PartService
participant "Kafka\n(Event Topics)" as Kafka
database "Participation\nDB" as PartDB
participant "Analytics\nService" as Analytics

actor "사장님" as Owner
participant "Frontend\n(사장님용)" as OwnerFE

== UFR-PART-010: 이벤트 참여 ==

Customer -> CustomerFE: 이벤트 참여 화면 접근\n(우리동네TV/SNS/링고비즈)
activate CustomerFE

CustomerFE -> Customer: 참여 정보 입력 폼 표시\n(이름, 전화번호, 참여경로)

Customer -> CustomerFE: 참여 정보 입력 및\n참여 버튼 클릭
CustomerFE -> CustomerFE: 클라이언트 유효성 검증\n(이름 2자 이상, 전화번호 형식)

CustomerFE -> Gateway: POST /api/v1/participations\n{이름, 전화번호, 참여경로, 개인정보동의}
activate Gateway

Gateway -> PartService: POST /participations/register\n{이름, 전화번호, 참여경로, 개인정보동의}
activate PartService

PartService -> PartDB: 참여자 중복 확인\n(전화번호, 이벤트ID로 조회)
activate PartDB
PartDB --> PartService: 중복 참여 여부 반환
deactivate PartDB

alt 중복 참여인 경우
    PartService --> Gateway: 409 Conflict\n{message: "이미 참여하신 이벤트입니다"}
    Gateway --> CustomerFE: 409 Conflict
    CustomerFE -> Customer: 중복 참여 오류 메시지 표시
    deactivate PartService
    deactivate Gateway
    deactivate CustomerFE
else 신규 참여인 경우
    PartService -> PartService: 응모 번호 생성\n(UUID 또는 시퀀스 기반)

    PartService -> PartDB: 참여자 정보 저장\n(이름, 전화번호, 참여경로,\n응모번호, 참여일시)
    activate PartDB
    PartDB --> PartService: 저장 완료
    deactivate PartDB

    PartService -> Kafka: Publish Event\n"ParticipantRegistered"\n{participantId, eventId,\nentryPath, timestamp}
    activate Kafka
    note right of Kafka
        Topic: participant-events
        Event: ParticipantRegistered
        Data: {
            participantId: UUID,
            eventId: UUID,
            entryPath: string,
            timestamp: datetime
        }
    end note

    Kafka --> Analytics: Subscribe Event\n"ParticipantRegistered"
    activate Analytics
    Analytics -> Analytics: 참여자 데이터 집계\n- 채널별 참여자 수\n- 시간대별 참여 추이\n- 실시간 통계 업데이트
    deactivate Analytics
    deactivate Kafka

    PartService --> Gateway: 201 Created\n{응모번호, 당첨발표일, 참여완료메시지}
    deactivate PartService

    Gateway --> CustomerFE: 201 Created
    deactivate Gateway

    CustomerFE -> Customer: 참여 완료 화면 표시\n- 응모번호\n- 당첨 발표일\n- "참여해주셔서 감사합니다"
    deactivate CustomerFE
end

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

Owner -> OwnerFE: 이벤트 상세 화면에서\n"참여자 목록" 탭 클릭
activate OwnerFE

OwnerFE -> Gateway: GET /api/v1/events/{eventId}/participants\n?page=1&size=20
activate Gateway

Gateway -> PartService: GET /events/{eventId}/participants\n?page=1&size=20
activate PartService

PartService -> PartDB: 참여자 목록 조회\n(이벤트ID, 페이지네이션)\nORDER BY 참여일시 DESC
activate PartDB
PartDB --> PartService: 참여자 목록 반환\n(이름, 전화번호, 참여경로,\n응모번호, 참여일시)\n+ 총 참여자 수
deactivate PartDB

PartService --> Gateway: 200 OK\n{participants[], totalCount, page, size}
deactivate PartService

Gateway --> OwnerFE: 200 OK
deactivate Gateway

OwnerFE -> Owner: 참여자 목록 화면 표시\n- 참여자 정보 테이블\n- 페이지네이션\n- 총 참여자 수\n- CSV 다운로드 버튼
deactivate OwnerFE

note right of Owner
    참여자 정보:
    - 이름 (마스킹: 김**)
    - 전화번호 (마스킹: 010-****-1234)
    - 참여경로 (우리동네TV, Instagram 등)
    - 응모번호
    - 참여일시
end note

== UFR-PART-030: 당첨자 추첨 ==

Owner -> OwnerFE: 이벤트 상세 화면에서\n"당첨자 추첨" 버튼 클릭
activate OwnerFE

OwnerFE -> Owner: 추첨 확인 다이얼로그 표시\n"당첨자를 추첨하시겠습니까?"

Owner -> OwnerFE: 확인 버튼 클릭

OwnerFE -> Gateway: POST /api/v1/events/{eventId}/draw-winners\n{당첨인원, 매장방문가산점옵션}
activate Gateway

Gateway -> PartService: POST /events/{eventId}/draw-winners\n{winnerCount, visitBonus}
activate PartService

PartService -> PartDB: 미당첨 참여자 목록 조회\n(이벤트ID로 당첨되지 않은 참여자 조회)
activate PartDB
PartDB --> PartService: 전체 참여자 목록 반환
deactivate PartDB

PartService -> PartService: 당첨자 추첨 알고리즘 실행\n1. 난수 생성 (Crypto.randomBytes)\n2. 매장방문 가산점 적용 (옵션)\n3. Fisher-Yates Shuffle\n4. 당첨인원만큼 선정

PartService -> PartDB: 당첨자 정보 업데이트\n(당첨 여부를 true로 설정, 당첨 일시 기록)
activate PartDB
PartDB --> PartService: 업데이트 완료
deactivate PartDB

PartService -> PartDB: 추첨 로그 저장\n(이벤트ID, 추첨방법, 당첨인원,\n알고리즘, 추첨일시)
activate PartDB
note right of PartDB
    추첨 로그 저장:
    - 추첨 일시
    - 추첨 방법
    - 알고리즘 버전
    - 가산점 적용 여부
end note
PartDB --> PartService: 로그 저장 완료
deactivate PartDB

PartService --> Gateway: 200 OK\n{당첨자목록, 추첨로그ID}
deactivate PartService

Gateway --> OwnerFE: 200 OK
deactivate Gateway

OwnerFE -> Owner: 당첨자 목록 화면 표시\n- 당첨자 정보 (이름, 전화번호, 응모번호)\n- 추첨 완료 메시지
deactivate OwnerFE

@enduml
