package com.unicorn.hgzero.meeting.biz.service;

import com.unicorn.hgzero.meeting.biz.domain.MeetingAnalysis;
import com.unicorn.hgzero.meeting.biz.dto.MeetingEndDTO;
import com.unicorn.hgzero.meeting.biz.usecase.in.meeting.EndMeetingUseCase;
import com.unicorn.hgzero.meeting.infra.client.AIServiceClient;
import com.unicorn.hgzero.meeting.infra.dto.ai.ConsolidateRequest;
import com.unicorn.hgzero.meeting.infra.dto.ai.ConsolidateResponse;
import com.unicorn.hgzero.meeting.infra.dto.ai.ExtractedTodoDTO;
import com.unicorn.hgzero.meeting.infra.dto.ai.ParticipantMinutesDTO;
import com.unicorn.hgzero.meeting.infra.gateway.entity.MeetingAnalysisEntity;
import com.unicorn.hgzero.meeting.infra.gateway.entity.MeetingEntity;
import com.unicorn.hgzero.meeting.infra.gateway.entity.MinutesEntity;
import com.unicorn.hgzero.meeting.infra.gateway.entity.MinutesSectionEntity;
import com.unicorn.hgzero.meeting.infra.gateway.entity.TodoEntity;
import com.unicorn.hgzero.meeting.infra.gateway.repository.MeetingAnalysisJpaRepository;
import com.unicorn.hgzero.meeting.infra.gateway.repository.MeetingJpaRepository;
import com.unicorn.hgzero.meeting.infra.gateway.repository.MinutesJpaRepository;
import com.unicorn.hgzero.meeting.infra.gateway.repository.MinutesSectionJpaRepository;
import com.unicorn.hgzero.meeting.infra.gateway.repository.TodoJpaRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 회의 종료 비즈니스 로직 (AI 통합)
 */
@Slf4j
@Service
@Primary
@RequiredArgsConstructor
public class EndMeetingService implements EndMeetingUseCase {

    private final MeetingJpaRepository meetingRepository;
    private final MinutesJpaRepository minutesRepository;
    private final MinutesSectionJpaRepository minutesSectionRepository;
    private final TodoJpaRepository todoRepository;
    private final MeetingAnalysisJpaRepository analysisRepository;
    private final AIServiceClient aiServiceClient;

    /**
     * 회의 종료 및 AI 분석 실행
     *
     * @param meetingId 회의 ID
     * @return 회의 종료 결과 DTO
     */
    @Override
    @Transactional
    public MeetingEndDTO endMeeting(String meetingId) {
        log.info("회의 종료 시작 - meetingId: {}", meetingId);

        // 1. 회의 정보 조회
        MeetingEntity meeting = meetingRepository.findById(meetingId)
                .orElseThrow(() -> new IllegalArgumentException("회의를 찾을 수 없습니다: " + meetingId));

        // 2. 참석자별 회의록 조회 (userId가 있는 회의록들)
        List<MinutesEntity> participantMinutesList = minutesRepository.findByMeetingIdAndUserIdIsNotNull(meetingId);

        if (participantMinutesList.isEmpty()) {
            throw new IllegalStateException("참석자 회의록이 없습니다: " + meetingId);
        }

        // 3. 각 회의록의 sections 조회 및 통합
        List<MinutesSectionEntity> allMinutesSections = new ArrayList<>();
        for (MinutesEntity minutes : participantMinutesList) {
            List<MinutesSectionEntity> sections = minutesSectionRepository.findByMinutesIdOrderByOrderAsc(
                    minutes.getMinutesId()
            );
            allMinutesSections.addAll(sections);
        }

        // 4. AI 통합 분석 요청 데이터 생성
        ConsolidateRequest request = createConsolidateRequest(meeting, allMinutesSections, participantMinutesList);

        // 5. AI Service 호출
        ConsolidateResponse aiResponse = aiServiceClient.consolidateMinutes(request);

        // 5. AI 분석 결과 저장
        MeetingAnalysis analysis = saveAnalysisResult(meeting, aiResponse);

        // 6. Todo 생성 및 저장
        List<TodoEntity> todos = createAndSaveTodos(meeting, aiResponse, analysis);

        // 6. 회의 종료 처리
        meeting.end();
        meetingRepository.save(meeting);

        // 7. 응답 DTO 생성
        return createMeetingEndDTO(meeting, analysis, todos, participantMinutesList.size());
    }

