package com.zm.order.tool.server.builder;
import com.zm.order.tool.server.query.SearchOrderQuery;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * @Description 搜索查询条件构造
 * @Author: ph
 * @Date: 2019/11/1 16:43
 */
public class SearchRequestBuilder {
    private static final Logger logger = LoggerFactory.getLogger(SearchRequestBuilder.class);

    public static SearchSourceBuilder buildOrderSearchBuilder(SearchOrderQuery searchOrderQuery) {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        buildBaseInfoQuery(searchOrderQuery, boolQueryBuilder);
        buildPayInfoQuery(searchOrderQuery, boolQueryBuilder);
        buildPerformanceInfoQuery(searchOrderQuery, boolQueryBuilder);
        // 是否是searchAfter模式
        if (Objects.nonNull(searchOrderQuery.getSearchAfter()) && searchOrderQuery.getSearchAfter()) {
            searchSourceBuilder.sort("orderId", SortOrder.ASC);
            searchSourceBuilder.searchAfter(new Object[]{searchOrderQuery.getLastId()});
            searchSourceBuilder.size(searchOrderQuery.getSize());
        } else {
            if (Objects.nonNull(searchOrderQuery.getStart())) {
                searchSourceBuilder.from(searchOrderQuery.getStart());
                searchSourceBuilder.size(searchOrderQuery.getPageSize());
            }
            if (!StringUtils.isEmpty(searchOrderQuery.getSortField()) && !StringUtils.isEmpty(searchOrderQuery.getSortOrder())) {
                searchSourceBuilder.sort(searchOrderQuery.getSortField(), SortOrder.fromString(searchOrderQuery.getSortOrder()));
            }
        }
        searchSourceBuilder.query(boolQueryBuilder);
        if (searchOrderQuery.getCountUser()) {
            AggregationBuilder termsBuilder = AggregationBuilders.terms("userCount").field("userId");
            searchSourceBuilder.aggregation(termsBuilder);
        }
        // 根据标记判断是否需要统计总数，提升搜索性能
        Boolean count = searchOrderQuery.getRespCount();
        searchSourceBuilder.trackTotalHits(count == null || count);
        return searchSourceBuilder;
    }

