package com.njcn.csharmonic.handler;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.github.tocrhz.mqtt.annotation.MqttSubscribe;
import com.github.tocrhz.mqtt.annotation.NamedValue;
import com.github.tocrhz.mqtt.annotation.Payload;
import com.github.tocrhz.mqtt.publisher.MqttPublisher;
import com.njcn.csdevice.api.CsLineFeignClient;
import com.njcn.csdevice.api.CsLineTopologyFeignClient;
import com.njcn.csdevice.api.DevCapacityFeignClient;
import com.njcn.csdevice.pojo.vo.AppTopologyDiagramVO;
import com.njcn.csharmonic.param.CommonStatisticalQueryParam;
import com.njcn.csharmonic.param.FrequencyStatisticalQueryParam;
import com.njcn.csharmonic.pojo.dto.RealTimeDataDTO;
import com.njcn.csharmonic.pojo.vo.CsRtDataVO;
import com.njcn.csharmonic.pojo.vo.CsWarnDescVO;
import com.njcn.csharmonic.pojo.vo.ThdDataVO;
import com.njcn.csharmonic.service.CsEventPOService;
import com.njcn.csharmonic.service.ILineTargetService;
import com.njcn.csharmonic.service.StableDataService;
import com.njcn.csharmonic.service.TemperatureService;
import com.njcn.influx.pojo.dto.StatisticalDataDTO;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.system.api.CsStatisticalSetFeignClient;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.system.pojo.po.EleEpdPqd;
import com.njcn.zlevent.api.FileFeignClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author xuyang
 * @version 1.0.0
 * @date 2023年06月10日 09:41
 */
@Slf4j
@Component
@AllArgsConstructor
public class MqttMessageHandler {

    private final MqttPublisher publisher;
    private final ILineTargetService lineTargetService;
    private final CsStatisticalSetFeignClient csStatisticalSetFeignClient;
    private final StableDataService stableDataService;
    private final RedisUtil redisUtil;
    private final TemperatureService temperatureService;
    private final DevCapacityFeignClient devCapacityFeignClient;
    private final DecimalFormat df = new DecimalFormat("#0.000");
    private final FileFeignClient fileFeignClient;
    private final CsEventPOService csEventPOService;
    private final CsLineTopologyFeignClient csLineTopologyClient;
    private final CsLineFeignClient csLineFeignClient;
    private final DicDataFeignClient dicDataFeignClient;

    /**
     * 实时数据应答
     */
    @MqttSubscribe(value = "/zl/askRtData/{pageId}", qos = 1)
    public void responseRtData(String topic, @NamedValue("pageId") String pageId, MqttMessage message, @Payload String payload) {
        List<CsRtDataVO> list = lineTargetService.getLineData(pageId);
        Gson gson = new Gson();
        publisher.send("/zl/rtData/" + pageId, gson.toJson(list), 1, false);
    }

    @MqttSubscribe(value = "/zl/askTemperData/{devId}", qos = 1)
    public void responseTemperData(String topic, @NamedValue("devId") String devId, MqttMessage message, @Payload String payload) {
        List<StatisticalDataDTO> statisticalDataDTOS = temperatureService.queryTemperature(devId);
        statisticalDataDTOS.stream().forEach(temp -> {
            temp.setClDid(getCldidName(temp.getClDid()));
        });
        Gson gson = new Gson();
        publisher.send("/zl/TemperData/" + devId, gson.toJson(statisticalDataDTOS), 1, false);
    }


