package com.arms.api.report.rolling3m.service;

import com.arms.api.issue.almapi.model.entity.AlmIssueEntity;
import com.arms.api.report.rolling3m.assignee.model.dto.Rolling3mDTO;
import com.arms.api.report.rolling3m.model.vo.ReqIssueDifficultyDistributionVO;
import com.arms.api.report.rolling3m.model.vo.ReqIssuePriorityDistributionVO;
import com.arms.api.report.rolling3m.model.vo.PriorityValueVO;
import com.arms.api.serverinfo.msa_communicate.BackendCoreReportPerformanceService;
import com.arms.egovframework.javaservice.esframework.esquery.SimpleQuery;
import com.arms.egovframework.javaservice.esframework.esquery.filter.RangeQueryFilter;
import com.arms.egovframework.javaservice.esframework.model.dto.request.AggregationRequestDTO;
import com.arms.egovframework.javaservice.esframework.model.vo.DocumentBucket;
import com.arms.egovframework.javaservice.esframework.repository.common.EsCommonRepositoryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.arms.egovframework.javaservice.esframework.esquery.SimpleQuery.aggregation;

/**
 * 요구사항(isReq=true)인 document만 집계합니다.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RequirementDistributionServiceImpl implements RequirementDistributionService {

    private final EsCommonRepositoryWrapper<AlmIssueEntity> esCommonRepositoryWrapper;

    private final BackendCoreReportPerformanceService backendCoreReportPerformanceService;

    @Override
    public ReqIssueDifficultyDistributionVO selectReqIssueDifficultyDistributionByAssignee(Rolling3mDTO request) {
        List<DocumentBucket> buckets = esCommonRepositoryWrapper.aggregateRecent(
                aggregation(
                        AggregationRequestDTO.builder()
                                .mainField("cReqProperty.cReqDifficultyName.keyword")
                                .mainFieldAlias("difficultyGroup")
                                .build()
                )
                        .andTermQueryFilter("pdServiceId", request.getPdServiceId())
                        .andTermsQueryFilter("pdServiceVersions", request.getPdServiceVersions())
                        .andTermQueryFilter("assignee.assignee_accountId.keyword", request.getAssigneeId())
                        .andTermQueryFilter("isReq", Boolean.TRUE)
                        .andRangeQueryFilter(RangeQueryFilter.of("created").betweenDate("now-3M/d", "now"))
        ).deepestList();
        return buildDifficultyDistribution(buckets);
    }

    @Override
    public ReqIssueDifficultyDistributionVO selectReqIssueDifficultyDistribution(Rolling3mDTO request) {
        List<DocumentBucket> buckets = esCommonRepositoryWrapper.aggregateRecent(
                aggregation(
                        AggregationRequestDTO.builder()
                                .mainField("cReqProperty.cReqDifficultyName.keyword")
                                .mainFieldAlias("difficultyGroup")
                                .build()
                )
                        .andTermQueryFilter("pdServiceId", request.getPdServiceId())
                        .andTermsQueryFilter("pdServiceVersions", request.getPdServiceVersions())
                        .andTermQueryFilter("isReq", Boolean.TRUE)
                        .andRangeQueryFilter(RangeQueryFilter.of("created").betweenDate("now-3M/d", "now"))
        ).deepestList();
        return buildDifficultyDistribution(buckets);
    }

    @Override
    public ReqIssuePriorityDistributionVO selectReqIssuePriorityDistributionByAssignee(Rolling3mDTO rolling3mDTO) {
        List<Long> cIds = selectReqIssueCIdsByAssignee(rolling3mDTO);
        return buildPriorityValueDistribution(getPriorityValueListFromBackendCore(rolling3mDTO.getPdServiceId(), cIds));
    }

    @Override
    public ReqIssuePriorityDistributionVO selectReqIssuePriorityDistribution(Rolling3mDTO rolling3mDTO) {
        List<Long> cIds = selectReqIssueCIds(rolling3mDTO);
        return buildPriorityValueDistribution(getPriorityValueListFromBackendCore(rolling3mDTO.getPdServiceId(), cIds));
    }

    private List<PriorityValueVO> getPriorityValueListFromBackendCore (Long pdServiceId, List<Long> cIds) {
        String reqAddTableName = "T_ARMS_REQADD_" + pdServiceId;
        return backendCoreReportPerformanceService.selectPriorityValueByTable(reqAddTableName, cIds);
    }

    private ReqIssueDifficultyDistributionVO buildDifficultyDistribution(List<DocumentBucket> buckets) {
        ReqIssueDifficultyDistributionVO.ReqIssueDifficultyDistributionVOBuilder builder =
                ReqIssueDifficultyDistributionVO.builder()
                        .veryHard(0L).hard(0L).normal(0L).easy(0L).veryEasy(0L);

        for (DocumentBucket bucket : buckets) {
            String label = bucket.valueByName("difficultyGroup");
            long count = bucket.countByName("difficultyGroup");
            switch (label) {
                case "매우 어려움" -> builder.veryHard(count);
                case "어려움"     -> builder.hard(count);
                case "보통"       -> builder.normal(count);
                case "쉬움"       -> builder.easy(count);
                case "매우 쉬움"  -> builder.veryEasy(count);
            }
        }
        return builder.build();
    }

    private ReqIssuePriorityDistributionVO buildPriorityValueDistribution(List<PriorityValueVO> valueList) {
        long highest = 0L, high = 0L, medium = 0L, low = 0L, lowest = 0L;

        for (PriorityValueVO row : valueList) {
            Number priorityValueObj = row.getPriorityValue();
            if (priorityValueObj == null) continue;

            double value = priorityValueObj.doubleValue();
            if      (value < 1.95) lowest++;
            else if (value < 3.35) low++;
            else if (value < 4.75) medium++;
            else if (value < 6.15) high++;
            else                   highest++;
        }

        return ReqIssuePriorityDistributionVO.builder()
                .highest(highest).high(high).medium(medium).low(low).lowest(lowest)
                .build();
    }

    private List<Long> selectReqIssueCIdsByAssignee(Rolling3mDTO request) {
        return esCommonRepositoryWrapper.findRecentHits(
                        SimpleQuery.termQueryFilter("pdServiceId", request.getPdServiceId())
                                .andTermsQueryFilter("pdServiceVersions", request.getPdServiceVersions())
                                .andTermQueryFilter("assignee.assignee_accountId.keyword", request.getAssigneeId())
                                .andTermQueryFilter("isReq", Boolean.TRUE)
                                .andRangeQueryFilter(RangeQueryFilter.of("created").betweenDate("now-3M/d", "now"))
                ).toDocs().stream()
                .map(AlmIssueEntity::getCReqLink)
                .toList();
    }

    private List<Long> selectReqIssueCIds(Rolling3mDTO request) {
        return esCommonRepositoryWrapper.findRecentHits(
                        SimpleQuery.termQueryFilter("pdServiceId", request.getPdServiceId())
                                .andTermsQueryFilter("pdServiceVersions", request.getPdServiceVersions())
                                .andTermQueryFilter("isReq", Boolean.TRUE)
                                .andRangeQueryFilter(RangeQueryFilter.of("created").betweenDate("now-3M/d", "now"))
                ).toDocs().stream()
                .map(AlmIssueEntity::getCReqLink)
                .toList();
    }
}
