package com.njcn.prepare.harmonic.service.mysql.Impl.line;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.device.pq.api.LineFeignClient;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.harmonic.pojo.po.day.RStatComassesDPO;
import com.njcn.influx.pojo.po.DataFlicker;
import com.njcn.influx.pojo.po.DataV;
import com.njcn.influx.utils.InfluxDbUtils;
import com.njcn.prepare.harmonic.mapper.mysql.day.RStatComassesDMapper;
import com.njcn.prepare.harmonic.pojo.bo.CalculatedParam;
import com.njcn.prepare.harmonic.service.mysql.line.HarmonicGeneralService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.influxdb.dto.QueryResult;
import org.influxdb.impl.InfluxDBResultMapper;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 稳态综合评估
 * @author xiaoyao
 * @version 1.0.0
 * @createTime 2022/11/3 11:06
 */
@Slf4j
@Service
@AllArgsConstructor
public class HarmonicGeneralServiceImpl extends MppServiceImpl<RStatComassesDMapper, RStatComassesDPO> implements HarmonicGeneralService {

    private final InfluxDbUtils influxDbUtils;

    private final LineFeignClient lineFeignClient;


    @Override
    public void newGeneralData(CalculatedParam calculatedParam) {
        List<RStatComassesDPO> list = new ArrayList<>();
        List<String> lineIdOutList;
        if (CollUtil.isEmpty(calculatedParam.getIdList())){
            List<Overlimit> overLimitList = getAllLineOutData();
            lineIdOutList = overLimitList.stream().map(Overlimit::getId).collect(Collectors.toList());
        }else {
            lineIdOutList = new ArrayList<>(calculatedParam.getIdList());
        }
        Date dateOut = DateUtil.parse(calculatedParam.getDataDate());
        for (String lineId : lineIdOutList){
            RStatComassesDPO rStatComassesDpo = new RStatComassesDPO();
            rStatComassesDpo.setTime(dateOut);
            rStatComassesDpo.setLineId(lineId);
            Map<String, Object> fields = getGeneralData(lineId,calculatedParam.getDataDate());
            if(CollUtil.isNotEmpty(fields)) {
                rStatComassesDpo.setFreqDev1(Objects.isNull(fields.get("freq_dev1")) ? 0.0 : Double.parseDouble(fields.get("freq_dev1").toString()));
                rStatComassesDpo.setFreqDev2(Objects.isNull(fields.get("freq_dev2")) ? 0.0 : Double.parseDouble(fields.get("freq_dev2").toString()));
                rStatComassesDpo.setFreqDev3(Objects.isNull(fields.get("freq_dev3")) ? 0.0 : Double.parseDouble(fields.get("freq_dev3").toString()));
                rStatComassesDpo.setFreqDev4(Objects.isNull(fields.get("freq_dev4")) ? 0.0 : Double.parseDouble(fields.get("freq_dev4").toString()));
                rStatComassesDpo.setFreqDev5(Objects.isNull(fields.get("freq_dev5")) ? 0.0 : Double.parseDouble(fields.get("freq_dev5").toString()));

                rStatComassesDpo.setVuDev1(Objects.isNull(fields.get("vu_dev1")) ? 0.0 : Double.parseDouble(fields.get("vu_dev1").toString()));
                rStatComassesDpo.setVuDev2(Objects.isNull(fields.get("vu_dev2")) ? 0.0 : Double.parseDouble(fields.get("vu_dev2").toString()));
                rStatComassesDpo.setVuDev3(Objects.isNull(fields.get("vu_dev3")) ? 0.0 : Double.parseDouble(fields.get("vu_dev3").toString()));
                rStatComassesDpo.setVuDev4(Objects.isNull(fields.get("vu_dev4")) ? 0.0 : Double.parseDouble(fields.get("vu_dev4").toString()));
                rStatComassesDpo.setVuDev5(Objects.isNull(fields.get("vu_dev5")) ? 0.0 : Double.parseDouble(fields.get("vu_dev5").toString()));

                rStatComassesDpo.setDataPst1(Objects.isNull(fields.get("data_pst1")) ? 0.0 : Double.parseDouble(fields.get("data_pst1").toString()));
                rStatComassesDpo.setDataPst2(Objects.isNull(fields.get("data_pst2")) ? 0.0 : Double.parseDouble(fields.get("data_pst2").toString()));
                rStatComassesDpo.setDataPst3(Objects.isNull(fields.get("data_pst3")) ? 0.0 : Double.parseDouble(fields.get("data_pst3").toString()));
                rStatComassesDpo.setDataPst4(Objects.isNull(fields.get("data_pst4")) ? 0.0 : Double.parseDouble(fields.get("data_pst4").toString()));
                rStatComassesDpo.setDataPst5(Objects.isNull(fields.get("data_pst5")) ? 0.0 : Double.parseDouble(fields.get("data_pst5").toString()));

                rStatComassesDpo.setVUnbalance1(Objects.isNull(fields.get("v_unbalance1")) ? 0.0 : Double.parseDouble(fields.get("v_unbalance1").toString()));
                rStatComassesDpo.setVUnbalance2(Objects.isNull(fields.get("v_unbalance2")) ? 0.0 : Double.parseDouble(fields.get("v_unbalance2").toString()));
                rStatComassesDpo.setVUnbalance3(Objects.isNull(fields.get("v_unbalance3")) ? 0.0 : Double.parseDouble(fields.get("v_unbalance3").toString()));
                rStatComassesDpo.setVUnbalance4(Objects.isNull(fields.get("v_unbalance4")) ? 0.0 : Double.parseDouble(fields.get("v_unbalance4").toString()));
                rStatComassesDpo.setVUnbalance5(Objects.isNull(fields.get("v_unbalance5")) ? 0.0 : Double.parseDouble(fields.get("v_unbalance5").toString()));

                rStatComassesDpo.setVThd1(Objects.isNull(fields.get("v_thd1")) ? 0.0 : Double.parseDouble(fields.get("v_thd1").toString()));
                rStatComassesDpo.setVThd2(Objects.isNull(fields.get("v_thd2")) ? 0.0 : Double.parseDouble(fields.get("v_thd2").toString()));
                rStatComassesDpo.setVThd3(Objects.isNull(fields.get("v_thd3")) ? 0.0 : Double.parseDouble(fields.get("v_thd3").toString()));
                rStatComassesDpo.setVThd4(Objects.isNull(fields.get("v_thd4")) ? 0.0 : Double.parseDouble(fields.get("v_thd4").toString()));
                rStatComassesDpo.setVThd5(Objects.isNull(fields.get("v_thd5")) ? 0.0 : Double.parseDouble(fields.get("v_thd5").toString()));

                rStatComassesDpo.setEvent1(Objects.isNull(fields.get("event1")) ? 0.0 : Double.parseDouble(fields.get("event1").toString()));
                rStatComassesDpo.setEvent2(Objects.isNull(fields.get("event2")) ? 0.0 : Double.parseDouble(fields.get("event2").toString()));
                rStatComassesDpo.setEvent3(Objects.isNull(fields.get("event3")) ? 0.0 : Double.parseDouble(fields.get("event3").toString()));
                rStatComassesDpo.setEvent4(Objects.isNull(fields.get("event4")) ? 0.0 : Double.parseDouble(fields.get("event4").toString()));
                rStatComassesDpo.setEvent5(Objects.isNull(fields.get("event5")) ? 0.0 : Double.parseDouble(fields.get("event5").toString()));
                list.add(rStatComassesDpo);
            }
        }
        if(CollUtil.isNotEmpty(list)){
            this.saveOrUpdateBatchByMultiId(list,50);
        }
    }