    /**
     * 物联平台的组态实时数据调试
     */
    @MqttSubscribe(value = "/zl/askCSConfigRtData/{pageId}", qos = 1)
    public void responseCSConfigRtData(String topic, @NamedValue("pageId") String pageId, MqttMessage message, @Payload String payload) {
        List<String> lineIdList = Arrays.stream(payload.substring(1, payload.length() - 1).split(","))
                .map(String::trim)
                .collect(Collectors.toList());
        List<CsRtDataVO> lineData = lineTargetService.getLineDataNew(pageId);
        List<CsRtDataVO> collect = lineData.stream().filter(temp -> (!CollectionUtils.isEmpty(lineIdList)) && lineIdList.contains(temp.getLineId())).collect(Collectors.toList());
        RealTimeDataDTO recallReplyDTO = new RealTimeDataDTO();
        recallReplyDTO.setCode(200);
        recallReplyDTO.setMessage(JSONObject.toJSONString(collect));
        Gson gson = new Gson();
        publisher.send("/zl/csConfigRtData/" + pageId, gson.toJson(recallReplyDTO), 1, false);
    }

    @MqttSubscribe(value = "/zl/askCSConfigWarnData/{pageId}", qos = 1)
    public void responseCSConfigWarnData(String topic, @NamedValue("pageId") String pageId, MqttMessage message, @Payload String payload) {
        List<String> lineIdList = Arrays.stream(payload.substring(1, payload.length() - 1).split(","))
                .map(String::trim)
                .collect(Collectors.toList());
        // 目前暂且查最近的60条记录
        List<CsWarnDescVO> csWarnDescVOList = csEventPOService.getEventDesc(lineIdList);
        RealTimeDataDTO recallReplyDTO = new RealTimeDataDTO();
        recallReplyDTO.setCode(200);
        recallReplyDTO.setMessage(JSONObject.toJSONString(csWarnDescVOList));
        Gson gson = new Gson();
        publisher.send("/zl/TemperData/" + pageId, gson.toJson(recallReplyDTO), 1, false);
    }

