package com.arms.egovframework.javaservice.esframework.factory.creator;

import com.arms.egovframework.javaservice.esframework.esquery.EsQuery;
import com.arms.egovframework.javaservice.esframework.factory.builder.CompositeAggregationQueryBuilder;
import com.arms.egovframework.javaservice.esframework.model.dto.esquery.CompositeGroupDTO;
import com.arms.egovframework.javaservice.esframework.model.dto.esquery.CompositeSourceDTO;
import com.arms.egovframework.javaservice.esframework.model.dto.esquery.DocFiledType;
import lombok.Getter;
import org.opensearch.search.aggregations.bucket.composite.*;
import org.opensearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.opensearch.search.sort.SortOrder;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Getter
public class CompositeAggregationQueryCreator extends CompositeAggregationQueryBuilder {

    private CompositeAggregationQueryCreator(CompositeGroupDTO compositeGroupDTO, EsQuery esQuery) {
        super(
              compositeGroupDTO
            , esQuery
            , new CompositeAggregationBuilder(
                Optional.ofNullable(compositeGroupDTO.getSources().getFirst().getFieldAlias())
                    .orElseGet(() -> "composite_group_by_" + compositeGroupDTO.getSources().getFirst().getField()),
                createCompositeSources(compositeGroupDTO.getSources())
            ).size(compositeGroupDTO.getSize())
        );
    }

    private static List<CompositeValuesSourceBuilder<?>> createCompositeSources(List<CompositeSourceDTO> sources) {
        return sources.stream()
                .map(source -> {
                    String alias = Optional.ofNullable(source.getFieldAlias())
                            .orElseGet(() -> "source_" + source.getField());
                    if(source.getFiledType().equals(DocFiledType.HistogramDay)){
                        return new DateHistogramValuesSourceBuilder(alias).calendarInterval(DateHistogramInterval.DAY)
                                .field(source.getField())
                                .format("yyyy-MM-dd")
                                .order(source.isAscending() ? SortOrder.ASC : SortOrder.DESC);
                    }
                    if(source.getFiledType().equals(DocFiledType.HistogramWeek)){
                        return new DateHistogramValuesSourceBuilder(alias).calendarInterval(DateHistogramInterval.WEEK)
                                .field(source.getField())
                                .format("yyyy-MM-dd")
                                .order(source.isAscending() ? SortOrder.ASC : SortOrder.DESC);
                    }
                    if(source.getFiledType().equals(DocFiledType.HistogramMonth)){
                        return new DateHistogramValuesSourceBuilder(alias).calendarInterval(DateHistogramInterval.MONTH)
                                .field(source.getField())
                                .format("yyyy-MM")
                                .order(source.isAscending() ? SortOrder.ASC : SortOrder.DESC);
                    }
                    return new TermsValuesSourceBuilder(alias)
                            .field(source.getField())
                            .order(source.isAscending() ? SortOrder.ASC : SortOrder.DESC);
                })
                .collect(Collectors.toList());
    }

    public static CompositeAggregationQueryCreator of(CompositeGroupDTO compositeGroupDTO, EsQuery esQuery) {
        return new CompositeAggregationQueryCreator(compositeGroupDTO, esQuery);
    }

    public static CompositeAggregationQueryCreator of(CompositeGroupDTO compositeGroupDTO) {
        return new CompositeAggregationQueryCreator(compositeGroupDTO, compositeGroupDTO.getEsQuery());
    }
}