    /**
     * AI 통합 분석 요청 데이터 생성
     * 참석자별 회의록의 섹션들을 참석자별로 그룹화하여 AI 요청 데이터 생성
     */
    private ConsolidateRequest createConsolidateRequest(
            MeetingEntity meeting,
            List<MinutesSectionEntity> allMinutesSections,
            List<MinutesEntity> participantMinutesList) {

        // 참석자별 회의록을 ParticipantMinutesDTO로 변환
        List<ParticipantMinutesDTO> participantMinutes = participantMinutesList.stream()
                .<ParticipantMinutesDTO>map(minutes -> {
                    // 해당 회의록의 섹션들만 필터링
                    String content = allMinutesSections.stream()
                            .filter(section -> section.getMinutesId().equals(minutes.getMinutesId()))
                            .<String>map(section -> section.getTitle() + "\n" + section.getContent())
                            .collect(Collectors.joining("\n\n"));

                    return ParticipantMinutesDTO.builder()
                            .userId(minutes.getUserId())
                            .userName(minutes.getUserId()) // 실제로는 userName이 필요하지만 일단 userId 사용
                            .content(content)
                            .build();
                })
                .collect(Collectors.toList());

        return ConsolidateRequest.builder()
                .meetingId(meeting.getMeetingId())
                .participantMinutes(participantMinutes)
                .build();
    }

    /**
     * AI 분석 결과 저장
     */
    private MeetingAnalysis saveAnalysisResult(MeetingEntity meeting, ConsolidateResponse aiResponse) {
        // AgendaAnalysis 리스트 생성
        List<MeetingAnalysis.AgendaAnalysis> agendaAnalyses = aiResponse.getAgendaSummaries().stream()
                .<MeetingAnalysis.AgendaAnalysis>map(summary -> MeetingAnalysis.AgendaAnalysis.builder()
                        .agendaId(UUID.randomUUID().toString())
                        .title(summary.getAgendaTitle())
                        .aiSummaryShort(summary.getSummaryShort())
                        .discussion(summary.getSummary() != null ? summary.getSummary() : "")
                        .decisions(List.of())
                        .pending(summary.getPending() != null ? summary.getPending() : List.of())
                        .extractedTodos(summary.getTodos() != null
                                ? summary.getTodos().stream()
                                        .<String>map(todo -> todo.getTitle())
                                        .collect(Collectors.toList())
                                : List.of())
                        .build())
                .collect(Collectors.toList());

        // MeetingAnalysis 도메인 생성
        MeetingAnalysis analysis = MeetingAnalysis.builder()
                .analysisId(UUID.randomUUID().toString())
                .meetingId(meeting.getMeetingId())
                .minutesId(meeting.getMeetingId()) // 실제로는 minutesId 필요
                .keywords(aiResponse.getKeywords())
                .decisions(aiResponse.getDecisions())
                .agendaAnalyses(agendaAnalyses)
                .status("COMPLETED")
                .completedAt(LocalDateTime.now())
                .createdAt(LocalDateTime.now())
                .build();

        // Entity 저장
        MeetingAnalysisEntity entity = MeetingAnalysisEntity.fromDomain(analysis);
        analysisRepository.save(entity);

        log.info("AI 분석 결과 저장 완료 - analysisId: {}", analysis.getAnalysisId());

        return analysis;
    }

