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

import com.unicorn.hgzero.common.exception.BusinessException;
import com.unicorn.hgzero.common.exception.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

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

/**
 * 회의록 도메인 모델
 */
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Minutes {

    /**
     * 회의록 ID
     */
    private String minutesId;

    /**
     * 회의 ID
     */
    private String meetingId;

    /**
     * 작성자 사용자 ID (NULL: AI 통합 회의록, NOT NULL: 참석자별 회의록)
     */
    private String userId;

    /**
     * 회의록 제목
     */
    private String title;

    /**
     * 회의록 섹션 목록
     */
    private List<MinutesSection> sections;

    /**
     * 회의록 상태 (DRAFT, FINALIZED)
     */
    private String status;

    /**
     * 버전
     */
    private Integer version;

    /**
     * 작성자 ID
     */
    private String createdBy;

    /**
     * 생성 시간
     */
    private LocalDateTime createdAt;

    /**
     * 최종 수정 시간
     */
    private LocalDateTime lastModifiedAt;

    /**
     * 최종 수정자 ID
     */
    private String lastModifiedBy;

    /**
     * 회의 전체 결정사항
     */
    private String decisions;

    /**
     * 확정자 ID
     */
    private String finalizedBy;

    /**
     * 확정 일시
     */
    private LocalDateTime finalizedAt;

    /**
     * 회의록 확정 가능 여부 검증
     *
     * @param meeting 회의 정보
     * @param userId 확정 요청자 ID
     * @throws BusinessException 검증 실패 시
     */
    public void validateCanConfirm(Meeting meeting, String userId) {
        List<String> errors = new ArrayList<>();

        // 1. 상태 검증
        if (!"DRAFT".equals(this.status)) {
            throw new BusinessException(ErrorCode.INVALID_INPUT_VALUE, "회의록이 작성중 상태가 아닙니다. 현재 상태: " + this.status);
        }

        if (!"COMPLETED".equals(meeting.getStatus())) {
            throw new BusinessException(ErrorCode.INVALID_INPUT_VALUE, "회의가 종료되지 않았습니다. 현재 회의 상태: " + meeting.getStatus());
        }

        // 2. 권한 검증
        boolean isOrganizer = meeting.getOrganizerId().equals(userId);
        boolean isParticipant = meeting.getParticipants() != null && meeting.getParticipants().contains(userId);

        if (!isOrganizer && !isParticipant) {
            throw new BusinessException(ErrorCode.ACCESS_DENIED, "회의록 확정 권한이 없습니다.");
        }

        // 3. 필수 항목 검증
        if (this.title == null || this.title.trim().isEmpty()) {
            errors.add("회의록 제목이 없습니다.");
        } else if (this.title.trim().length() < 5) {
            errors.add("회의록 제목은 최소 5자 이상이어야 합니다.");
        }

        if (meeting.getParticipants() == null || meeting.getParticipants().isEmpty()) {
            errors.add("참석자가 최소 1명 이상 있어야 합니다.");
        }

        // 섹션 검증
        if (this.sections != null && !this.sections.isEmpty()) {
            boolean hasDiscussionContent = false;
            boolean hasDecisionContent = false;

            for (MinutesSection section : this.sections) {
                if ("DISCUSSION".equals(section.getType()) && section.getContent() != null && section.getContent().trim().length() >= 20) {
                    hasDiscussionContent = true;
                }
                if ("DECISION".equals(section.getType())) {
                    if (section.getContent() != null && !section.getContent().trim().isEmpty()) {
                        hasDecisionContent = true;
                    }
                }
            }

            if (!hasDiscussionContent) {
                errors.add("주요 논의 내용이 없거나 20자 미만입니다.");
            }

            if (!hasDecisionContent) {
                errors.add("결정 사항이 없습니다. (결정사항이 없는 경우 '결정사항 없음'을 명시해주세요)");
            }
        } else {
            errors.add("회의록 섹션이 없습니다.");
        }

        // 4. 데이터 무결성 검증
        if (this.sections != null) {
            for (MinutesSection section : this.sections) {
                // 필수 필드 검증
                if (section.getTitle() == null || section.getTitle().trim().isEmpty()) {
                    errors.add("섹션 제목이 비어있는 섹션이 있습니다. (섹션 ID: " + section.getSectionId() + ")");
                }

                if (section.getContent() == null || section.getContent().trim().isEmpty()) {
                    errors.add("섹션 내용이 비어있는 섹션이 있습니다. (섹션 ID: " + section.getSectionId() + ")");
                }
            }
        }

        // 검증 오류가 있으면 예외 발생
        if (!errors.isEmpty()) {
            String errorMessage = "회의록 확정 검증 실패:\n" + String.join("\n", errors);
            throw new BusinessException(ErrorCode.INVALID_INPUT_VALUE, errorMessage);
        }

        // 5. 이력 검증 (경고)
        if (this.lastModifiedAt != null) {
            Duration duration = Duration.between(this.lastModifiedAt, LocalDateTime.now());
            if (duration.toHours() > 24) {
                // 로그로 경고만 출력 (진행 가능)
                // TODO: 경고 메시지를 응답에 포함시키는 방법 고려
            }
        }
    }

    /**
     * 회의록 확정
     */
    public void finalize(String userId) {
        this.status = "FINALIZED";
        this.finalizedBy = userId;
        this.finalizedAt = LocalDateTime.now();
    }

    /**
     * 회의록 수정
     */
    public void update() {
        this.version++;
    }

    /**
     * 회의록 확정 여부 확인
     */
    public boolean isFinalized() {
        return "FINALIZED".equals(this.status);
    }

    /**
     * 버전 증가
     */
    public void incrementVersion() {
        this.version++;
    }

    /**
     * 회의록 제목 업데이트
     */
    public void updateTitle(String title) {
        this.title = title;
        this.version++;
    }

    /**
     * 모든 섹션 잠금
     */
    public void lockAllSections(String userId) {
        if (this.sections != null) {
            for (MinutesSection section : this.sections) {
                if (!section.isLocked()) {
                    section.lock(userId);
                }
            }
        }
    }
}
