package com.chenyang.nse.bussiness.tools.es;

import com.ghca.fastjson.JSONObject;
import com.chenyang.nse.bussiness.commmon.json.ErrCode;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreDatasystem;
import com.chenyang.nse.bussiness.exception.CustomException;
import com.chenyang.nse.bussiness.tools.string.AesTool;
import com.chenyang.nse.bussiness.tools.utils.GHCAUtils;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang3.StringUtils;
import org.frameworkset.elasticsearch.client.ClientInterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ElasticSearchUtil {
   private static final Logger log = LoggerFactory.getLogger(ElasticSearchUtil.class);

   public static Set<String> getFields(TCoreDatasystem dataSystem, String index, String type) {
      String mapping = getMapping(dataSystem, index, type);

      try {
         Set<String> jsonKeySet = getJsonKeySet(mapping, index, type);
         return jsonKeySet;
      } catch (Exception e) {
         log.error("parse json error", e);
         throw new CustomException(ErrCode.DATA_PROCESS_ERROR);
      }
   }

   public static String getMapping(TCoreDatasystem dataSystem, String index, String type) {
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.append(index).append("/_mapping/").append(type).append("?pretty");
      ClientInterface clientInterface = GHCAUtils.getInstance().connectToES(dataSystem.getDbip(), dataSystem.getDbport(), dataSystem.getUsername(), AesTool.decrypt(dataSystem.getPassword(), "ghca"));

      String result;
      try {
         result = clientInterface.getClient().executeHttp(stringBuilder.toString(), "get");
      } finally {
         clientInterface.getClient().close();
      }

      return result;
   }

   public static String getIndices(ClientInterface clientInterface) {
      return clientInterface.getClient().executeHttp("_cat/indices?format=json", "get");
   }

   public static String getMapping(ClientInterface clientInterface, String index) {
      return clientInterface.getClient().executeHttp(index + "/_mapping", "get");
   }

   public static Set<String> getFields(ClientInterface clientInterface, String index, String type) {
      String mapping = getMapping(clientInterface, index, type);

      try {
         Set<String> jsonKeySet = getJsonKeySet(mapping, index, type);
         return jsonKeySet;
      } catch (Exception e) {
         log.error("parse json error", e);
         throw new CustomException(ErrCode.DATA_PROCESS_ERROR);
      }
   }

   public static String getMapping(ClientInterface clientInterface, String index, String type) {
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.append(index).append("/_mapping/").append(type).append("?pretty");
      return clientInterface.getClient().executeHttp(stringBuilder.toString(), "get");
   }

   public static Set<String> getJsonKeySet(String jsonStr, String index, String type) {
      if (StringUtils.isBlank(jsonStr)) {
         log.error("json is blank!");
         throw new CustomException(ErrCode.DATA_PROCESS_ERROR);
      } else {
         Set<String> set = new TreeSet();
         JSONObject jsonObject = JSONObject.parseObject(jsonStr).getJSONObject(index).getJSONObject("mappings").getJSONObject(type);
         processMapping(jsonObject, "", set);
         return set;
      }
   }

   private static void processMapping(JSONObject jsonObject, String key, Set<String> set) {
      Object fieldType = jsonObject.get("type");
      if (Objects.isNull(fieldType)) {
         JSONObject jsonObjectProperties = jsonObject.getJSONObject("properties");
         if (Objects.nonNull(jsonObjectProperties)) {
            processMappingJsonObject(jsonObjectProperties, key, set);
         } else {
            processMappingJsonObject(jsonObject, key, set);
         }
      } else if ("nested".equals(fieldType)) {
         JSONObject jsonObjectNested = jsonObject.getJSONObject("properties");
         processMapping(jsonObjectNested, key, set);
      } else {
         String analyzer = jsonObject.getString("analyzer");
         StringBuilder stringBuilder = new StringBuilder();
         stringBuilder.append(key).append("###").append(fieldType);
         if (StringUtils.isNotEmpty(analyzer)) {
            stringBuilder.append(":").append(analyzer);
         }

         set.add(stringBuilder.toString());
      }

   }

   private static void processMappingJsonObject(JSONObject jsonObject, String key, Set<String> set) {
      for(String keyTemp1 : jsonObject.keySet()) {
         JSONObject jsonObjectField = jsonObject.getJSONObject(keyTemp1);
         String keyTemp2 = StringUtils.isBlank(key) ? keyTemp1 : key + "." + keyTemp1;
         processMapping(jsonObjectField, keyTemp2, set);
      }

   }

   public static String queryByPage(ClientInterface clientInterface, String index, String type, int from, int size) {
      StringBuilder stringBuilder1 = new StringBuilder();
      stringBuilder1.append(index).append("/").append(type).append("/").append("_search");
      StringBuilder stringBuilder2 = new StringBuilder();
      stringBuilder2.append("{\"from\":").append(from).append(",\"size\":").append(size).append("}");
      String result = clientInterface.getClient().executeHttp(stringBuilder1.toString(), stringBuilder2.toString(), "post");
      return result;
   }

   public static String getAnalyze(ClientInterface clientInterface, String index, String text, String analyzer) {
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.append("{\"text\":\"").append(text).append("\"");
      if (StringUtils.isNotBlank(analyzer)) {
         stringBuilder.append(",\"analyzer\":\"").append(analyzer).append("\"");
      }

      stringBuilder.append("}");
      String result = clientInterface.getClient().executeHttp(index + "/_analyze", stringBuilder.toString(), "post");
      return result;
   }

   public static String assembleData(String index, String type, String id, String doc) {
      StringBuilder stringBuilder1 = new StringBuilder();
      stringBuilder1.append("{\"update\":{\"_index\":\"").append(index).append("\",\"_type\":\"").append(type).append("\",\"_id\":\"").append(id).append("\"}}\n");
      stringBuilder1.append("{\"doc\":").append(doc).append("}\n");
      return stringBuilder1.toString();
   }

   public static String update(ClientInterface clientInterface, String entity) {
      String result = clientInterface.getClient().executeHttp("/_bulk", entity, "post");
      return result;
   }

   public static void main(String[] args) {
      ClientInterface clientInterface = GHCAUtils.getInstance().connectToES("192.168.2.173", "9205", "elastic", AesTool.decrypt("changeme", "ghca"));
   }
}