    /**
     * Todo 생성 및 저장
     */
    private List<TodoEntity> createAndSaveTodos(MeetingEntity meeting, ConsolidateResponse aiResponse, MeetingAnalysis analysis) {
        List<TodoEntity> todos = aiResponse.getAgendaSummaries().stream()
                .<TodoEntity>flatMap(agenda -> {
                    String agendaId = findAgendaIdByTitle(analysis, agenda.getAgendaTitle());
                    List<ExtractedTodoDTO> todoList = agenda.getTodos() != null ? agenda.getTodos() : List.of();
                    return todoList.stream()
                            .<TodoEntity>map(todo -> TodoEntity.builder()
                                    .todoId(UUID.randomUUID().toString())
                                    .meetingId(meeting.getMeetingId())
                                    .minutesId(meeting.getMeetingId()) // 실제로는 minutesId 필요
                                    .title(todo.getTitle())
                                    .assigneeId("") // AI가 담당자를 추출하지 않으므로 빈 값
                                    .status("PENDING")
                                    .build());
                })
                .collect(Collectors.toList());

        if (!todos.isEmpty()) {
            todoRepository.saveAll(todos);
            log.info("Todo 생성 완료 - 총 {}개", todos.size());
        }

        return todos;
    }

    /**
     * 안건 제목으로 안건 ID 찾기
     */
    private String findAgendaIdByTitle(MeetingAnalysis analysis, String title) {
        return analysis.getAgendaAnalyses().stream()
                .filter(agenda -> agenda.getTitle().equals(title))
                .findFirst()
                .map(MeetingAnalysis.AgendaAnalysis::getAgendaId)
                .orElse(null);
    }

    /**
     * 회의 종료 결과 DTO 생성
     */
    private MeetingEndDTO createMeetingEndDTO(MeetingEntity meeting, MeetingAnalysis analysis,
                                              List<TodoEntity> todos, int participantCount) {
        // 회의 소요 시간 계산
        int durationMinutes = calculateDurationMinutes(meeting.getStartedAt(), meeting.getEndedAt());

        // 안건별 요약 DTO 생성
        List<MeetingEndDTO.AgendaSummaryDTO> agendaSummaries = analysis.getAgendaAnalyses().stream()
                .<MeetingEndDTO.AgendaSummaryDTO>map(agenda -> {
                    // 해당 안건의 Todo 필터링 (agendaId가 없을 수 있음)
                    List<MeetingEndDTO.TodoSummaryDTO> agendaTodos = todos.stream()
                            .filter(todo -> agenda.getAgendaId().equals(todo.getMinutesId())) // 임시 매핑
                            .<MeetingEndDTO.TodoSummaryDTO>map(todo -> MeetingEndDTO.TodoSummaryDTO.builder()
                                    .title(todo.getTitle())
                                    .build())
                            .collect(Collectors.toList());

                    return MeetingEndDTO.AgendaSummaryDTO.builder()
                            .title(agenda.getTitle())
                            .aiSummaryShort(agenda.getAiSummaryShort())
                            .details(MeetingEndDTO.AgendaDetailsDTO.builder()
                                    .discussion(agenda.getDiscussion())
                                    .decisions(agenda.getDecisions())
                                    .pending(agenda.getPending())
                                    .build())
                            .todos(agendaTodos)
                            .build();
                })
                .collect(Collectors.toList());

        return MeetingEndDTO.builder()
                .title(meeting.getTitle())
                .participantCount(participantCount)
                .durationMinutes(durationMinutes)
                .agendaCount(analysis.getAgendaAnalyses().size())
                .todoCount(todos.size())
                .keywords(analysis.getKeywords())
                .agendaSummaries(agendaSummaries)
                .build();
    }

    /**
     * 회의 소요 시간 계산 (분 단위)
     */
    private int calculateDurationMinutes(LocalDateTime startedAt, LocalDateTime endedAt) {
        if (startedAt == null || endedAt == null) {
            return 0;
        }
        return (int) Duration.between(startedAt, endedAt).toMinutes();
    }
}
