package com.njcn.harmonic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.dto.SimpleDTO;
import com.njcn.device.biz.commApi.CommLineClient;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.pms.api.PmsGeneralDeviceInfoClient;
import com.njcn.device.pms.pojo.dto.PmsGeneralDeviceDTO;
import com.njcn.device.pms.pojo.param.PmsDeviceInfoParam;
import com.njcn.device.pq.api.GeneralDeviceInfoClient;
import com.njcn.device.pq.api.LineFeignClient;
import com.njcn.device.pq.api.UserLedgerFeignClient;
import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.biz.pojo.dto.PollutionLineDTO;
import com.njcn.device.pq.pojo.dto.PollutionParamDTO;
import com.njcn.device.pq.pojo.param.DeviceInfoParam;
import com.njcn.device.pq.pojo.po.LineDetail;
import com.njcn.harmonic.mapper.RStatComassesDMapper;
import com.njcn.harmonic.pojo.dto.ComAssessDTO;
import com.njcn.harmonic.pojo.po.PQSComAssesPO;
import com.njcn.harmonic.pojo.po.day.RStatComassesDPO;
import com.njcn.harmonic.pojo.vo.ComAssessVO;
import com.njcn.harmonic.service.ComAssessService;
import com.njcn.harmonic.utils.HarmonicComAssesUtil;
import com.njcn.supervision.pojo.param.user.UserReportParam;
import com.njcn.supervision.pojo.vo.user.UserLedgerVO;
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 lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @version 1.0.0
 * @author: chenchao
 * @date: 2022/04/21 10:03
 */
@Service
@AllArgsConstructor
public class ComAssessServiceImpl extends ServiceImpl<RStatComassesDMapper, RStatComassesDPO> implements ComAssessService {

    private final GeneralDeviceInfoClient generalDeviceInfoClient;
    private final HarmonicComAssesUtil comAssesUtil;
    private final LineFeignClient lineFeignClient;
    private final CommTerminalGeneralClient commTerminalGeneralClient;
    private final PmsGeneralDeviceInfoClient pmsGeneralDeviceInfoClient;
    private final CommLineClient commLineClient;
    private final DicDataFeignClient dicDataFeignClient;
    private final UserLedgerFeignClient userLedgerFeignClient;

