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.IssueArmsStateCountVO;
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.esquery.MainGroupDTO;
import com.arms.egovframework.javaservice.esframework.model.dto.request.AggregationRequestDTO;
import com.arms.egovframework.javaservice.esframework.model.vo.DocumentAggregations;
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 static com.arms.egovframework.javaservice.esframework.esquery.SimpleQuery.aggregation;

/**
 * 모든 이슈(isReq=T/F)의 암스 상태가 armsStateCategory다.
 * 수집 시 alm 서버와 매핑된 arms state로 업데이트 해준다.
 *
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class IssueStateServiceImpl implements IssueStateService {

    private final EsCommonRepositoryWrapper<AlmIssueEntity> esCommonRepositoryWrapper;

    @Override
    public IssueArmsStateCountVO selectStateCountVOByAssignee(Rolling3mDTO rolling3mDTO, Boolean isReq) {
        SimpleQuery<MainGroupDTO> query = aggregation(
                AggregationRequestDTO.builder()
                        .mainField("armsStateCategory")
                        .mainFieldAlias("stateName")
                        .build()
        )
                .andTermQueryFilter("pdServiceId", rolling3mDTO.getPdServiceId())
                .andTermsQueryFilter("pdServiceVersions", rolling3mDTO.getPdServiceVersions())
                .andTermQueryFilter("assignee.assignee_accountId.keyword", rolling3mDTO.getAssigneeId())
                .andRangeQueryFilter(RangeQueryFilter.of("created").betweenDate("now-3M/d", "now"));

        if (isReq != null) {
            query.andTermQueryFilter("isReq", isReq);
        }
        return toStateCountVO(esCommonRepositoryWrapper.aggregateRecent(query));
    }

    @Override
    public IssueArmsStateCountVO selectStateCountVO(Rolling3mDTO rolling3mDTO, Boolean isReq) {
        SimpleQuery<MainGroupDTO> query = aggregation(
                AggregationRequestDTO.builder()
                        .mainField("armsStateCategory")
                        .mainFieldAlias("stateName")
                        .build()
        )
                .andTermQueryFilter("pdServiceId", rolling3mDTO.getPdServiceId())
                .andTermsQueryFilter("pdServiceVersions", rolling3mDTO.getPdServiceVersions())
                .andRangeQueryFilter(RangeQueryFilter.of("created").betweenDate("now-3M/d", "now"));

        if (isReq != null) {
            query.andTermQueryFilter("isReq", isReq);
        }
        return toStateCountVO(esCommonRepositoryWrapper.aggregateRecent(query));
    }

    private IssueArmsStateCountVO toStateCountVO(DocumentAggregations documentAggregations) {
        long openCount       = 0L;
        long inProgressCount = 0L;
        long completedCount  = 0L;

        for (DocumentBucket bucket : documentAggregations.deepestList()) {
            String state = bucket.valueByName("stateName");
            Long   count = bucket.countByName("stateName");
            switch (state) {
                case "열림"  -> openCount       = count;
                case "진행중" -> inProgressCount = count;
                case "해결됨" -> completedCount  = count;
                default      -> log.info("알려지지 않은 state: {}", state);
            }
        }

        return IssueArmsStateCountVO.from(
                documentAggregations.getTotalHits(),
                openCount,
                inProgressCount,
                completedCount);
    }
}
