package com.casic.missiles.es;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * ES查询请求体
 *
 * @author zhangyingjie123
 * @since 2020-11-30
 */
public class ElasticSearchQuery {
    private JSONObject body;
    private JSONObject query;
    private JSONObject bool;
    private JSONArray boolMust;
    private JSONObject filter;
    private JSONObject filterBool;
    private JSONArray filterBoolMust;
    private JSONArray filterBoolMustnot;

    public static final String MUST_FLAG = "1";
    public static final String MUST_NOT_FLAG = "0";

    public static final String QUERY = "query";
    public static final String BOOL = "bool";
    public static final String MUST = "must";
    public static final String MUST_NOT = "must_not";
    public static final String FILTER = "filter";


    /**
     * 生成查询请求体基础结构：
     * {
     *     "query": {
     *         "bool": {
     *             "must" [],
     *             "filter": {
     *                 "bool": {
     *                     "must": [],
     *                     "must_not": []
     *                 }
     *             }
     *         }
     *     }
     * }
     */
    public ElasticSearchQuery() {
        this.body = new JSONObject();
        this.query = this.query();
        this.bool = this.bool();
        this.boolMust = this.boolMust();
        this.filter = this.filter();
        this.filterBool = this.filterBool();
        this.filterBoolMust = this.filterBoolMust();
        this.filterBoolMustnot = this.filterBoolMustnot();
    }

    public ElasticSearchQuery(JSONObject body){
        this.body = body;
    }

    public JSONObject getBody() {
        return body;
    }

    private JSONObject query(){
        if(ObjectUtil.isEmpty(this.body.get(QUERY))){
            this.body.put("query",new JSONObject());
        }
        return this.body.getJSONObject(QUERY);

    }

    private JSONObject bool() {
        JSONObject query = this.query;
        if(ObjectUtil.isEmpty(query.get(BOOL))){
            query.put(BOOL,new JSONObject());
        }
        return query.getJSONObject(BOOL);
    }

    private JSONArray boolMust(){
        JSONObject bool = this.bool;
        if(ObjectUtil.isEmpty(bool.get(MUST))){
            bool.put(MUST,new JSONArray());
        }
        return bool.getJSONArray(MUST);
    }

    private JSONObject filter(){
        JSONObject bool = this.bool;
        if(ObjectUtil.isEmpty(bool.get(FILTER))){
            bool.put(FILTER,new JSONObject());
        }
        return bool.getJSONObject(FILTER);
    }

    private JSONObject filterBool(){
        JSONObject filter = this.filter;
        if(ObjectUtil.isEmpty(filter.get(BOOL))){
            filter.put(BOOL,new JSONObject());
        }
        return filter.getJSONObject(BOOL);
    }

    private JSONArray filterBoolMust(){
        JSONObject bool = this.filterBool;
        if(ObjectUtil.isEmpty(bool.get(MUST))){
            bool.put(MUST,new JSONArray());
        }
        return bool.getJSONArray(MUST);
    }

    private JSONArray filterBoolMustnot(){
        JSONObject bool = this.filterBool;
        if(ObjectUtil.isEmpty(bool.get(MUST_NOT))){
            bool.put(MUST_NOT,new JSONArray());
        }
        return bool.getJSONArray(MUST_NOT);
    }

    public void match(String filed, Serializable value){
        JSONArray boolMust = this.boolMust;
        JSONObject match = new JSONObject();
        JSONObject filedJson = new JSONObject();
        filedJson.put(filed,value);
        match.put("match",filedJson);
        boolMust.add(match);
    }

    public void matchPhrase(String filed, Serializable value){
        JSONArray boolMust = this.boolMust;
        JSONObject matchPhrase = new JSONObject();
        JSONObject filedJson = new JSONObject();
        filedJson.put(filed,value);
        matchPhrase.put("match_phrase",filedJson);
        boolMust.add(matchPhrase);
    }

    public void term(String filed, Serializable value){
        this.term(filed,value,MUST_FLAG);
    }

    public void term(String filed, Serializable value,String mustFlag){
        JSONObject filedJson = new JSONObject();
        filedJson.put(filed,value);
        JSONObject term = new JSONObject();
        term.put("term",filedJson);
        if(MUST_FLAG.equals(mustFlag)){
            this.filterBoolMust.add(term);
        }
        if(MUST_NOT_FLAG.equals(mustFlag)){
            this.filterBoolMustnot.add(term);
        }
    }

    public void terms(String filed,List value){
        this.terms(filed,value,MUST_FLAG);
    }

    public void terms(String filed, List value, String mustFlag){
        JSONObject filedJson = new JSONObject();
        filedJson.put(filed,value);
        JSONObject terms = new JSONObject();
        terms.put("terms",filedJson);
        if(MUST_FLAG.equals(mustFlag)){
            this.filterBoolMust.add(terms);
        }
        if(MUST_NOT_FLAG.equals(mustFlag)){
            this.filterBoolMustnot.add(terms);
        }
    }

    public void range(String filed, Serializable from, Serializable to){
        this.range(filed,from,to,MUST_FLAG);
    }

    public void range(String filed, Serializable from, Serializable to, String mustFlag){
        JSONObject rangeJson = new JSONObject();
        if(ObjectUtil.isNotEmpty(from)){
            rangeJson.put("from",from);
        }
        if(ObjectUtil.isNotEmpty(to)){
            rangeJson.put("to",to);
        }
        JSONObject filedJson = new JSONObject();
        filedJson.put(filed,rangeJson);
        JSONObject range = new JSONObject();
        range.put("range",filedJson);
        if(MUST_FLAG.equals(mustFlag)){
            this.filterBoolMust.add(range);
        }
        if(MUST_NOT_FLAG.equals(mustFlag)){
            this.filterBoolMustnot.add(range);
        }
    }

    public void size(int size){
        this.body.put("size",size);
    }

    public void from(int from) {
        this.body.put("from",from);
    }

    public void sort(String sort, String order){
        JSONObject sortJson = new JSONObject();
        JSONObject orderJson = new JSONObject();
        orderJson.put("order",order);
        sortJson.put(sort,orderJson);
        this.body.put("sort",sortJson);
    }

    public void aggs(String aggsName, String filed){
        JSONObject terms = new JSONObject();
        terms.put("field",filed);
        JSONObject aggsTerms = new JSONObject();
        aggsTerms.put("terms",terms);
        JSONObject aggsBody = new JSONObject();
        aggsBody.put(aggsName,aggsTerms);
        this.body.put("aggs",aggsBody);
    }

    public void aggs(JSONObject aggBody){
        this.body.put("aggs",aggBody);
    }



    public static void main(String[] args) {
        ElasticSearchQuery query = new ElasticSearchQuery();
        query.matchPhrase("name","张三");
        query.term("sex","2");
        List<Long> deptIds = new ArrayList<>();
        deptIds.add(0L);
        deptIds.add(24L);
        query.terms("deptId", deptIds);
        Date date1 = DateUtil.parse("2020-01-01","yyyy-MM-dd");
        Date date2 = DateUtil.parse("2020-04-01","yyyy-MM-dd");
        query.range("collTime",date1.getTime(),date2.getTime());
        query.term("collState","3",MUST_NOT_FLAG);
        query.size(10);
        query.from(0);
        query.sort("irId","asc");
        System.out.println(query.getBody().toJSONString());
    }


}
