package com.arms.api.issue.search.service;

import com.arms.api.issue.almapi.model.entity.AlmIssueEntity;
import com.arms.api.search_engine.model.dto.BaseSearchAggrDTO;
import com.arms.api.search_engine.model.dto.SearchDTO;
import com.arms.api.search_engine.model.vo.SearchAggrResultVO;
import com.arms.api.search_engine.model.vo.SearchDocFieldNameAndCount;
import com.arms.api.search_engine.model.vo.SearchResultVO;
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.model.vo.DocumentResultWrapper;
import com.arms.egovframework.javaservice.esframework.model.vo.DocumentAggregations;

import com.arms.egovframework.javaservice.esframework.repository.common.EsCommonRepositoryWrapper;
import com.arms.egovframework.javaservice.esframework.esquery.SimpleQuery;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.arms.egovframework.javaservice.esframework.esquery.highlight.EsHighlightQuery.esHighlightAll;

@Slf4j
@Service
@AllArgsConstructor
public class AlmIssueSearchImpl implements AlmIssueSearch {

    private final EsCommonRepositoryWrapper<AlmIssueEntity> esCommonRepositoryWrapper;

    @Override
    public SearchResultVO<AlmIssueEntity> searchAlmIssue(SearchDTO searchDTO) {

        String startDate = searchDTO.getStartDate();
        String endDate = searchDTO.getEndDate();

        String filterFieldName = getFilterFieldName(searchDTO.getFilter().getName());

        DocumentResultWrapper<AlmIssueEntity> hits = esCommonRepositoryWrapper.findHits(
                SimpleQuery.search(searchDTO)
                    .andQueryStringFilter(searchDTO.getSearchString())
                    .andTermsQueryFilter(filterFieldName, searchDTO.getFilter().getValues())
                    .andRangeQueryFilter(RangeQueryFilter.of("@timestamp").betweenDate(startDate, endDate))
                    .highlight(esHighlightAll())
        );

        return SearchResultVO.<AlmIssueEntity>builder()
                .totalResultDocs(hits.getTotalHits())
                .searchResultDocs(hits.toHitDocs())
                .build();
    }

    private String getFilterFieldName(String filterName) {
        if (filterName != null && !filterName.isBlank() && filterName.equals("project")) {
            return "project.project_name.keyword";
        }
        return null;
    }

    // 포괄V2용
    @Override
    public SearchAggrResultVO aggregateByAlmProjectName(BaseSearchAggrDTO searchAggrDTO) {

        String startDate = searchAggrDTO.getStartDate();
        String endDate = searchAggrDTO.getEndDate();

        DocumentAggregations documentAggregations = esCommonRepositoryWrapper.aggregate(SimpleQuery.aggregation(
                    AggregationRequestDTO.builder()
                            .size(5)
                            .mainField("project.project_name.keyword")
                            .mainFieldAlias("projectName")
                            .isAscending(false)
                    .build()
                )
                .andQueryStringFilter(searchAggrDTO.getSearchString())
                .andRangeQueryFilter(RangeQueryFilter.of("@timestamp").betweenDate(startDate, endDate)));

        List<DocumentBucket> documentBuckets = documentAggregations.deepestList();
        List<SearchDocFieldNameAndCount> list = documentBuckets.stream()
                .map(documentBucket -> SearchDocFieldNameAndCount
                        .builder()
                        .docFieldName(documentBucket.valueByName("projectName"))
                        .docCount(documentBucket.countByName("projectName"))
                        .build())
                .toList();

        return SearchAggrResultVO.builder()
                .totalHits(documentAggregations.getTotalHits())
                .docFieldNameAndCounts(list)
                .build();
    }

}