    private static void buildPerformanceInfoQuery(SearchOrderQuery searchOrderQuery, BoolQueryBuilder boolQueryBuilder) {
        if (Objects.nonNull(searchOrderQuery.getPerformanceType())) {
            TermQueryBuilder performanceTypeQuery = QueryBuilders.termQuery("performanceType", searchOrderQuery.getPerformanceType());
            boolQueryBuilder.must(performanceTypeQuery);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getPerformancePlatformList())) {
            TermsQueryBuilder performancePlatformsQuery = QueryBuilders.termsQuery("performancePlatform", searchOrderQuery.getPerformancePlatformList());
            boolQueryBuilder.must(performancePlatformsQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getPerformancePlatform()) && Objects.nonNull(searchOrderQuery.getOrderType())) {
            TermQueryBuilder performancePlatformQuery = QueryBuilders.termQuery("performancePlatform", searchOrderQuery.getPerformancePlatform());
            boolQueryBuilder.must(performancePlatformQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getPerformanceStatus())) {
            TermQueryBuilder performanceStatusQuery = QueryBuilders.termQuery("performanceStatus", searchOrderQuery.getPerformanceStatus());
            boolQueryBuilder.must(performanceStatusQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getIsImmediatePerformance())) {
            TermQueryBuilder isImmediatePerformanceQuery = QueryBuilders.termQuery("isImmediatePerformance", searchOrderQuery.getIsImmediatePerformance());
            boolQueryBuilder.must(isImmediatePerformanceQuery);
        }
        if (!StringUtils.isEmpty(searchOrderQuery.getMobile())) {
            TermQueryBuilder mobileQuery = QueryBuilders.termQuery("mobile", searchOrderQuery.getMobile());
            boolQueryBuilder.must(mobileQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getIsReceipt())) {
            TermQueryBuilder isReceiptQueryBuilder = QueryBuilders.termQuery("isReceipt", searchOrderQuery.getIsReceipt());
            boolQueryBuilder.must(isReceiptQueryBuilder);
        }
        if (Objects.nonNull(searchOrderQuery.getReceiptTerminal())) {
            TermQueryBuilder receiptTerminalQueryBuilder = QueryBuilders.termQuery("receiptTerminal", searchOrderQuery.getReceiptTerminal());
            boolQueryBuilder.must(receiptTerminalQueryBuilder);
        }
        if (Objects.nonNull(searchOrderQuery.getAfterSaleStatus())) {
            TermQueryBuilder afterSaleStatusQueryBuilder = QueryBuilders.termQuery("afterSaleStatus", searchOrderQuery.getAfterSaleStatus());
            boolQueryBuilder.must(afterSaleStatusQueryBuilder);
        }
        if (Objects.nonNull(searchOrderQuery.getReceiveStatus())) {
            TermQueryBuilder receiveStatusQueryBuilder = QueryBuilders.termQuery("receiveStatus", searchOrderQuery.getReceiveStatus());
            boolQueryBuilder.must(receiveStatusQueryBuilder);
        }
        if (Objects.nonNull(searchOrderQuery.getDiscountType())) {
            TermQueryBuilder discountTypeQueryBuilder = QueryBuilders.termQuery("discountTypeList", searchOrderQuery.getDiscountType());
            boolQueryBuilder.must(discountTypeQueryBuilder);
        }
        if (Objects.nonNull(searchOrderQuery.getSpecialDeleted()) && searchOrderQuery.getSpecialDeleted() == 1) {
            boolQueryBuilder.must(QueryBuilders.termQuery("isDeleted", -3));
        }
    }

    private static void buildPayInfoQuery(SearchOrderQuery searchOrderQuery, BoolQueryBuilder boolQueryBuilder) {
        if (Objects.nonNull(searchOrderQuery.getPayAtStart())) {
            RangeQueryBuilder payAtQuery = QueryBuilders.rangeQuery("payAt");
            payAtQuery.lt(searchOrderQuery.getPayAtEnd());
            payAtQuery.gt(searchOrderQuery.getPayAtStart());
            boolQueryBuilder.must(payAtQuery);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getPayTypeList())) {
            TermsQueryBuilder payTypeQueryBuilder = QueryBuilders.termsQuery("payType", searchOrderQuery.getPayTypeList());
            boolQueryBuilder.must(payTypeQueryBuilder);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getPayStatusList())) {
            TermsQueryBuilder payStatusQueryBuilder = QueryBuilders.termsQuery("payStatus", searchOrderQuery.getPayStatusList());
            boolQueryBuilder.must(payStatusQueryBuilder);
        }
        if (Objects.nonNull(searchOrderQuery.getPayStatus())) {
            TermQueryBuilder payStatusQueryBuilder = QueryBuilders.termQuery("payStatus", searchOrderQuery.getPayStatus());
            boolQueryBuilder.must(payStatusQueryBuilder);
        }
        if (Objects.nonNull(searchOrderQuery.getPayModel())) {
            TermQueryBuilder payModelQueryBuilder = QueryBuilders.termQuery("payModel", searchOrderQuery.getPayModel());
            boolQueryBuilder.must(payModelQueryBuilder);
        }
    }

    private static void buildBaseInfoQuery(SearchOrderQuery searchOrderQuery, BoolQueryBuilder boolQueryBuilder) {
        if (!CollectionUtils.isEmpty(searchOrderQuery.getOrderTypeList())) {
            TermsQueryBuilder orderTypeQuery = QueryBuilders.termsQuery("orderType", searchOrderQuery.getOrderTypeList());
            boolQueryBuilder.must(orderTypeQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getSellerId())) {
            TermQueryBuilder sellerIdQuery = QueryBuilders.termQuery("sellerId", searchOrderQuery.getSellerId());
            boolQueryBuilder.must(sellerIdQuery);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getSellerIdList())) {
            TermsQueryBuilder sellerIdList = QueryBuilders.termsQuery("sellerId", searchOrderQuery.getSellerIdList());
            boolQueryBuilder.must(sellerIdList);
        }
        if (Objects.nonNull(searchOrderQuery.getStoreId())) {
            TermQueryBuilder storeIdQuery = QueryBuilders.termQuery("storeId", searchOrderQuery.getStoreId());
            boolQueryBuilder.must(storeIdQuery);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getUserIdList())) {
            TermsQueryBuilder userIdQuery = QueryBuilders.termsQuery("userId", searchOrderQuery.getUserIdList());
            boolQueryBuilder.must(userIdQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getOrderAtStart())) {
            RangeQueryBuilder orderAtQuery = QueryBuilders.rangeQuery("orderAt");
            orderAtQuery.lt(searchOrderQuery.getOrderAtEnd());
            orderAtQuery.gt(searchOrderQuery.getOrderAtStart());
            boolQueryBuilder.must(orderAtQuery);
        }
        if (searchOrderQuery.getUpdatedAtStart() != null && searchOrderQuery.getUpdatedAtEnd() != null) {
            RangeQueryBuilder query = QueryBuilders.rangeQuery("updatedAt");
            query.lte(searchOrderQuery.getUpdatedAtEnd().getTime());
            query.gte(searchOrderQuery.getUpdatedAtStart().getTime());
            boolQueryBuilder.must(query);
        }
        if (!StringUtils.isEmpty(searchOrderQuery.getOrderNo())) {
            TermQueryBuilder orderNoQuery = QueryBuilders.termQuery("orderNo", searchOrderQuery.getOrderNo());
            boolQueryBuilder.must(orderNoQuery);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getOrderNoList())) {
            TermsQueryBuilder orderNoQuery = QueryBuilders.termsQuery("orderNo", searchOrderQuery.getOrderNoList());
            boolQueryBuilder.must(orderNoQuery);
        }
        if (!StringUtils.isEmpty(searchOrderQuery.getStoreOrderNo())) {
            TermQueryBuilder storeOrderNoQuery = QueryBuilders.termQuery("storeOrderNo", searchOrderQuery.getStoreOrderNo());
            boolQueryBuilder.must(storeOrderNoQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getOrderSubType())) {
            TermQueryBuilder isMultiQueryBuilder = QueryBuilders.termQuery("orderSubType", searchOrderQuery.getOrderSubType());
            boolQueryBuilder.must(isMultiQueryBuilder);
        }
        if (Objects.nonNull(searchOrderQuery.getStatus())) {
            TermQueryBuilder statusQuery = QueryBuilders.termQuery("status", searchOrderQuery.getStatus());
            boolQueryBuilder.must(statusQuery);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getStatusList())) {
            TermsQueryBuilder statusQuery = QueryBuilders.termsQuery("status", searchOrderQuery.getStatusList());
            boolQueryBuilder.must(statusQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getSource())) {
            TermQueryBuilder sourceQuery = QueryBuilders.termQuery("source", searchOrderQuery.getSource());
            boolQueryBuilder.must(sourceQuery);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getSourceList())) {
            TermsQueryBuilder sourceQuery = QueryBuilders.termsQuery("source", searchOrderQuery.getSourceList());
            boolQueryBuilder.must(sourceQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getSourceNo())) {
            TermQueryBuilder sourceNoQuery = QueryBuilders.termQuery("sourceNo", searchOrderQuery.getSourceNo());
            boolQueryBuilder.must(sourceNoQuery);
        }
        if (Objects.nonNull(searchOrderQuery.getGoodsOrderSource())) {
            TermQueryBuilder sourceNoQuery = QueryBuilders.termQuery("goodsOrderSource", searchOrderQuery.getGoodsOrderSource());
            boolQueryBuilder.must(sourceNoQuery);
        }
        if (!CollectionUtils.isEmpty(searchOrderQuery.getOrderIdList())) {
            TermsQueryBuilder query = QueryBuilders.termsQuery("orderId", searchOrderQuery.getOrderIdList());
            boolQueryBuilder.must(query);
        }
        if (searchOrderQuery.getBizType() != null) {
            boolQueryBuilder.must(QueryBuilders.termQuery("bizType", searchOrderQuery.getBizType()));
        }
    }

    /**
      * 构建删除ES参数
      *
      * @date 2021/8/9 15:37
      * @param searchOrderQuery
      * @return queryBuilder
     **/
    public static QueryBuilder buildDelEsQuery(SearchOrderQuery searchOrderQuery) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        QueryBuilder queryBuilder = boolQueryBuilder;
        try {
            if (Objects.isNull(searchOrderQuery.getOrderAtStart()) || Objects.isNull(searchOrderQuery.getOrderAtEnd())) {
                throw new RuntimeException("删除数据时间范围不能为空");
            }
            RangeQueryBuilder payAtQuery = QueryBuilders.rangeQuery("orderAt");
            payAtQuery.lte(searchOrderQuery.getOrderAtEnd().getTime());
            payAtQuery.gte(searchOrderQuery.getOrderAtStart().getTime());
            boolQueryBuilder.must(payAtQuery);
        } catch (Throwable e) {
            logger.error("[buildDelEsQuery]failed！cause by:{}", e);
        }

        return queryBuilder;
    }
}
