package com.arms.api.report.rolling3m.assignee.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.assignee.model.vo.AssigneeVO;
import com.arms.api.report.rolling3m.assignee.model.vo.AssigneeInfo;
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.SubGroupFieldDTO;
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 org.springframework.util.ObjectUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * [담당자 조회시 주의]
 * 1개 회사에서 n개의 클라우드 지라를 사용할 경우를 대비해서 jira_server_id가 조건으로 추가되어야 함.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AssigneeServiceImpl implements AssigneeService {

    private final EsCommonRepositoryWrapper<AlmIssueEntity> esCommonRepositoryWrapper;

    @Override
    public List<AssigneeInfo> selectRolling3mAssigneeList(Rolling3mDTO rolling3mDTO) {
        DocumentAggregations assigneeAggregation = esCommonRepositoryWrapper.aggregateRecent(
                SimpleQuery.aggregation(
                                AggregationRequestDTO.builder()
                                        .mainField("jira_server_id")
                                        .mainFieldAlias("jiraServerId")
                                        .addGroup(
                                                SubGroupFieldDTO.builder()
                                                        .subField("assignee.assignee_accountId.keyword")
                                                        .subFieldAlias("accountId")
                                                        .build(),
                                                SubGroupFieldDTO.builder()
                                                        .subField("assignee.assignee_displayName.keyword")
                                                        .subFieldAlias("displayName")
                                                        .build()
                                        )
                                        .build()
                        ).andTermQueryFilter("pdServiceId", rolling3mDTO.getPdServiceId())
                        .andTermsQueryFilter("pdServiceVersions", rolling3mDTO.getPdServiceVersions())
                        .andExistsQueryFilter("assignee")
                        .andRangeQueryFilter(RangeQueryFilter.of("created").betweenDate("now-3M/d", "now")));

        return mapToVOList(assigneeAggregation);
    }

    private List<AssigneeInfo> mapToVOList(DocumentAggregations assigneeAggregation) {
        List<DocumentBucket> docs = assigneeAggregation.deepestList();

        if (ObjectUtils.isEmpty(docs)) return Collections.emptyList();

        return docs.stream()
                .filter(Objects::nonNull)
                .map(almIssue -> AssigneeInfo.builder()
                        .jiraServerId(almIssue.valueByName("jiraServerId"))
                        .accountId(almIssue.valueByName("accountId"))
                        .displayName(almIssue.valueByName("displayName"))
                        .build())
                .distinct()
                .toList();
    }

    @Override
    public AssigneeVO selectAssigneeDisplayName(Rolling3mDTO rolling3mDTO) {
        List<AlmIssueEntity> docs = esCommonRepositoryWrapper.findRecentHits(
                        SimpleQuery
                                .termQueryFilter("pdServiceId", rolling3mDTO.getPdServiceId())
                                .andTermsQueryFilter("pdServiceVersions", rolling3mDTO.getPdServiceVersions())
                                .andTermQueryFilter("assignee.assignee_accountId.keyword", rolling3mDTO.getAssigneeId()))
                .toDocs();
        return mapToAssigneeVO(docs);
    }

    private AssigneeVO mapToAssigneeVO(List<AlmIssueEntity> docs) {
        if (ObjectUtils.isEmpty(docs)) {
            return AssigneeVO.builder()
                    .accountId("notFound")
                    .displayName("알 수 없음")
                    .build();
        }
        AlmIssueEntity.Assignee assignee = docs.getFirst().getAssignee();
        return AssigneeVO.builder()
                .accountId(assignee.getAccountId())
                .displayName(assignee.getDisplayName())
                .build();
    }

}