    /**
     * 实时数据应答
     */
    @MqttSubscribe(value = "/zl/askDevData/{devId}/{typeId}", qos = 1)
    public void responseTopoDataByType(String topic, @NamedValue("devId") String devId, @NamedValue("typeId") String typeId, MqttMessage message, @Payload String payload) {
        String topoDataJson = redisUtil.getStringByKey(devId + "#" + typeId);
        if (StringUtils.isEmpty(topoDataJson)) {
            List<ThdDataVO> result = new ArrayList<>();
            List<ThdDataVO> tempList = new ArrayList<>();

            //1.查询拓扑图配置的指标:拓扑图扑图配置：7677f94c749dedaff30f911949cbd724
            List<EleEpdPqd> data = csStatisticalSetFeignClient.queryStatisticalSelect(Collections.singletonList(typeId)).getData();
            data.forEach(temp -> {
                if (Objects.nonNull(temp.getHarmStart()) && Objects.nonNull(temp.getHarmEnd())) {
                    FrequencyStatisticalQueryParam frequencyStatisticalQueryParam = new FrequencyStatisticalQueryParam();
                    frequencyStatisticalQueryParam.setDevId(devId);
                    frequencyStatisticalQueryParam.setStatisticalId(temp.getId());
                    frequencyStatisticalQueryParam.setValueType("AVG");
                    frequencyStatisticalQueryParam.setFrequencyStart(temp.getHarmStart());
                    frequencyStatisticalQueryParam.setFrequencyEnd(temp.getHarmEnd());
                    List<ThdDataVO> thdDataVOList = stableDataService.QuerySqlData(frequencyStatisticalQueryParam);
                    tempList.addAll(thdDataVOList);
                } else {
                    CommonStatisticalQueryParam commonStatisticalQueryParam = new CommonStatisticalQueryParam();
                    commonStatisticalQueryParam.setDevId(devId);
                    commonStatisticalQueryParam.setStatisticalId(temp.getId());
                    commonStatisticalQueryParam.setValueType("AVG");
                    List<ThdDataVO> listFuture = stableDataService.queryFisrtCommonStatistical(commonStatisticalQueryParam);
                    tempList.addAll(listFuture);
                }
            });

            //过滤T相
            List<ThdDataVO> m = tempList.stream().filter(temp -> Objects.equals(temp.getPhase(), "T")).collect(Collectors.toList());
            m.stream().forEach(temp -> {
                Stream.of("A", "B", "C").forEach(phase -> {
                    ThdDataVO thdDataVO = new ThdDataVO();
                    BeanUtils.copyProperties(temp, thdDataVO);
                    thdDataVO.setPhase(phase);
                    result.add(thdDataVO);
                });
            });
            //如果是基础数据则添加拓扑图的数据
            if (Objects.equals("fc8c86dbc3f2d9810f5cd8f53c295415", typeId)) {
                List<ThdDataVO> apfRmsI = tempList.stream().filter(temp -> Objects.equals(temp.getStatisticalName(), "Apf_RmsI_TolOut(A)")).collect(Collectors.toList());

                List<DictData> dictData = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.LINE_POSITION.getCode()).getData();
                Map<String, DictData> codeToDictData = dictData.stream().collect(Collectors.toMap(DictData::getId, Function.identity()));
                //添加拓扑图上自定义的指标
                //根据设备id查询拓扑图
                AppTopologyDiagramVO vo = csLineTopologyClient.queryTopologyDiagram(devId).getData();
                vo.getAppsLineTopologyDiagramPO().forEach(item -> {
                    String linePositionCode = codeToDictData.get(item.getLinePostion()).getCode();
                    if (Objects.equals(linePositionCode, DicDataEnum.OUTPUT_SIDE.getCode())) {
                        //输出侧
                        if (item.getTarget() != null && !item.getTarget().isEmpty()) {
                            List<ThdDataVO> l1 = new ArrayList<>();
                            //根据指标查询
                            List<EleEpdPqd> data1 = csStatisticalSetFeignClient.queryStatisticalSelect(Collections.singletonList(item.getTarget())).getData();
                            data1.forEach(temp -> {
                                CommonStatisticalQueryParam commonStatisticalQueryParam = new CommonStatisticalQueryParam();
                                commonStatisticalQueryParam.setDevId(devId);
                                commonStatisticalQueryParam.setStatisticalId(temp.getId());
                                commonStatisticalQueryParam.setValueType("AVG");
                                List<ThdDataVO> listFuture = stableDataService.queryFisrtCommonStatistical(commonStatisticalQueryParam);
                                l1.addAll(listFuture);
                            });
                            Map<String, List<ThdDataVO>> collect3 = l1.stream().collect(Collectors.groupingBy(ThdDataVO::getLineId));
                            collect3.forEach((k, v) -> {
                                if (!CollectionUtil.isEmpty(v)) {
                                    double asDouble = v.stream().mapToDouble(ThdDataVO::getStatisticalData).average().getAsDouble();
                                    ThdDataVO thdDataVO = new ThdDataVO();
                                    BeanUtils.copyProperties(v.get(0), thdDataVO);
                                    thdDataVO.setStatisticalData(Double.valueOf(df.format(asDouble)));
                                    thdDataVO.setPhase("avg");
                                    result.add(thdDataVO);
                                }
                            });
                        } else {
                            Map<String, List<ThdDataVO>> collect2 = apfRmsI.stream().collect(Collectors.groupingBy(ThdDataVO::getLineId));
                            collect2.forEach((k, v) -> {
                                if (!CollectionUtil.isEmpty(v)) {
                                    double asDouble = v.stream().mapToDouble(ThdDataVO::getStatisticalData).average().getAsDouble();
                                    ThdDataVO thdDataVO = new ThdDataVO();
                                    BeanUtils.copyProperties(v.get(0), thdDataVO);
                                    thdDataVO.setStatisticalData(Double.valueOf(df.format(asDouble)));
                                    thdDataVO.setPhase("avg");
                                    result.add(thdDataVO);
                                }
                            });
                        }
                    } else if (Objects.equals(linePositionCode, DicDataEnum.GRID_SIDE.getCode())) {
                        //电网侧
                        if (item.getTarget() != null && !item.getTarget().isEmpty()) {
                            //根据指标查询
                            List<ThdDataVO> l1 = new ArrayList<>();
                            //根据指标查询
                            List<EleEpdPqd> data1 = csStatisticalSetFeignClient.queryStatisticalSelect(Collections.singletonList(item.getTarget())).getData();
                            data1.forEach(temp -> {
                                CommonStatisticalQueryParam commonStatisticalQueryParam = new CommonStatisticalQueryParam();
                                commonStatisticalQueryParam.setDevId(devId);
                                commonStatisticalQueryParam.setStatisticalId(temp.getId());
                                commonStatisticalQueryParam.setValueType("AVG");
                                List<ThdDataVO> listFuture = stableDataService.queryFisrtCommonStatistical(commonStatisticalQueryParam);
                                l1.addAll(listFuture);
                            });
                            Map<String, List<ThdDataVO>> collect3 = l1.stream().collect(Collectors.groupingBy(ThdDataVO::getLineId));
                            collect3.forEach((k, v) -> {
                                if (!CollectionUtil.isEmpty(v)) {
                                    double asDouble = v.stream().mapToDouble(ThdDataVO::getStatisticalData).average().getAsDouble();
                                    ThdDataVO thdDataVO = new ThdDataVO();
                                    BeanUtils.copyProperties(v.get(0), thdDataVO);
                                    thdDataVO.setStatisticalData(Double.valueOf(df.format(asDouble)));
                                    thdDataVO.setPhase("avg");
                                    result.add(thdDataVO);
                                }
                            });
                        } else {
                            List<ThdDataVO> apfThdISys = tempList.stream().filter(temp -> Objects.equals(temp.getStatisticalName(), "Apf_ThdA_Sys(%)")).collect(Collectors.toList());
                            Map<String, List<ThdDataVO>> collect4 = apfThdISys.stream().collect(Collectors.groupingBy(ThdDataVO::getLineId));
                            collect4.forEach((k, v) -> {
                                if (!CollectionUtil.isEmpty(v)) {
                                    double asDouble = v.stream().mapToDouble(ThdDataVO::getStatisticalData).average().getAsDouble();
                                    ThdDataVO thdDataVO = new ThdDataVO();
                                    BeanUtils.copyProperties(v.get(0), thdDataVO);
                                    thdDataVO.setStatisticalData(Double.valueOf(df.format(asDouble)));
                                    thdDataVO.setPhase("avg");
                                    result.add(thdDataVO);

                                }
                            });
                        }
                    } else if (Objects.equals(linePositionCode, DicDataEnum.LOAD_SIDE.getCode())) {
                        //负载侧
                        if (item.getTarget() != null && !item.getTarget().isEmpty()) {
                            //根据指标查询
                            List<ThdDataVO> l1 = new ArrayList<>();
                            //根据指标查询
                            List<EleEpdPqd> data1 = csStatisticalSetFeignClient.queryStatisticalSelect(Collections.singletonList(item.getTarget())).getData();
                            data1.forEach(temp -> {
                                CommonStatisticalQueryParam commonStatisticalQueryParam = new CommonStatisticalQueryParam();
                                commonStatisticalQueryParam.setDevId(devId);
                                commonStatisticalQueryParam.setStatisticalId(temp.getId());
                                commonStatisticalQueryParam.setValueType("AVG");
                                List<ThdDataVO> listFuture = stableDataService.queryFisrtCommonStatistical(commonStatisticalQueryParam);
                                l1.addAll(listFuture);
                            });
                            Map<String, List<ThdDataVO>> collect3 = l1.stream().collect(Collectors.groupingBy(ThdDataVO::getLineId));
                            collect3.forEach((k, v) -> {
                                if (!CollectionUtil.isEmpty(v)) {
                                    double asDouble = v.stream().mapToDouble(ThdDataVO::getStatisticalData).average().getAsDouble();
                                    ThdDataVO thdDataVO = new ThdDataVO();
                                    BeanUtils.copyProperties(v.get(0), thdDataVO);
                                    thdDataVO.setStatisticalData(Double.valueOf(df.format(asDouble)));
                                    thdDataVO.setPhase("avg");
                                    result.add(thdDataVO);
                                }
                            });
                        } else {
                            List<ThdDataVO> apfThdI = tempList.stream().filter(temp -> Objects.equals(temp.getStatisticalName(), "Apf_ThdA_Load(%)")).collect(Collectors.toList());
                            Map<String, List<ThdDataVO>> collect3 = apfThdI.stream().collect(Collectors.groupingBy(ThdDataVO::getLineId));
                            collect3.forEach((k, v) -> {
                                if (!CollectionUtil.isEmpty(v)) {
                                    double asDouble = v.stream().mapToDouble(ThdDataVO::getStatisticalData).average().getAsDouble();
                                    ThdDataVO thdDataVO = new ThdDataVO();
                                    BeanUtils.copyProperties(v.get(0), thdDataVO);
                                    thdDataVO.setStatisticalData(Double.valueOf(df.format(asDouble)));
                                    thdDataVO.setPhase("avg");
                                    result.add(thdDataVO);
                                }
                            });
                        }
                    }
                });
                Double capacity = devCapacityFeignClient.getDevCapacity(devId).getData();
                apfRmsI.forEach(temp -> {
                    ThdDataVO thdDataVO = new ThdDataVO();
                    BeanUtils.copyProperties(temp, thdDataVO);
                    thdDataVO.setUnit("%");
                    thdDataVO.setStatisticalName("load_Rate");
                    thdDataVO.setAnotherName("负载率");
                    if (capacity <= 0) {
                        thdDataVO.setStatisticalData(3.1415926);
                    } else {
                        double v = temp.getStatisticalData() * 100 / capacity;
                        thdDataVO.setStatisticalData(Double.valueOf(df.format(v)));
                    }
                    result.add(thdDataVO);
                });
            }

            List<ThdDataVO> notM = tempList.stream().filter(temp -> !Objects.equals(temp.getPhase(), "T")).collect(Collectors.toList());
            result.addAll(notM);
            Gson gson = new Gson();
            topoDataJson = gson.toJson(result);
            redisUtil.saveByKeyWithExpire(devId + "#" + typeId, (Object) topoDataJson, 30L);
        }
        publisher.send("/zl/devData/" + devId + "/" + typeId, topoDataJson, 1, false);
    }

    public String getCldidName(String cldid) {

        switch (cldid) {
            case "0":
                return "主模块";
            case "1":
                return "APF模块 1";
            case "2":
                return "APF模块 2";
            case "3":
                return "APF模块 3";
            case "4":
                return "APF模块 4";
            case "5":
                return "APF模块 5";
            case "6":
                return "APF模块 6";
            case "7":
                return "APF模块 7";
            case "8":
                return "APF模块 8";
            case "9":
                return "APF模块 9";
            case "10":
                return "APF模块 10";
            default:
                break;
        }
        return "";
    }

//    class TaskWithResult implements Callable<List<ThdDataVO>> {
//        private CommonStatisticalQueryParam commonStatisticalQueryParam;
//
//        public TaskWithResult(CommonStatisticalQueryParam commonStatisticalQueryParam) {
//            this.commonStatisticalQueryParam = commonStatisticalQueryParam;
//        }
//
//        /**
//         * 任务的具体过程，一旦任务传给ExecutorService的submit方法，则该方法自动在一个线程上执行。
//         *
//         * @return
//         * @throws Exception
//         */
//        @Override
//        public List<ThdDataVO> call() throws Exception {
//            List<ThdDataVO> thdDataVOList = new ArrayList<>();
//            thdDataVOList = stableDataService.queryFisrtCommonStatistical(commonStatisticalQueryParam);
//            return thdDataVOList;
//        }
//    }

    /**
     * 处理补召数据
     */
    @MqttSubscribe(value = "/makeUpData/{nDid}/{lineId}", qos = 1)
    public void responseRtData(String topic, @NamedValue("nDid") String nDid, @NamedValue("lineId") String lineId, MqttMessage message, @Payload String payload) {
        //下载文件
        fileFeignClient.downloadMakeUpFile(nDid);
    }

}
