package com.kt.distribution.controller;

import com.kt.distribution.dto.DistributionRequest;
import com.kt.distribution.dto.DistributionResponse;
import com.kt.distribution.dto.DistributionStatusResponse;
import com.kt.distribution.service.DistributionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * Distribution Controller
 * POST /distribute - 다중 채널 배포 실행
 * GET /{eventId}/status - 배포 상태 조회
 *
 * @author System Architect
 * @since 2025-10-23
 */
@Slf4j
@RestController
@RequestMapping
@RequiredArgsConstructor
@Tag(name = "Distribution", description = "다중 채널 배포 관리 API")
public class DistributionController {

    private final DistributionService distributionService;

    /**
     * 다중 채널 배포 실행
     * UFR-DIST-010: 다중채널배포
     *
     * @param request DistributionRequest
     * @return DistributionResponse
     */
    @Operation(
            summary = "다중 채널 배포 요청",
            description = """
                    이벤트 콘텐츠를 선택된 채널들에 동시 배포합니다.

                    ## 처리 흐름
                    1. 배포 요청 검증 (이벤트 ID, 채널 목록, 콘텐츠 데이터)
                    2. 채널별 병렬 배포 실행 (1분 이내 완료 목표)
                    3. Circuit Breaker로 장애 채널 격리
                    4. 실패 시 Retry (지수 백오프: 1s, 2s, 4s)
                    5. Fallback: 실패 채널 스킵 및 알림
                    """
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "배포 완료",
                    content = @Content(schema = @Schema(implementation = DistributionResponse.class))
            ),
            @ApiResponse(responseCode = "400", description = "잘못된 요청"),
            @ApiResponse(responseCode = "404", description = "이벤트를 찾을 수 없음"),
            @ApiResponse(responseCode = "500", description = "서버 내부 오류")
    })
    @PostMapping("/distribute")
    public ResponseEntity<DistributionResponse> distribute(@RequestBody DistributionRequest request) {
        log.info("Received distribution request: eventId={}, channels={}",
                request.getEventId(), request.getChannels());

        DistributionResponse response = distributionService.distribute(request);

        log.info("Distribution request processed: eventId={}, success={}, successCount={}, failureCount={}",
                response.getEventId(), response.isSuccess(),
                response.getSuccessCount(), response.getFailureCount());

        return ResponseEntity.ok(response);
    }

    /**
     * 배포 상태 조회
     * UFR-DIST-020: 배포상태조회
     *
     * @param eventId 이벤트 ID
     * @return DistributionStatusResponse
     */
    @Operation(
            summary = "배포 상태 조회",
            description = """
                    특정 이벤트의 배포 상태를 실시간으로 조회합니다.

                    ## 조회 정보
                    - 전체 배포 상태 (진행중, 완료, 부분성공, 실패)
                    - 채널별 배포 상태 및 결과
                    - 실패 채널 상세 정보 (오류 유형, 재시도 횟수)
                    """
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "배포 상태 조회 성공",
                    content = @Content(schema = @Schema(implementation = DistributionStatusResponse.class))
            ),
            @ApiResponse(responseCode = "404", description = "배포 이력을 찾을 수 없음"),
            @ApiResponse(responseCode = "500", description = "서버 내부 오류")
    })
    @GetMapping("/{eventId}/status")
    public ResponseEntity<DistributionStatusResponse> getDistributionStatus(
            @Parameter(description = "이벤트 ID", required = true, example = "evt-12345")
            @PathVariable String eventId) {
        log.info("Received distribution status request: eventId={}", eventId);

        DistributionStatusResponse response = distributionService.getDistributionStatus(eventId);

        log.info("Distribution status retrieved: eventId={}, overallStatus={}",
                eventId, response.getOverallStatus());

        if ("NOT_FOUND".equals(response.getOverallStatus())) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok(response);
    }
}