    @Override
    public List<ComAssessVO> getComAccessData(DeviceInfoParam.BusinessParam comAccessParam) {
        List<ComAssessVO> comAssessVOList = new ArrayList<>();
        List<String> lineList = new ArrayList<>();
        //监测点信息
        List<PollutionLineDTO> lineInfo = new ArrayList<>();

        String systemType = commTerminalGeneralClient.isPqOrPms().getData();
        if (systemType.equals("pq")) {
            List<UserLedgerVO> userLedgerVOList = userLedgerFeignClient.selectUserList(new UserReportParam()).getData();
            Map<String, UserLedgerVO> userLedgerVOMap = userLedgerVOList.stream().collect(Collectors.toMap(UserLedgerVO::getId, Function.identity()));

            //按部门分类的实际运行终端综合信息
            List<GeneralDeviceDTO> deviceDataList = generalDeviceInfoClient.getPracticalRunDeviceInfo(comAccessParam).getData();
            deviceDataList.forEach(dept -> lineList.addAll(dept.getLineIndexes()));
            //查询所有信息
            List<PQSComAssesPO> comAccessData = getComAccessData(lineList, comAccessParam.getSearchBeginTime(), comAccessParam.getSearchEndTime());

            //按变电站分类的实际运行终端综合信息
            if (!CollectionUtils.isEmpty(deviceDataList)) {
                for (GeneralDeviceDTO dept : deviceDataList) {
                    if (CollectionUtils.isEmpty(dept.getLineIndexes())) {
                        continue;
                    }

                    List<LineDetail> lineDetailList = lineFeignClient.getLineDetail(dept.getLineIndexes()).getData();
                    List<ComAssessVO> children = new ArrayList<>();
                    if (CollUtil.isNotEmpty(lineDetailList)) {
                        List<LineDetail> userLedgerList = lineDetailList.stream().filter(it -> StrUtil.isNotBlank(it.getObjId())).collect(Collectors.toList());
                        List<LineDetail> powerLedgerList = lineDetailList.stream().filter(it -> StrUtil.isBlank(it.getObjId())).collect(Collectors.toList());

                        if (CollUtil.isNotEmpty(userLedgerList)) {
                            Map<String, List<LineDetail>> objMap = userLedgerList.stream().collect(Collectors.groupingBy(LineDetail::getObjId));
                            objMap.forEach((obj, list) -> {
                                ComAssessVO comAssessVO = new ComAssessVO();
                                if (userLedgerVOMap.containsKey(obj)) {
                                    List<ComAssessDTO> childrenDTOS = new ArrayList<>();
                                    UserLedgerVO userLedgerVO = userLedgerVOMap.get(obj);
                                    comAssessVO.setId(userLedgerVO.getId());
                                    comAssessVO.setName(userLedgerVO.getProjectName());
                                    List<String> lineIds = list.stream().map(LineDetail::getId).collect(Collectors.toList());
                                    List<PQSComAssesPO> collect = comAccessData.stream().filter(x -> lineIds.contains(x.getLineId())).collect(Collectors.toList());
                                    setResults(collect, childrenDTOS);
                                    float allComAss = comAssesUtil.getAllComAss(childrenDTOS);
                                    String lv = getLevel(allComAss);
                                    comAssessVO.setMonitors(list.size());
                                    comAssessVO.setData(allComAss);
                                    comAssessVO.setLevel(lv);
                                    children.add(comAssessVO);
                                }
                            });
                        }

                        if (CollUtil.isNotEmpty(powerLedgerList)) {
                            List<String> ids = powerLedgerList.stream().map(LineDetail::getId).collect(Collectors.toList());
                            PollutionParamDTO paramDTO = new PollutionParamDTO();
                            paramDTO.setLineList(ids);
                            lineInfo = lineFeignClient.getLineInfo(paramDTO).getData();
                            Map<String, List<PollutionLineDTO>> map = lineInfo.stream()
                                    .sorted(Comparator.comparing(PollutionLineDTO::getSubstationSort))
                                    .collect(Collectors.groupingBy(
                                            PollutionLineDTO::getSubstationId,
                                            LinkedHashMap::new,
                                            Collectors.toList()
                                    ));
                            List<ComAssessDTO> childrenDTOS = new ArrayList<>();
                            map.forEach((sub,list) -> {
                                //获取变电站信息
                                ComAssessVO child = new ComAssessVO();
                                child.setName(list.get(0).getSubstation());
                                child.setMonitors(list.size());
                                //监测点id
                                List<String> lineIds = list.stream().map(PollutionLineDTO::getId).collect(Collectors.toList());
                                List<PQSComAssesPO> collect = comAccessData.stream().filter(x -> lineIds.contains(x.getLineId())).collect(Collectors.toList());
                                setResults(collect, childrenDTOS);
                                float allComAss = comAssesUtil.getAllComAss(childrenDTOS);
                                String lv = getLevel(allComAss);
                                child.setData(allComAss);
                                child.setLevel(lv);
                                children.add(child);
                            });
                        }
                    }
                    ComAssessVO comAssessVO = new ComAssessVO();
                    comAssessVO.setName(dept.getName());
                    comAssessVO.setMonitors(dept.getLineIndexes().size());
                    List<PQSComAssesPO> collect = comAccessData.stream().filter(x -> dept.getLineIndexes().contains(x.getLineId())).collect(Collectors.toList());
                    List<ComAssessDTO> dtos = new ArrayList<>();
                    setResults(collect, dtos);
                    float allComAss = comAssesUtil.getAllComAss(dtos);
                    String lv = getLevel(allComAss);
                    comAssessVO.setData(allComAss);
                    comAssessVO.setLevel(lv);
                    comAssessVO.setChildren(children);
                    comAssessVOList.add(comAssessVO);
                }
            }
          //  List<ComAssessVO> list = comAssessVOList.stream().sorted(Comparator.comparing(ComAssessVO::getData).reversed()).collect(Collectors.toList());
            return comAssessVOList;
        } else {
            DictData dictData = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.RUN.getCode(), DicDataTypeEnum.LINE_STATE.getCode()).getData();
            PmsDeviceInfoParam param = new PmsDeviceInfoParam();
            param.setDeptIndex(comAccessParam.getDeptIndex());
            SimpleDTO simpleDTO = new SimpleDTO();
            simpleDTO.setId(dictData.getId());
            param.setMonitorState(Stream.of(simpleDTO).collect(Collectors.toList()));
            param.setStatisticalType(new SimpleDTO());
            List<PmsGeneralDeviceDTO> deviceDataList = pmsGeneralDeviceInfoClient.getPmsDeviceInfoWithInOrg(param).getData();
            deviceDataList.forEach(dept -> {
                lineList.addAll(dept.getMonitorIdList());
            });
            if (!CollectionUtils.isEmpty(lineList)) {

                lineInfo = commLineClient.getLineInfo(lineList).getData();
            }
            Map<String, List<PollutionLineDTO>> map = lineInfo.stream().collect(Collectors.groupingBy(PollutionLineDTO::getSubstationId));
            //查询所有信息
            List<PQSComAssesPO> comAccessData = getComAccessData(lineList, comAccessParam.getSearchBeginTime(), comAccessParam.getSearchEndTime());

            //按变电站分类的实际运行终端综合信息
            if (!CollectionUtils.isEmpty(deviceDataList)) {
                for (PmsGeneralDeviceDTO dept : deviceDataList) {
                    if (CollectionUtils.isEmpty(dept.getMonitorIdList())) {
                        continue;
                    }
                    ComAssessVO comAssessVO = new ComAssessVO();
                    comAssessVO.setName(dept.getName());
                    comAssessVO.setId(dept.getIndex());
                    comAssessVO.setMonitors(dept.getMonitorIdList().size());

                    List<ComAssessDTO> childrenDTOS = new ArrayList<>();
                    List<ComAssessVO> children = new ArrayList<>();
                    if (!CollectionUtils.isEmpty(dept.getPowerrIdList())) {
                        dept.getPowerrIdList().forEach(sub -> {
                            //获取变电站信息
                            List<PollutionLineDTO> l1 = map.get(sub);
                            ComAssessVO child = new ComAssessVO();
                            child.setName(l1.get(0).getSubstation());
                            child.setMonitors(l1.size());
                            //监测点id
                            List<String> lineIds = l1.stream().map(PollutionLineDTO::getId).collect(Collectors.toList());
                            List<PQSComAssesPO> collect = comAccessData.stream().filter(x -> lineIds.contains(x.getLineId())).collect(Collectors.toList());
                            setResults(collect, childrenDTOS);
                            float allComAss = comAssesUtil.getAllComAss(childrenDTOS);
                            String lv = getLevel(allComAss);
                            child.setData(allComAss);
                            child.setLevel(lv);
                            child.setId(l1.get(0).getSubstationId());
                            children.add(child);
                        });
                    }
                    List<String> lineIds = dept.getMonitorIdList();
                    List<PQSComAssesPO> collect = comAccessData.stream().filter(x -> lineIds.contains(x.getLineId())).collect(Collectors.toList());
                    List<ComAssessDTO> dtos = new ArrayList<>();
                    setResults(collect, dtos);
                    float allComAss = comAssesUtil.getAllComAss(dtos);
                    String lv = getLevel(allComAss);
                    comAssessVO.setData(allComAss);
                    comAssessVO.setLevel(lv);
                    comAssessVO.setChildren(children);
                    comAssessVOList.add(comAssessVO);
                }
                ;

            }
            List<ComAssessVO> list = comAssessVOList.stream().sorted(Comparator.comparing(ComAssessVO::getData).reversed()).collect(Collectors.toList());

            return list;
        }
    }

    //设置保留四位小数
    private void setResults(List<PQSComAssesPO> pqsComAssesPOS, List<ComAssessDTO> comAssessDTOS) {
        for (int i = 0; i < pqsComAssesPOS.size(); i++) {
            float v1 = new BigDecimal(pqsComAssesPOS.get(i).getVuDev1()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            ComAssessDTO comAssessDTO = new ComAssessDTO();
            comAssessDTO.setVuDev1(v1);
            float v2 = new BigDecimal(pqsComAssesPOS.get(i).getVuDev2()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVuDev2(v2);
            float v3 = new BigDecimal(pqsComAssesPOS.get(i).getVuDev3()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVuDev3(v3);
            float v4 = new BigDecimal(pqsComAssesPOS.get(i).getVuDev4()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVuDev4(v4);
            float v5 = new BigDecimal(pqsComAssesPOS.get(i).getVuDev5()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVuDev5(v5);
            float f1 = new BigDecimal(pqsComAssesPOS.get(i).getFreqDev1()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setFreqDev1(f1);
            float f2 = new BigDecimal(pqsComAssesPOS.get(i).getFreqDev2()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setFreqDev2(f2);
            float f3 = new BigDecimal(pqsComAssesPOS.get(i).getFreqDev3()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setFreqDev3(f3);
            float f4 = new BigDecimal(pqsComAssesPOS.get(i).getFreqDev4()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setFreqDev4(f4);
            float f5 = new BigDecimal(pqsComAssesPOS.get(i).getFreqDev5()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setFreqDev5(f5);
            float d1 = new BigDecimal(pqsComAssesPOS.get(i).getDataPlt1()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setDataPlT1(d1);
            float d2 = new BigDecimal(pqsComAssesPOS.get(i).getDataPlt2()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setDataPlT2(d2);
            float d3 = new BigDecimal(pqsComAssesPOS.get(i).getDataPlt3()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setDataPlT3(d3);
            float d4 = new BigDecimal(pqsComAssesPOS.get(i).getDataPlt4()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setDataPlT4(d4);
            float d5 = new BigDecimal(pqsComAssesPOS.get(i).getDataPlt5()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setDataPlT5(d5);
            float vu1 = new BigDecimal(pqsComAssesPOS.get(i).getVUnbalance1()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVUnbalance1(vu1);
            float vu2 = new BigDecimal(pqsComAssesPOS.get(i).getVUnbalance2()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVUnbalance2(vu2);
            float vu3 = new BigDecimal(pqsComAssesPOS.get(i).getVUnbalance3()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVUnbalance3(vu3);
            float vu4 = new BigDecimal(pqsComAssesPOS.get(i).getVUnbalance4()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVUnbalance4(vu4);
            float vu5 = new BigDecimal(pqsComAssesPOS.get(i).getVUnbalance5()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVUnbalance5(vu5);
            float vt1 = new BigDecimal(pqsComAssesPOS.get(i).getVThd1()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVTHD1(vt1);
            float vt2 = new BigDecimal(pqsComAssesPOS.get(i).getVThd2()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVTHD2(vt2);
            float vt3 = new BigDecimal(pqsComAssesPOS.get(i).getVThd3()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVTHD3(vt3);
            float vt4 = new BigDecimal(pqsComAssesPOS.get(i).getVThd4()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVTHD4(vt4);
            float vt5 = new BigDecimal(pqsComAssesPOS.get(i).getVThd5()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setVTHD5(vt5);
            float e1 = new BigDecimal(pqsComAssesPOS.get(i).getEvent1()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setEvent1(e1);
            float e2 = new BigDecimal(pqsComAssesPOS.get(i).getEvent2()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setEvent2(e2);
            float e3 = new BigDecimal(pqsComAssesPOS.get(i).getEvent3()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setEvent3(e3);
            float e4 = new BigDecimal(pqsComAssesPOS.get(i).getEvent4()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setEvent4(e4);
            float e5 = new BigDecimal(pqsComAssesPOS.get(i).getEvent5()).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();
            comAssessDTO.setEvent5(e5);
            comAssessDTOS.add(comAssessDTO);
        }
    }

    //获取综合评估等级
    private String getLevel(float synDatas) {
        if (synDatas == 3.14159f) {
            return "（暂无数据）";
        }
        if (0 <= synDatas && synDatas < 2) {
            return "极差";
        } else if (2 <= synDatas && synDatas < 3) {
            return "较差";
        } else if (3 <= synDatas && synDatas < 4) {
            return "合格";
        } else if (4 <= synDatas && synDatas < 4.5) {
            return "良好";
        } else {
            return "优质";
        }
    }


    /**
     * influxDB查询综合评估相关信息
     * 返回每个监测点在时间段的各指标平均数
     *
     * @param lineIndexes
     * @param searchBeginTime
     * @param searchEndTime
     */
    private List<PQSComAssesPO> getComAccessData(List<String> lineIndexes, String searchBeginTime, String searchEndTime) {
        List<PQSComAssesPO> avgCount = this.baseMapper.getAvgCount(lineIndexes,
                DateUtil.beginOfDay(DateUtil.parse(searchBeginTime)).toString(),
                DateUtil.beginOfDay(DateUtil.parse(searchEndTime)).toString());
        if (CollUtil.isNotEmpty(avgCount)) {
            return avgCount;
        }
        return new ArrayList<>();


//        //组装sql语句
//        StringBuilder builder = new StringBuilder();
//        builder.append("MEAN(vu_dev1)AS vu_dev1, MEAN(vu_dev2)AS vu_dev2, MEAN(vu_dev3)AS vu_dev3, MEAN(vu_dev4)AS vu_dev4, MEAN(vu_dev5)AS vu_dev5, MEAN(freq_dev1)AS freq_dev1, MEAN(freq_dev2)AS freq_dev2, MEAN(freq_dev3)AS freq_dev3, MEAN(freq_dev4)AS freq_dev4, MEAN(freq_dev5)AS freq_dev5, MEAN(data_plt1)AS data_plt1, MEAN(data_plt2)AS data_plt2, MEAN(data_plt3)AS data_plt3, MEAN(data_plt4)AS data_plt4, MEAN(data_plt5)AS data_plt5, MEAN(v_unbalance1)AS v_unbalance1, MEAN(v_unbalance2)AS v_unbalance2, MEAN(v_unbalance3)AS v_unbalance3, MEAN(v_unbalance4)AS v_unbalance4, MEAN(v_unbalance5)AS v_unbalance5, MEAN(v_thd1)AS v_thd1, MEAN(v_thd2)AS v_thd2, MEAN(v_thd3)AS v_thd3, MEAN(v_thd4)AS v_thd4, MEAN(v_thd5)AS v_thd5, MEAN(event1)AS event1, MEAN(event2)AS event2, MEAN(event3)AS event3, MEAN(event4)AS event4, MEAN(event5)AS event5");
//        StringBuffer string = new StringBuffer();
//        string.append(InfluxDBPublicParam.TIME + " >= '" + searchBeginTime + InfluxDBPublicParam.START_TIME + "' and " + InfluxDBPublicParam.TIME + " <= '" + searchEndTime + InfluxDBPublicParam.END_TIME + "' and ");
//        for (int i = 0; i < lineIndexes.size(); i++) {
//            if (lineIndexes.size() - i != 1) {
//                string.append(InfluxDBPublicParam.LINE_ID + "='").append(lineIndexes.get(i)).append("' or ");
//            } else {
//                string.append(InfluxDBPublicParam.LINE_ID + "='").append(lineIndexes.get(i)).append("' group by " + InfluxDBPublicParam.LINE_ID);
//            }
//        }
//        //sql语句
//        String sql = "SELECT "+ builder +" FROM "+InfluxDBPublicParam.PQS_COMASSES+" WHERE " + string + InfluxDBPublicParam.TIME_ZONE;
//        //结果集
//        System.out.println("--------------->>>>"+sql);
//        QueryResult result = influxDbUtils.query(sql);
//        //结果集映射到对象中
//        InfluxDBResultMapper resultMapper = new InfluxDBResultMapper();
//        List<PQSComAssesPO> pqsComAssesPOS = resultMapper.toPOJO(result, PQSComAssesPO.class);
//        return pqsComAssesPOS;
    }


}
