package com.liangjian.dataplatform.member.service.impl;

import com.liangjian.dataplatform.member.dao.fourthly.MemDataDictoryRepository;
import com.liangjian.dataplatform.member.dao.tertiary.DataDictoryRepository;
import com.liangjian.dataplatform.member.entity.po.fourthly.MemDataDictory;
import com.liangjian.dataplatform.member.entity.po.secondary.FiltersData;
import com.liangjian.dataplatform.member.entity.po.secondary.FiltersUtils;
import com.liangjian.dataplatform.member.entity.po.tertiary.DataDictory;
import com.liangjian.dataplatform.member.jobUtil.EsUtils;
import com.liangjian.dataplatform.member.service.IMemberListService;
import com.liangjian.dataplatform.member.util.StringUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class MemberListService implements IMemberListService {

    //链接查询es
    public static EsUtils esUtils=new EsUtils();

    //sql查询es _xpack/sql?format=json
    public static String Host="http://192.168.50.34:9200/";

    @Autowired
    private MemDataDictoryRepository memDataDictoryRepository;


//    @Autowired
//    private EntityManager entityManager;


    @Override
    public String index(FiltersData data) {
        String aaa = JSONObject.fromObject(data).toString();
        int start = 0;
        String filterStr = null;
        String query = null;
        Map<String, Object> ret = new HashMap<String, Object>();
        Map<String, List<FiltersUtils>> map = new HashMap<String, List<FiltersUtils>>();
        List<String> phonesSearch = new ArrayList<String>(1);
        if(data != null){
            List<FiltersUtils> filters = data.getFilters();
            if(filters != null && filters.size() != 0){
                for (FiltersUtils filter : filters) {
                    String fieId = filter.getField();
                    String value = filter.getValue();
                    if("MemUsualPhone".equals(fieId.trim()) && null != value && !"".equals(value.trim())){
                        phonesSearch.add(value);
                        String[] encryption = getPhoneEncrypt((String[])phonesSearch.toArray(), true);
                        value = encryption[0];
                    }

                    if(fieId.indexOf(".")>0 &&  null != value && !value.equals("null")){
                        List<FiltersUtils> list = null;
                        map.put(fieId, list);
                        if (list == null) {
                            list = new ArrayList<FiltersUtils>();
                        }
                        else {
                            filter = null;//空字段
                        }
                        List<Map<String, Object>> rulesList = filter.getRules();
                        if(null != rulesList && rulesList.size() > 0){
                            Map<String, Object> rulesMap = rulesList.get(0);
                            if(!StringUtil.isEmpty(rulesMap.get("value").toString())){
                                list.add(filter);
                            }
                        }
                        map.put(fieId, list);
                    }

                }
            }
            filterStr = getFilterString(filters);
            if (data.getPageIndex() == 1){
                start = 0;
            } else{
                start = ((data.getPageIndex() - 1) * data.getPageSize()) + 1;
            }
            query = "select * from mem_memberbase_p where 1=1 "+filterStr+"  order by RegisterTime desc   limit "+data.getPageSize()+"";

        }
        String sql = EsUtils.query(query, "_sql/translate?format=json",true);
        ret.put("items", new ArrayList<Map<String, Object>>());
        String from = "\"from\":" + start + ",";
        StringBuffer sb= new StringBuffer(sql);
        sql = sb.insert(1,from).toString();


        int sourceIndex = sql.indexOf("\"_source\":{");
        int sourceIndexEnd = sql.indexOf("},", sourceIndex);
        String sourcestr = sql.substring(sourceIndex, sourceIndexEnd  + 1);
        sql = sql.replace(sourcestr, "\"_source\":{\"includes\":[\"*\"], \"excludes\": []}");

        int fieldIndex = sql.indexOf("\"docvalue_fields\":[");
        int fieldIndexEnd = sql.indexOf("],", fieldIndex);

        String firstHalf = sql.substring(0, fieldIndex);
        String Half = sql.substring(fieldIndex + (fieldIndexEnd - fieldIndex + 2), sql.length());
        sql = firstHalf+Half;

        if(map.size() > 0){
            for (String key : map.keySet()) {
                List<FiltersUtils> filters = map.get(key);
                if(null == filters || filters.size() == 0){
                    continue;
                }
                String [] values = new String[filters.size()];
                for (int i = 0; i <filters.size() ; i++) {
                    FiltersUtils filter = filters.get(i);
                    List<Map<String, Object>> rules = filter.getRules();
                    if(null == rules || rules.size() == 0){
                        String value = filter.getValue();
                        if(!StringUtil.isEmpty(value)){
                            values[i] = value;
                        }
                        continue;
                    }else{
                        String value = rules.get(0).get("value").toString();
                        if(!StringUtil.isEmpty(value)){
                            values[i] = value;
                        }
                    }
                }

                StringBuilder nestMinMatch = new StringBuilder(5);
                nestMinMatch.append("{ 'bool': { 'should': [");
                for (int i = 0; i <values.length ; i++) {
                    var valuestr = "[" + String.join(",", values[0]) +"]";
                    String newKey = key.replace('.',',');
                    String [] keytoken = newKey.split(",");
                    String path = keytoken[0];
                    String tnest ="{\"nested\":{\"query\":{\"bool\":{\"must\":[{\"term\":{\"Terminals.TerminalCode\":{\"value\":\"6\"}}}]}},\"path\":\"Terminals\",\"ignore_unmapped\":false,\"score_mode\":\"none\",\"boost\":1.0}}";
                    tnest = tnest.replace(":\"6\"", ":\"" + values[0]+ "\"");
                    tnest = tnest.replace("Terminals.TerminalCode", key);
                    tnest = tnest.replace("Terminals", path);
                    nestMinMatch.append(tnest);
                }
//                nestMinMatch = nestMinMatch.remove(nestMinMatch.length()-1,1);
                nestMinMatch.substring(nestMinMatch.length()-1);
                nestMinMatch.append("],'minimum_should_match': "+ values.length+ "");
                nestMinMatch.append("}}" );

                String snest = "{\"nested\":{\"query\":{\"term\":{\"Terminals.MemSourcePlatforms\":{\"value\":\"2\",\"boost\":1.0}}},\"path\":\"Terminals\",\"ignore_unmapped\":false,\"score_mode\":\"none\",\"boost\":1.0}}";
                String sValue = "";
                List<Map<String, Object>> rules = null;
                if(null != filters && filters.size() > 0){
                    rules = filters.get(0).getRules();
                }

                if (rules !=null && rules.size()>0){
                    sValue = rules.get(0).get("value").toString();
                }else{
                    sValue = filters.get(0).getValue();
                }

                sql = sql.replace(snest.replace("Terminals.MemSourcePlatforms", key).replace("\"2\"", "\""+ sValue + "\""), nestMinMatch.toString());
            }
        }

        String str = EsUtils.query(sql, "mem_memberbase_p/_search?format=json",false);

        net.sf.json.JSONObject jsonObject= JSONObject.fromObject(str);
        JSONArray jsonArray = JSONObject.fromObject(jsonObject.getString("hits")).getJSONArray("hits");
        List<Map<String, Object>> items = new ArrayList<Map<String, Object>>();
        for (int i=0; i<jsonArray.size();i++){
            Map<String, Object> hitsMap = (Map<String, Object>) jsonArray.get(i);
            Map<String, Object> sourceMap = (Map<String, Object>) hitsMap.get("_source");
            sourceMap.put("_id",hitsMap.get("_id"));
            items.add(sourceMap);
        }
        Object[] object = jsonArray.toArray();
        List<Object> lisat = Arrays.asList(object);
        List<String> phones = new ArrayList<String>(items.size());
        for (Map<String, Object> o : items) {
            Map<String, Object> maps = (Map<String, Object>)o;
            if(null != maps.get("MemUsualPhone") && maps.get("MemUsualPhone").toString().length() == 32){
                phones.add(maps.get("MemUsualPhone").toString());
            }else{
                phones.add("");
            }
        }
        String[] phones1 = getPhoneEncrypt(phones.toArray(String[]::new),false);
        for (int i = 0; i <items.size() ; i++) {
            Map<String, Object> maps = (Map<String, Object>)items.get(i);
            if(null != maps.get("MemUsualPhone") && maps.get("MemUsualPhone").toString().length() == 32){
                maps.put("MemUsualPhoneCr",maps.get("MemUsualPhone"));
                String phoneStars = phones1[i];
                if (phoneStars != null && phoneStars.length() > 8){
                    String replaced = phoneStars.substring(3, 7);
                    phoneStars = phoneStars.replace(replaced, "****");
                }
                maps.put("MemUsualPhone",phoneStars);
                maps.put("MemUsualPhoneOr",phones1[i]);
            }
//            Object MemUsualPhone = source.get("MemUsualPhone");
//            source.put("MemUsualPhone","");
        }
        //总数
        long totalcount = 0;
        sql ="select count(1) from mem_memberbase_p where 1=1 " +filterStr +"";
        String dataTotale = EsUtils.query(sql,"_sql?format=json", true);
        JSONObject totalJson= JSONObject.fromObject(dataTotale);
        JSONArray rowsArray = totalJson.getJSONArray("rows");
        List<Integer> listRow = (List<Integer>) rowsArray.get(0);

        ret.put("items",items);
        ret.put("totalCount",listRow.get(0));
        String json = JSONObject.fromObject(ret).toString();
        return json;
    }


    // 加密
    public String[] getPhoneEncrypt(String[] MemPhones, boolean sign){
        int len = MemPhones.length;
        String[] phones = new String[len];
        StringBuilder sb = new StringBuilder();
        sb.append("select ");

        for (int i = 0;i<len;i++){
           String number = MemPhones[i];
           if(!StringUtil.isEmpty(number)){
               Map<String, Object> map = null;
               if(sign){// 加密
                   map = memDataDictoryRepository.desEncryptFixKey(number);
               }else{// 解密
                   map = memDataDictoryRepository.desDecryptFixKey(number);
               }
               String phone = (String) map.get("phone");
               phones[i] = phone;
           }
        }
        return phones;
    }


    public String getFilterString(List<FiltersUtils> filterList) {
        String queryCondition = "";
        if (filterList != null) {
            for (FiltersUtils item : filterList) {
                if (item != null && (!StringUtil.isEmpty(item.getValue()) || (item.getRules() != null && item.getRules().size() > 0))) {
                    String val = item.getValue();
                    String field = item.getField();
                    String operate = item.getOperate();
                    switch (operate) {
                        case "equal":
                            queryCondition += " and " + field + "=  '" + val + "'";
                            break;
                        case "notequal":
                            queryCondition += " and " + field + "!=  " + val;

                            break;
                        case "less":
                            queryCondition += " and " + field + "< " + val;

                            break;
                        case "lessorequal":
                            queryCondition += " and " + field + "<= " + val;

                            break;
                        case "greater":
                            queryCondition += " and " + field + "> " + val;

                            break;
                        case "greateroreeuqal":
                            queryCondition += " and " + field + ">= " + val;

                            break;
                        case "contains":
                            queryCondition += " and " + field + " like '%" + val + "%'";

                            break;
                        case "startswith":
                            queryCondition += " and " + field + " like '" + val + "%'";

                            break;
                        case "endswith":
                            queryCondition += " and " + field + " like '%" + val + "'";

                            break;
                        case "or":
                            var innerCondition = "1 = 1";
                            List<Map<String, Object>> rulesMap = item.getRules();
                            for (Map<String, Object> stringObjectMap : rulesMap) {
                                String rulesField = (String) stringObjectMap.get("field");
                                String rulesValue = (String) stringObjectMap.get("value");
                                innerCondition += " or "+rulesField+" = '"+rulesValue+"'";
                            }

                            innerCondition = innerCondition.replace("1 = 1 or", "");
                            queryCondition += " and (" + innerCondition + ")";

                            break;
                        case "nestand":
                            var innerConditionNest = "1 = 1";
                            List<Map<String, Object>> rules = item.getRules();
                            for (Map<String, Object> stringObjectMap : rules) {
                                String rulesField = (String) stringObjectMap.get("field");
                                String rulesvalue = (String) stringObjectMap.get("value");
                                innerConditionNest += " and "+rulesField+" = '"+rulesvalue+"'";
                            }
                            innerConditionNest = innerConditionNest.replace("1 = 1 and", "");
                            queryCondition += " and (" + innerConditionNest + ")";

                            break;
                    }
                }
            }
//            Console.WriteLine(queryCondition);
        }
        return queryCondition;
    }
}
