package com.zm.order.tool.server.builder;

import com.google.common.collect.Lists;
import com.zm.order.tool.server.enums.DeleteTypeEnum;
import com.zm.order.tool.server.query.SearchRefundQuery;
import com.zm.order.tool.server.utils.OrderCommonUtils;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * <p>
 *
 * </p>
 *
 * @author nianchang
 * @date 2024/01/04 2:59 下午
 */
public class SearchRefundRequestBuilder {

    public static SearchSourceBuilder buildOrderSearchBuilder(SearchRefundQuery query) {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        buildBaseInfoQuery(query, boolQueryBuilder);
        buildBase0InfoQuery(query, boolQueryBuilder);
        buildBase1InfoQuery(query, boolQueryBuilder);
        // 是否是searchAfter模式
        if (Objects.nonNull(query.getSearchAfter()) && query.getSearchAfter()) {
            builder.sort("docId", SortOrder.ASC);
            builder.searchAfter(new Object[]{query.getLastId()});
            builder.size(query.getSize());
        } else {
            // 如果不是统计并且没有传分页，默认查询第一页数据
            // count请求不能传分页参数，ES会报错，规避ES字段排序（提升性能）
            if (query.getCountRequest() == null || !query.getCountRequest()) {
                if (query.getStart() == null) {
                    builder.from(1);
                    builder.size(10);
                } else {
                    builder.from(query.getStart());
                    builder.size(query.getPageSize());
                }
                builder.sort("applyAt", SortOrder.DESC);
                builder.sort("docId", SortOrder.DESC);
            }
        }
        builder.query(boolQueryBuilder);

        // 根据标记判断是否需要统计总数，提升搜索性能
        // 这里的和上面的countRequest不同，此处一般用于导出场景，使用id推进分页，所以需要字段排序
        Boolean count = query.getRespCount();
        builder.trackTotalHits(count == null || count);
        return builder;
    }