    private Map<String, Object> getGeneralData(String lineId, String date){
        InfluxDBResultMapper mapper = new InfluxDBResultMapper();
        BigDecimal hundred = BigDecimal.valueOf(100);
        Map<String, Object> outMap = new HashMap<>();
        String processParam = " and line_id = '"+lineId+"' and time >= '"
                +date+" 00:00:00' and time <= '"+date+" 23:59:59' group by time(1m) fill(none) tz('Asia/Shanghai')";

        String vuDevSql = "select count(vu_dev) from data_v where phasic_type != 'T' and quality_flag = '0' and value_type = 'AVG' and ";
        QueryResult vuDevResult1 = influxDbUtils.query(vuDevSql + "vu_dev >=10" + processParam);
        QueryResult vuDevResult2 = influxDbUtils.query(vuDevSql + "vu_dev <10 and vu_dev >=7" + processParam);
        QueryResult vuDevResult3 = influxDbUtils.query(vuDevSql + "vu_dev <7 and vu_dev >=4" + processParam);
        QueryResult vuDevResult4 = influxDbUtils.query(vuDevSql + "vu_dev <4 and vu_dev >=2" + processParam);
        QueryResult vuDevResult5 = influxDbUtils.query(vuDevSql + "vu_dev <2 and vu_dev >=0" + processParam);
        BigDecimal vuDev1 = BigDecimal.valueOf(mapper.toPOJO(vuDevResult1, DataV.class).size());
        BigDecimal vuDev2 = BigDecimal.valueOf(mapper.toPOJO(vuDevResult2, DataV.class).size());
        BigDecimal vuDev3 = BigDecimal.valueOf(mapper.toPOJO(vuDevResult3, DataV.class).size());
        BigDecimal vuDev4 = BigDecimal.valueOf(mapper.toPOJO(vuDevResult4, DataV.class).size());
        BigDecimal vuDev5 = BigDecimal.valueOf(mapper.toPOJO(vuDevResult5, DataV.class).size());
        BigDecimal vuDevAll = vuDev1.add(vuDev2).add(vuDev3).add(vuDev4).add(vuDev5);
        if (vuDevAll.compareTo(BigDecimal.ZERO)!=0){
            outMap.put("vu_dev1",vuDev1.multiply(hundred).divide(vuDevAll,3, RoundingMode.HALF_UP));
            outMap.put("vu_dev2",vuDev2.multiply(hundred).divide(vuDevAll,3, RoundingMode.HALF_UP));
            outMap.put("vu_dev3",vuDev3.multiply(hundred).divide(vuDevAll,3, RoundingMode.HALF_UP));
            outMap.put("vu_dev4",vuDev4.multiply(hundred).divide(vuDevAll,3, RoundingMode.HALF_UP));
            outMap.put("vu_dev5",vuDev5.multiply(hundred).divide(vuDevAll,3, RoundingMode.HALF_UP));
        }

        String freqDevSql = "select count(freq_dev) from data_v where phasic_type != 'T' and quality_flag = '0' and value_type = 'AVG' and ";
        QueryResult freqDevResult1 = influxDbUtils.query(freqDevSql + "freq_dev >=0.3" + processParam);
        QueryResult freqDevResult2 = influxDbUtils.query(freqDevSql + "freq_dev <0.3 and freq_dev >=0.2" + processParam);
        QueryResult freqDevResult3 = influxDbUtils.query(freqDevSql + "freq_dev <0.2 and freq_dev >=0.1" + processParam);
        QueryResult freqDevResult4 = influxDbUtils.query(freqDevSql + "freq_dev <0.1 and freq_dev >=0.05" + processParam);
        QueryResult freqDevResult5 = influxDbUtils.query(freqDevSql + "freq_dev <0.05 and freq_dev >=0" + processParam);
        BigDecimal freqDev1 = BigDecimal.valueOf(mapper.toPOJO(freqDevResult1, DataV.class).size());
        BigDecimal freqDev2 = BigDecimal.valueOf(mapper.toPOJO(freqDevResult2, DataV.class).size());
        BigDecimal freqDev3 = BigDecimal.valueOf(mapper.toPOJO(freqDevResult3, DataV.class).size());
        BigDecimal freqDev4 = BigDecimal.valueOf(mapper.toPOJO(freqDevResult4, DataV.class).size());
        BigDecimal freqDev5 = BigDecimal.valueOf(mapper.toPOJO(freqDevResult5, DataV.class).size());
        BigDecimal freqDevAll = freqDev1.add(freqDev2).add(freqDev3).add(freqDev4).add(freqDev5);
        if (freqDevAll.compareTo(BigDecimal.ZERO)!=0){
            outMap.put("freq_dev1",freqDev1.multiply(hundred).divide(freqDevAll,3, RoundingMode.HALF_UP));
            outMap.put("freq_dev2",freqDev2.multiply(hundred).divide(freqDevAll,3, RoundingMode.HALF_UP));
            outMap.put("freq_dev3",freqDev3.multiply(hundred).divide(freqDevAll,3, RoundingMode.HALF_UP));
            outMap.put("freq_dev4",freqDev4.multiply(hundred).divide(freqDevAll,3, RoundingMode.HALF_UP));
            outMap.put("freq_dev5",freqDev5.multiply(hundred).divide(freqDevAll,3, RoundingMode.HALF_UP));
        }

        String vThdSql = "select count(v_thd) from data_v where phasic_type != 'T' and quality_flag = '0' and value_type = 'CP95' and ";
        QueryResult vThdResult1 = influxDbUtils.query(vThdSql + "v_thd >=6" + processParam);
        QueryResult vThdResult2 = influxDbUtils.query(vThdSql + "v_thd <6 and v_thd >=4" + processParam);
        QueryResult vThdResult3 = influxDbUtils.query(vThdSql + "v_thd <4 and v_thd >=2" + processParam);
        QueryResult vThdResult4 = influxDbUtils.query(vThdSql + "v_thd <2 and v_thd >=1" + processParam);
        QueryResult vThdResult5 = influxDbUtils.query(vThdSql + "v_thd <1 and v_thd >=0" + processParam);
        BigDecimal vThd1 = BigDecimal.valueOf(mapper.toPOJO(vThdResult1, DataV.class).size());
        BigDecimal vThd2 = BigDecimal.valueOf(mapper.toPOJO(vThdResult2, DataV.class).size());
        BigDecimal vThd3 = BigDecimal.valueOf(mapper.toPOJO(vThdResult3, DataV.class).size());
        BigDecimal vThd4 = BigDecimal.valueOf(mapper.toPOJO(vThdResult4, DataV.class).size());
        BigDecimal vThd5 = BigDecimal.valueOf(mapper.toPOJO(vThdResult5, DataV.class).size());
        BigDecimal vThdAll = vThd1.add(vThd2).add(vThd3).add(vThd4).add(vThd5);
        if (vThdAll.compareTo(BigDecimal.ZERO)!=0){
            outMap.put("v_thd1",vThd1.multiply(hundred).divide(vThdAll,3, RoundingMode.HALF_UP));
            outMap.put("v_thd2",vThd2.multiply(hundred).divide(vThdAll,3, RoundingMode.HALF_UP));
            outMap.put("v_thd3",vThd3.multiply(hundred).divide(vThdAll,3, RoundingMode.HALF_UP));
            outMap.put("v_thd4",vThd4.multiply(hundred).divide(vThdAll,3, RoundingMode.HALF_UP));
            outMap.put("v_thd5",vThd5.multiply(hundred).divide(vThdAll,3, RoundingMode.HALF_UP));
        }

        String vUnbalanceSql="select count(v_unbalance) from data_v where phasic_type != 'T' and quality_flag = '0' and value_type = 'CP95' and ";
        QueryResult vUnbalanceResult1 = influxDbUtils.query(vUnbalanceSql + "v_unbalance >=4" + processParam);
        QueryResult vUnbalanceResult2 = influxDbUtils.query(vUnbalanceSql + "v_unbalance <4 and v_unbalance >=2" + processParam);
        QueryResult vUnbalanceResult3 = influxDbUtils.query(vUnbalanceSql + "v_unbalance <2 and v_unbalance >=1" + processParam);
        QueryResult vUnbalanceResult4 = influxDbUtils.query(vUnbalanceSql + "v_unbalance <1 and v_unbalance >=0.5" + processParam);
        QueryResult vUnbalanceResult5 = influxDbUtils.query(vUnbalanceSql + "v_unbalance <0.5 and v_unbalance >=0" + processParam);
        BigDecimal vUnbalance1 = BigDecimal.valueOf(mapper.toPOJO(vUnbalanceResult1, DataV.class).size());
        BigDecimal vUnbalance2 = BigDecimal.valueOf(mapper.toPOJO(vUnbalanceResult2, DataV.class).size());
        BigDecimal vUnbalance3 = BigDecimal.valueOf(mapper.toPOJO(vUnbalanceResult3, DataV.class).size());
        BigDecimal vUnbalance4 = BigDecimal.valueOf(mapper.toPOJO(vUnbalanceResult4, DataV.class).size());
        BigDecimal vUnbalance5 = BigDecimal.valueOf(mapper.toPOJO(vUnbalanceResult5, DataV.class).size());
        BigDecimal vUnbalanceAll = vUnbalance1.add(vUnbalance2).add(vUnbalance3).add(vUnbalance4).add(vUnbalance5);
        if (vUnbalanceAll.compareTo(BigDecimal.ZERO)!=0){
            outMap.put("v_unbalance1",vUnbalance1.multiply(hundred).divide(vUnbalanceAll,3, RoundingMode.HALF_UP));
            outMap.put("v_unbalance2",vUnbalance2.multiply(hundred).divide(vUnbalanceAll,3, RoundingMode.HALF_UP));
            outMap.put("v_unbalance3",vUnbalance3.multiply(hundred).divide(vUnbalanceAll,3, RoundingMode.HALF_UP));
            outMap.put("v_unbalance4",vUnbalance4.multiply(hundred).divide(vUnbalanceAll,3, RoundingMode.HALF_UP));
            outMap.put("v_unbalance5",vUnbalance5.multiply(hundred).divide(vUnbalanceAll,3, RoundingMode.HALF_UP));
        }

        String pstSql="select count(pst) from data_flicker where phasic_type != 'T' and quality_flag = '0' and ";
        QueryResult pstResult1 = influxDbUtils.query(pstSql + "pst >=0.8" + processParam);
        QueryResult pstResult2 = influxDbUtils.query(pstSql + "pst <0.8 and pst >=0.6" + processParam);
        QueryResult pstResult3 = influxDbUtils.query(pstSql + "pst <0.6 and pst >=0.4" + processParam);
        QueryResult pstResult4 = influxDbUtils.query(pstSql + "pst <0.4 and pst >=0.2" + processParam);
        QueryResult pstResult5 = influxDbUtils.query(pstSql + "pst <0.2 and pst >=0" + processParam);
        BigDecimal pst1 = BigDecimal.valueOf(mapper.toPOJO(pstResult1, DataFlicker.class).size());
        BigDecimal pst2 = BigDecimal.valueOf(mapper.toPOJO(pstResult2, DataFlicker.class).size());
        BigDecimal pst3 = BigDecimal.valueOf(mapper.toPOJO(pstResult3, DataFlicker.class).size());
        BigDecimal pst4 = BigDecimal.valueOf(mapper.toPOJO(pstResult4, DataFlicker.class).size());
        BigDecimal pst5 = BigDecimal.valueOf(mapper.toPOJO(pstResult5, DataFlicker.class).size());
        BigDecimal pstAll = pst1.add(pst2).add(pst3).add(pst4).add(pst5);
        if (pstAll.compareTo(BigDecimal.ZERO)!=0){
            outMap.put("data_plt1",pst1.multiply(hundred).divide(pstAll,3, RoundingMode.HALF_UP));
            outMap.put("data_plt2",pst2.multiply(hundred).divide(pstAll,3, RoundingMode.HALF_UP));
            outMap.put("data_plt3",pst3.multiply(hundred).divide(pstAll,3, RoundingMode.HALF_UP));
            outMap.put("data_plt4",pst4.multiply(hundred).divide(pstAll,3, RoundingMode.HALF_UP));
            outMap.put("data_plt5",pst5.multiply(hundred).divide(pstAll,3, RoundingMode.HALF_UP));
        }

        if (!CollUtil.isEmpty(outMap)){
            outMap.put("event1",100.0);
            outMap.put("event2",0.0);
            outMap.put("event3",0.0);
            outMap.put("event4",0.0);
            outMap.put("event5",0.0);
        }
        return outMap;
    }

    private List<Overlimit> getAllLineOutData() {
        return lineFeignClient.getAllLineOverLimit("harmonic-boot","").getData();
    }
}
