package com.unicorn.hgzero.meeting.infra.event.consumer;

import com.azure.messaging.eventhubs.*;
import com.azure.messaging.eventhubs.checkpointstore.blob.BlobCheckpointStore;
import com.azure.messaging.eventhubs.models.EventContext;
import com.azure.storage.blob.BlobContainerAsyncClient;
import com.azure.storage.blob.BlobContainerClientBuilder;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.unicorn.hgzero.meeting.biz.dto.AiAnalysisDTO;
import com.unicorn.hgzero.meeting.infra.cache.CacheService;
import com.unicorn.hgzero.meeting.infra.event.dto.MinutesAnalysisCompletedEvent;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 회의록 AI 분석 완료 이벤트 소비자
 * Azure EventHub 사용
 */
@Component
@RequiredArgsConstructor
@Slf4j
@ConditionalOnProperty(name = "eventhub.enabled", havingValue = "true", matchIfMissing = false)
public class MinutesAnalysisEventConsumer {

    private final ObjectMapper objectMapper;
    private final CacheService cacheService;
    private EventProcessorClient processorClient;

    @Value("${eventhub.connection-string}")
    private String connectionString;

    @Value("${eventhub.name}")
    private String eventHubName;

    @Value("${eventhub.consumer-group:$Default}")
    private String consumerGroup;

    @Value("${azure.storage.connection-string:}")
    private String storageConnectionString;

    @Value("${azure.storage.container-name:checkpoint}")
    private String checkpointContainerName;

    @PostConstruct
    public void initialize() {
        try {
            log.info("AI 분석 이벤트 소비자 초기화 시작 - eventHub: {}, consumerGroup: {}", 
                    eventHubName, consumerGroup);

            // Checkpoint Store 설정 (선택사항)
            BlobCheckpointStore checkpointStore = null;
            if (!storageConnectionString.isEmpty()) {
                BlobContainerAsyncClient containerClient = new BlobContainerClientBuilder()
                        .connectionString(storageConnectionString)
                        .containerName(checkpointContainerName)
                        .buildAsyncClient();
                checkpointStore = new BlobCheckpointStore(containerClient);
            }

            // EventProcessor 클라이언트 생성
            EventProcessorClientBuilder builder = new EventProcessorClientBuilder()
                    .connectionString(connectionString, eventHubName)
                    .consumerGroup(consumerGroup)
                    .processEvent(this::processAnalysisCompletedEvent)
                    .processError(this::processError);

            if (checkpointStore != null) {
                builder.checkpointStore(checkpointStore);
            }

            processorClient = builder.buildEventProcessorClient();
            processorClient.start();
            
            log.info("AI 분석 이벤트 소비자 시작 완료");

        } catch (Exception e) {
            log.error("AI 분석 이벤트 소비자 초기화 실패", e);
        }
    }

    /**
     * AI 분석 완료 이벤트 처리
     */
    private void processAnalysisCompletedEvent(EventContext context) {
        EventData eventData = context.getEventData();
        
        try {
            String messageBody = eventData.getBodyAsString();
            log.debug("AI 분석 완료 이벤트 수신 - sequenceNumber: {}", eventData.getSequenceNumber());

            // 메시지를 이벤트 객체로 변환
            MinutesAnalysisCompletedEvent event = objectMapper.readValue(messageBody, MinutesAnalysisCompletedEvent.class);

            // 이벤트 타입 확인
            if (!"MINUTES_ANALYSIS_COMPLETED".equals(event.getEventType())) {
                log.debug("처리 대상이 아닌 이벤트 타입 - eventType: {}", event.getEventType());
                context.updateCheckpoint();
                return;
            }

            // 분석 완료 이벤트 처리
            handleAnalysisCompleted(event);

            // 체크포인트 업데이트
            context.updateCheckpoint();
            log.debug("AI 분석 완료 이벤트 처리 완료 - minutesId: {}, sequenceNumber: {}", 
                    event.getMinutesId(), eventData.getSequenceNumber());

        } catch (Exception e) {
            log.error("AI 분석 완료 이벤트 처리 실패 - sequenceNumber: {}", eventData.getSequenceNumber(), e);
            // EventHub에서는 처리 실패해도 체크포인트를 업데이트하지 않음으로써 재처리 가능
        }
    }