    private static void buildBaseInfoQuery(SearchRefundQuery query, BoolQueryBuilder boolQueryBuilder) {
        if (!CollectionUtils.isEmpty(query.getDeleteTypeList())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("isDeleted", query.getDeleteTypeList()));
        } else {
            boolQueryBuilder.must(QueryBuilders.termsQuery(
                    "isDeleted", Lists.newArrayList(DeleteTypeEnum.ACTIVE.getValue())));
        }
        if (Objects.nonNull(query.getOrderType())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("orderType", query.getOrderType()));
        }
        if (!CollectionUtils.isEmpty(query.getOrderTypeList())) {
            TermsQueryBuilder orderTypeQuery = QueryBuilders.termsQuery("orderType", query.getOrderTypeList());
            boolQueryBuilder.must(orderTypeQuery);
        }
        if (Objects.nonNull(query.getBizType())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("bizType", query.getBizType()));
        }
        if (!CollectionUtils.isEmpty(query.getBizTypeList())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("bizType", query.getBizTypeList()));
        }
        if (Objects.nonNull(query.getExcludeBizType())) {
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("bizType", query.getExcludeBizType()));
        }
        if (!CollectionUtils.isEmpty(query.getExcludeBizTypeList())) {
            boolQueryBuilder.mustNot(QueryBuilders.termsQuery("bizType", query.getExcludeBizTypeList()));
        }
        if (Objects.nonNull(query.getSellerId())) {
            TermQueryBuilder sellerIdQuery = QueryBuilders.termQuery("sellerId", query.getSellerId());
            boolQueryBuilder.must(sellerIdQuery);
        }
        if (Objects.nonNull(query.getStoreId())) {
            TermQueryBuilder storeIdQuery = QueryBuilders.termQuery("storeId", query.getStoreId());
            boolQueryBuilder.must(storeIdQuery);
        }
        if (!CollectionUtils.isEmpty(query.getStoreIdList())) {
            TermsQueryBuilder storeIdList = QueryBuilders.termsQuery("storeId", query.getStoreIdList());
            boolQueryBuilder.must(storeIdList);
        }
        if (Objects.nonNull(query.getOrderAtStart()) && Objects.nonNull(query.getOrderAtEnd())) {
            RangeQueryBuilder orderAtQuery = QueryBuilders.rangeQuery("orderAt");
            orderAtQuery.lte(query.getOrderAtEnd());
            orderAtQuery.gte(query.getOrderAtStart());
            boolQueryBuilder.must(orderAtQuery);
        }
        if (Objects.nonNull(query.getApplyAtStart()) && Objects.nonNull(query.getApplyAtEnd())) {
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("applyAt");
            rangeQuery.lte(query.getApplyAtEnd());
            rangeQuery.gte(query.getApplyAtStart());
            boolQueryBuilder.must(rangeQuery);
        }
        if (Objects.nonNull(query.getDealAtStart()) && Objects.nonNull(query.getDealAtEnd())) {
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("dealAt");
            rangeQuery.lte(query.getDealAtEnd());
            rangeQuery.gte(query.getDealAtStart());
            boolQueryBuilder.must(rangeQuery);
        }
    }

    private static void buildBase1InfoQuery(SearchRefundQuery query, BoolQueryBuilder boolQueryBuilder) {
        if (!StringUtils.isEmpty(query.getOrderNo())) {
            TermQueryBuilder orderNoQuery = QueryBuilders.termQuery("orderNo", query.getOrderNo());
            boolQueryBuilder.must(orderNoQuery);
        }
        if (!CollectionUtils.isEmpty(query.getOrderNoList())) {
            TermsQueryBuilder orderNoQuery = QueryBuilders.termsQuery("orderNo", query.getOrderNoList());
            boolQueryBuilder.must(orderNoQuery);
        }
        if (!StringUtils.isEmpty(query.getRefundNo())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("refundNo", query.getRefundNo()));
        }
        if (!CollectionUtils.isEmpty(query.getRefundNoList())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("refundNo", query.getRefundNoList()));
        }
        if (Objects.nonNull(query.getOrderSubType())) {
            TermQueryBuilder isMultiQueryBuilder = QueryBuilders.termQuery("orderSubType", query.getOrderSubType());
            boolQueryBuilder.must(isMultiQueryBuilder);
        }
        if (!CollectionUtils.isEmpty(query.getOrderSubTypeList())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("orderSubType", query.getOrderSubTypeList()));
        }
        if (Objects.nonNull(query.getStatus())) {
            TermQueryBuilder statusQuery = QueryBuilders.termQuery("status", query.getStatus());
            boolQueryBuilder.must(statusQuery);
        }
        if (!CollectionUtils.isEmpty(query.getStatusList())) {
            TermsQueryBuilder statusQuery = QueryBuilders.termsQuery("status", query.getStatusList());
            boolQueryBuilder.must(statusQuery);
        }
        if (Objects.nonNull(query.getSource())) {
            TermQueryBuilder sourceQuery = QueryBuilders.termQuery("source", query.getSource());
            boolQueryBuilder.must(sourceQuery);
        }
        if (!CollectionUtils.isEmpty(query.getSourceList())) {
            TermsQueryBuilder sourceQuery = QueryBuilders.termsQuery("source", query.getSourceList());
            boolQueryBuilder.must(sourceQuery);
        }
        if (Objects.nonNull(query.getSourceNo())) {
            TermQueryBuilder sourceNoQuery = QueryBuilders.termQuery("sourceNo", query.getSourceNo());
            boolQueryBuilder.must(sourceNoQuery);
        }
    }

    private static void buildBase0InfoQuery(SearchRefundQuery query, BoolQueryBuilder boolQueryBuilder) {
        if (Objects.nonNull(query.getPlatformUserId())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("platformUserId", query.getPlatformUserId()));
        }
        if (!CollectionUtils.isEmpty(query.getPlatformUserIdList())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("platformUserId", query.getPlatformUserIdList()));
        }
        if (Objects.nonNull(query.getPlatformSellerId())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("platformSellerId", query.getPlatformSellerId()));
        }
        if (Objects.nonNull(query.getRefundLevel())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("refundLevel", query.getRefundLevel()));
        }
        if (Objects.nonNull(query.getRefundType())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("refundType", query.getRefundType()));
        }
        if (Objects.nonNull(query.getRefundWay())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("refundWay", query.getRefundWay()));
        }
        if (Objects.nonNull(query.getUserId())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("userId", query.getUserId()));
        }
        if (Objects.nonNull(query.getIsAlone())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("isAlone", query.getIsAlone()));
        }
        if (Objects.nonNull(query.getFromSystem())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("fromSystem", query.getFromSystem()));
        }
        if (Objects.nonNull(query.getReviewStatus())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("reviewStatus", query.getReviewStatus()));
        }
        if (Objects.nonNull(query.getPerformanceType())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("performanceType", query.getPerformanceType()));
        }
        if (!CollectionUtils.isEmpty(query.getPerformanceTypeList())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("performanceType", query.getPerformanceTypeList()));
        }
        if (!CollectionUtils.isEmpty(query.getPerformanceTypeList())) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("performanceType", query.getPerformanceTypeList()));
        }
        if (!CollectionUtils.isEmpty(query.getExcludeSourceList())) {
            boolQueryBuilder.mustNot(QueryBuilders.termsQuery("source", query.getExcludeSourceList()));
        }
        if (OrderCommonUtils.isNotEmpty(query.getMobile())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("mobile", query.getMobile()));
        }
    }
}
