package com.yeejoin.amos.api.householdapi.Utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.api.householdapi.face.model.HouseholdPvApiDto;
import com.yeejoin.amos.api.householdapi.face.orm.houseapi.entity.houseapi.HouseholdPvProducerInfo;
import com.yeejoin.amos.api.householdapi.face.service.impl.HouseholdPvApiServiceImpl;
import com.yeejoin.amos.api.householdapi.face.service.impl.HouseholdPvProducerInfoServiceImpl;
import com.yeejoin.amos.openapi.enums.PVProducerInfoEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.component.cache.Redis;

import java.util.*;

@Component
@Slf4j
public class HouseholdPvUtils {
    private final static String API_REDIS_PREFIX = "HOUSEHOLD_API_CACHE_";
//    @Autowired
//    InfluxDbConnection influxDbConnection;
    @Autowired
    private HouseholdPvProducerInfoServiceImpl householdPvProducerInfoServiceImpl;
    @Autowired
    private HouseholdPvApiServiceImpl householdPvApiServiceImpl;
//    @Autowired
//    private TdEngineUtils tdEngineUtils;

    /**
     * @param code 厂商code
     * @return HashMap<String, Object>   发送请求前的准备 准备header信息
     * @deprecated 根据厂商编码获取厂商的hearer
     */
    public HashMap<String, Object> getHeaderByProducerCode(String code) {
        HashMap<String, Object> hashMap = new HashMap<>();
        HashMap<String, String> hashMaphead = new HashMap<>();
        HouseholdPvProducerInfo householdPvProducerInfo = this.householdPvProducerInfoServiceImpl.queryForHouseholdPvProducerInfoByCode(code);
        String url = householdPvProducerInfo.getProdcerUrl() + householdPvProducerInfo.getTokenUrl();
        hashMap.put("apiurl", householdPvProducerInfo.getProdcerUrl());
        if (PVProducerInfoEnum.GDW.getCode().equals(code)) {
            HashMap<String, String> map = new HashMap<>();
            map.put("account", householdPvProducerInfo.getProdcerAccount());
            map.put("pwd", householdPvProducerInfo.getProdcerPassword());
            String body = JSON.toJSONString(map);
            String response = HttpUtil.createPost(url).body(body).execute().body();
            JSONObject jsonObject = JSON.parseObject(response);
            if (!ObjectUtils.isEmpty(jsonObject.get("data"))) {
                JSONObject jsonObject1 = (JSONObject) jsonObject.get("data");
                hashMaphead.put("token", (String) jsonObject1.get("token"));
                hashMap.put("header", hashMaphead);
            }
        } else if (PVProducerInfoEnum.SH.getCode().equals(code)) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("accountName", householdPvProducerInfo.getProdcerAccount());
            map.put("appId", householdPvProducerInfo.getProdcerAppid());
            map.put("appSecret", householdPvProducerInfo.getProdcerAppsecret());
            map.put("corporationId", householdPvProducerInfo.getCorporationId());
            map.put("accountType", 2);
            String body = JSON.toJSONString(map);
            String response = HttpUtil.createPost(url).body(body).execute().body();
            JSONObject jsonObject = JSON.parseObject(response);
            hashMaphead.put("Authorization", (String) jsonObject.get("data"));
            hashMap.put("header", hashMaphead);
        } else if (PVProducerInfoEnum.JLY.getCode().equals(code)) {
            hashMaphead.put("Content-type", "application/json;charset=UTF-8");
            hashMaphead.put("Authorization", "API " + householdPvProducerInfo.getProdcerAppid());
            hashMaphead.put("Content-MD5", null);
            hashMaphead.put("Date", GoLangHeaderUtils.getGMTTime());
            hashMap.put("header", hashMaphead);
            hashMap.put("appsecret", householdPvProducerInfo.getProdcerAppsecret());
        }
        return hashMap;
    }

    /**
     * @param seq apiId 数据库中维护的的apiId
     * @return String 请求返回的response字符串
     */
    public String gerResponseByAPiID(Long seq) {
        List cacheParams = new ArrayList();
        String respone = "";
        String params = "";
        JSONArray jsonArray = null;
        HouseholdPvApiDto householdPvApiDto = this.householdPvApiServiceImpl.queryBySeq(seq);
        HashMap<String, Object> producerInfo = this.getHeaderByProducerCode(householdPvApiDto.getProducerId());
        String baseurl = (String) producerInfo.get("apiurl");
        HashMap<String, String> headMap = (HashMap<String, String>) producerInfo.get("header");
        String orginalAuthorization = headMap.get("Authorization") + ":";
        String url = baseurl + householdPvApiDto.getApiUrl();
        String appsecret = (String) producerInfo.get("appsecret");
        if (ObjectUtil.isNotEmpty(householdPvApiDto.getDependecyApiId())) {
            String RedisKey = API_REDIS_PREFIX + householdPvApiDto.getDependecyApiId();
            cacheParams = Redis.getRedisTemplate().opsForList().range(RedisKey, 0, -1);
            if (cacheParams.size() > 0) {
                for (int i = 0; i < cacheParams.size(); i++) {
                    JSONObject jsonObject = JSON.parseObject(householdPvApiDto.getParamInfo());
                    if (ObjectUtil.isNotEmpty(householdPvApiDto.getDependApiParamKey())) {
                        jsonObject.put(householdPvApiDto.getDependApiParamKey(), cacheParams.get(i));
                    }
                    params = jsonObject.toJSONString();
                    if (PVProducerInfoEnum.JLY.getCode().equals(householdPvApiDto.getProducerId())) {
                        JLYHeaderMapHandler(params, householdPvApiDto, headMap, orginalAuthorization, appsecret, (String) cacheParams.get(i));
                    }
                    try {
                        Thread.sleep(500);
                        respone = sendRequest(householdPvApiDto.getRequestMethod(), url, params, headMap);
                        jsonArray = handlerResponseByResultResolverule(householdPvApiDto.getResultResolveRule(), respone);
                        handleResponseAndCacheData(String.valueOf(seq), householdPvApiDto.getCacheField(), jsonArray, householdPvApiDto.getMeasurement(),householdPvApiDto.getProducerId());
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        continue;
                    }
                }
            }
        } else {
            if (PVProducerInfoEnum.JLY.getCode().equals(householdPvApiDto.getProducerId())) {
                JLYHeaderMapHandler(params, householdPvApiDto, headMap, orginalAuthorization, appsecret, null);
            }
            respone = sendRequest(householdPvApiDto.getRequestMethod(), url, householdPvApiDto.getParamInfo(), headMap);
            jsonArray = handlerResponseByResultResolverule(householdPvApiDto.getResultResolveRule(), respone);
            handleResponseAndCacheData(String.valueOf(seq), householdPvApiDto.getCacheField(), jsonArray, householdPvApiDto.getMeasurement(),householdPvApiDto.getProducerId());
            if (ObjectUtil.isNotEmpty(householdPvApiDto.getIsPage())) {
                Integer size = getPagesize(householdPvApiDto.getPagesizeResolveRule(), respone);
                for (int i = 1; i < size; i++) {
                    JSONObject jsonObject = JSON.parseObject(householdPvApiDto.getParamInfo());
                    if (ObjectUtil.isNotEmpty(householdPvApiDto.getPageField())) {
                        jsonObject.put(householdPvApiDto.getPageField(), i + 1);
                    }
                    params = jsonObject.toJSONString();
                    if (PVProducerInfoEnum.JLY.getCode().equals(householdPvApiDto.getProducerId())) {
                        JLYHeaderMapHandler(params, householdPvApiDto, headMap, orginalAuthorization, appsecret, null);
                    }
                    respone = sendRequest(householdPvApiDto.getRequestMethod(), url, householdPvApiDto.getParamInfo(), headMap);
                    jsonArray = handlerResponseByResultResolverule(householdPvApiDto.getResultResolveRule(), respone);
                    handleResponseAndCacheData(String.valueOf(seq), householdPvApiDto.getCacheField(), jsonArray, householdPvApiDto.getMeasurement(),householdPvApiDto.getProducerId());
                }
            }

        }
        return respone;
    }

    /**
     * @param resultResovle 请求返回的解析规则 来源与数据库
     * @param response      请求返回的字符串
     * @return 解析后的数据
     */
    public JSONArray handlerResponseByResultResolverule(String resultResovle, String response) {
        JSONObject jsonObject = JSONObject.parseObject(response);
        JSONArray jsonArray = new JSONArray();
        if (ObjectUtil.isNotEmpty(resultResovle)) {
            String[] rules = resultResovle.split(",");
            if (rules.length > 0) {
                for (int i = 0; i < rules.length; i++) {
                    try {
                        jsonObject = (JSONObject) jsonObject.get(rules[i]);
                        if (jsonObject == null) {
                            jsonArray = (JSONArray) jsonObject.get(rules[i]);
                        }
                    } catch (Exception exception) {
                        jsonArray = (JSONArray) jsonObject.get(rules[i]);
                    }
                }
            }
            if (jsonArray.size() == 0) {
                jsonArray.add(jsonObject);
            }
        }
        return jsonArray;
    }

    /**
     * @param seq         apiID
     * @param cacheField  要缓存的字段
     * @param jsonArray   处理后的数据请求
     * @param measurement 要在influxdb中存储的数
     * @describe 该方法用于缓存需要缓存的字段 且将需要入库的数据进行入库
     */
    public void handleResponseAndCacheData(String seq, String cacheField, JSONArray jsonArray, String measurement,String produceID) {
        String apiID = API_REDIS_PREFIX + seq;
        List list = new ArrayList();
        List saveList = new ArrayList();
        if (jsonArray.size() > 0) {
            for (Object o : jsonArray) {
                List<Map<String, Object>> lines = new ArrayList<>();
                Map<String, Object> maps1 = (Map<String, Object>) o;
                LinkedHashMap<String,Object> sortHashMap =new LinkedHashMap<>();
                sortHashMap.put("station_list","station_list."+measurement);
                sortHashMap.put("timestamp",System.currentTimeMillis());
                sortHashMap.put("value",10.1);
                Set<String> keys = maps1.keySet();
                keys.forEach((key) -> {
                    maps1.put(key, ObjectUtils.isEmpty(maps1.get(key)) ? "null" : maps1.get(key).toString());
                });
                if (!ObjectUtils.isEmpty("cacheField")) {
                    list.add(maps1.get(cacheField));
                }
                sortHashMap.put("tags",maps1);
                lines.add(sortHashMap);
//                Map<String, String> maps2 = new HashMap<>();
//                maps2.put("key", UUID.randomUUID().toString());
                if (!ObjectUtils.isEmpty(measurement)) {
//                    influxDbConnection.insert(measurement, maps2, maps1);
                    log.error(JSONObject.toJSONString(lines));
//                    tdEngineUtils.writeDataIntoTdEngine(JSONObject.toJSONString(lines));
                }
            }
        }
//        tdEngineUtils.writeDataIntoTdEngine(lines.stream().map(s -> String.valueOf(s)).toArray(String[]::new));
        if (!ObjectUtils.isEmpty(cacheField)) {
            saveList = Redis.getRedisTemplate().opsForList().range(apiID, 0, -1);
            if (saveList.size() == 0) {
                Redis.getRedisTemplate().opsForList().leftPushAll(apiID, list);
            }
            saveList = Redis.getRedisTemplate().opsForList().range(apiID, 0, -1);
            if (saveList.size() != list.size()) {
                Redis.getRedisTemplate().delete(apiID);
                Redis.getRedisTemplate().opsForList().leftPushAll(apiID, list);
            }
        }
    }

    public String sendRequest(String requestMethod, String url, String params, HashMap<String, String> headMap) {
        String respone = "";
        if (requestMethod.equals("POST")) {
            respone = HttpUtil.createPost(url).headerMap(headMap, false).
                    body(params).execute().body();
        }
        if (requestMethod.equals("GET")) {
            respone = HttpUtil.createGet(url).headerMap(headMap, true).
                    body(params).execute().body();
        }
        return respone;
    }

    /***
     *
     * @param params 参数字符窜
     * @param householdPvApiDto apidto
     * @param headMap header头
     * @param orginalAuthorization 原始的orginalAuthorization
     * @param appsecret  appsecret
     * @param cacheParams  缓存的参数值
     * @desc 锦浪云请求参数及head头处理
     */
    public void JLYHeaderMapHandler(String params, HouseholdPvApiDto householdPvApiDto, HashMap<String, String> headMap, String orginalAuthorization, String appsecret, String cacheParams) {
        if (PVProducerInfoEnum.JLY.getCode().equals(householdPvApiDto.getProducerId())) {
            String contentMD5 = GoLangHeaderUtils.getDigest(params);
            headMap.put("Date", GoLangHeaderUtils.getGMTTime());
            String param = "POST" + "\n" + contentMD5 + "\n" + "application/json" + "\n" + headMap.get("Date") + "\n" + householdPvApiDto.getApiUrl();
            String sign = "";
            try {
                sign = GoLangHeaderUtils.HmacSHA1Encrypt(param, appsecret);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            headMap.put("Content-MD5", contentMD5);
            headMap.put("Authorization", orginalAuthorization + sign);
        }
    }

    public Integer getPagesize(String pageSizeResovle, String response) {
        Integer pageSize = 0;
        String[] rules = pageSizeResovle.split(",");
        JSONObject jsonObject = JSONObject.parseObject(response);
        if (rules.length > 0) {
            for (int i = 0; i < rules.length - 1; i++) {
                jsonObject = (JSONObject) jsonObject.get(rules[i]);
            }
        }
        pageSize = (Integer) jsonObject.get(rules[rules.length - 1]);
        return pageSize;
    }
}