    /**
     * AI 분석 완료 이벤트 처리 로직
     */
    private void handleAnalysisCompleted(MinutesAnalysisCompletedEvent event) {
        String minutesId = event.getMinutesId();
        
        try {
            if ("COMPLETED".equals(event.getStatus()) && event.getResult() != null) {
                // 분석 성공 시 캐시에 결과 저장
                AiAnalysisDTO analysisDTO = convertToAnalysisDTO(event);
                cacheService.cacheAiAnalysis(minutesId, analysisDTO);
                
                log.info("AI 분석 결과 캐시 저장 완료 - minutesId: {}, analysisId: {}", 
                        minutesId, event.getAnalysisId());

            } else if ("FAILED".equals(event.getStatus()) && event.getFailure() != null) {
                // 분석 실패 시 실패 정보 로깅
                MinutesAnalysisCompletedEvent.FailureInfo failure = event.getFailure();
                log.warn("AI 분석 실패 - minutesId: {}, errorCode: {}, errorMessage: {}, retryable: {}", 
                        minutesId, failure.getErrorCode(), failure.getErrorMessage(), failure.isRetryable());

                // 재시도 가능한 실패인 경우 나중에 재처리 로직 추가 가능
                if (failure.isRetryable()) {
                    log.info("재시도 가능한 분석 실패 - minutesId: {}", minutesId);
                    // TODO: 재시도 로직 구현
                }
            }

            // 회의록 상세 조회 캐시 무효화 (새로운 AI 분석 결과 반영을 위해)
            cacheService.evictCacheMinutesDetail(minutesId);

        } catch (Exception e) {
            log.error("AI 분석 완료 이벤트 처리 중 오류 - minutesId: {}", minutesId, e);
            throw e; // 상위로 예외 전파하여 메시지 재처리
        }
    }

    /**
     * 이벤트를 DTO로 변환
     */
    private AiAnalysisDTO convertToAnalysisDTO(MinutesAnalysisCompletedEvent event) {
        MinutesAnalysisCompletedEvent.AnalysisResult result = event.getResult();
        
        // 핵심내용 변환
        List<AiAnalysisDTO.KeyPoint> keyPoints = new ArrayList<>();
        String[] keyPointsArray = result.getKeyPoints();
        for (int i = 0; i < keyPointsArray.length; i++) {
            keyPoints.add(AiAnalysisDTO.KeyPoint.builder()
                    .index(i + 1)
                    .content(keyPointsArray[i])
                    .confidence(0.85) // 기본 신뢰도
                    .category("DISCUSSION")
                    .build());
        }

        // 결정사항 변환
        List<AiAnalysisDTO.Decision> decisions = Arrays.stream(result.getDecisions())
                .map(content -> AiAnalysisDTO.Decision.builder()
                        .content(content)
                        .category("STRATEGIC")
                        .confidence(0.80)
                        .extractedFrom(content)
                        .build())
                .collect(java.util.stream.Collectors.toList());

        // 관련회의록 변환 (현재는 ID만 있으므로 기본값 사용)
        List<AiAnalysisDTO.RelatedMinutes> relatedMinutes = Arrays.stream(result.getRelatedMinutesIds())
                .map(minutesId -> AiAnalysisDTO.RelatedMinutes.builder()
                        .minutesId(minutesId)
                        .title("관련 회의록") // 실제로는 별도 조회 필요
                        .relevanceScore(0.75)
                        .reason("키워드 및 주제 유사성")
                        .meetingDate(LocalDateTime.now().minusDays(7)) // 기본값
                        .build())
                .collect(java.util.stream.Collectors.toList());

        // 분석 결과 구성
        AiAnalysisDTO.AnalysisResult analysisResult = AiAnalysisDTO.AnalysisResult.builder()
                .keyPoints(keyPoints)
                .keywords(Arrays.asList(result.getKeywords()))
                .summary(result.getSummary())
                .decisions(decisions)
                .relatedMinutes(relatedMinutes)
                .qualityScore(result.getQualityScore())
                .build();

        return AiAnalysisDTO.builder()
                .minutesId(event.getMinutesId())
                .analysisId(event.getAnalysisId())
                .status("COMPLETED")
                .requestedAt(LocalDateTime.now().minusMinutes(10)) // 추정값
                .completedAt(event.getCompletedAt())
                .result(analysisResult)
                .build();
    }

    /**
     * 에러 처리
     */
    private void processError(com.azure.messaging.eventhubs.models.ErrorContext context) {
        log.error("AI 분석 이벤트 소비 중 오류 발생 - partitionContext: {}, throwable: {}", 
                context.getPartitionContext().getPartitionId(), 
                context.getThrowable().getMessage(), 
                context.getThrowable());
    }

    @PreDestroy
    public void cleanup() {
        if (processorClient != null) {
            try {
                processorClient.stop();
                log.info("AI 분석 이벤트 소비자 종료 완료");
            } catch (Exception e) {
                log.error("AI 분석 이벤트 소비자 종료 중 오류", e);
            }
        }
    }
}