package com.njcn.prepare.harmonic.service.mysql.upload.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.common.pojo.constant.BizParamConstant;
import com.njcn.device.biz.commApi.CommLineClient;
import com.njcn.device.biz.pojo.dto.DeptGetChildrenMoreDTO;
import com.njcn.device.biz.pojo.dto.LineDTO;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.pq.pojo.po.RStatIntegrityD;
import com.njcn.harmonic.pojo.po.upload.PmsRunStatisticM;
import com.njcn.harmonic.pojo.po.upload.PmsRunStatisticY;
import com.njcn.harmonic.pojo.po.upload.RUploadPointStatisticalDataD;
import com.njcn.prepare.harmonic.enums.UploadEnum;
import com.njcn.prepare.harmonic.mapper.mysql.day.RStatIntegrityDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.upload.PmsRunStatisticDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.upload.RUploadPointStatisticalDataDMapper;
import com.njcn.prepare.harmonic.pojo.bo.CalculatedParam;
import com.njcn.harmonic.pojo.po.upload.PmsRunStatisticD;
import com.njcn.prepare.harmonic.service.mysql.upload.IPmsRunStatisticMService;
import com.njcn.prepare.harmonic.service.mysql.upload.IPmsRunStatisticYService;
import com.njcn.prepare.harmonic.service.mysql.upload.IRUploadPointStatisticalDataDService;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.api.DictTreeFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.enums.DicTreeEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.system.pojo.po.SysDicTreePO;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;
import com.njcn.user.pojo.vo.PvTerminalTreeVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

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

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 主配网监测点统计数据-日表 服务实现类
 * </p>
 *
 * @author xuyang
 * @since 2023-12-07
 */
@Service
@RequiredArgsConstructor
public class RUploadPointStatisticalDataDServiceImpl extends MppServiceImpl<RUploadPointStatisticalDataDMapper, RUploadPointStatisticalDataD> implements IRUploadPointStatisticalDataDService {

    private final DeptFeignClient deptFeignClient;

    private final RStatIntegrityDMapper rStatIntegrityDMapper;

    private final DictTreeFeignClient dictTreeFeignClient;

    private final DicDataFeignClient dicDataFeignClient;

    private final CommLineClient commLineClient;
    private final PmsRunStatisticDMapper runStatisticDMapper;
    private final IPmsRunStatisticMService runStatisticMService;
    private final IPmsRunStatisticYService runStatisticYService;

    /**
     * 此算法用于计算底层数据，方便国网数据上送
     * 1.表中存储所有单位，没有数据的暂时设置为0
     * 2.r_operating_index_d表中获取终端、监测点个数
     * 3.r_stat_integrity_d表中获取数据应收数、实收数
     */
    @Override
    public void insertPointStatisticalDataDay(CalculatedParam<DeptGetChildrenMoreDTO> calculatedParam) {


        List<RUploadPointStatisticalDataD> result = new ArrayList<>();
        //获取省级单位id
        Dept data = deptFeignClient.getRootDept().getData();
        String provinceId = deptFeignClient.getDepSonIdByDeptId(data.getId()).getData().get(0);
        Dept dept = deptFeignClient.getDeptById(provinceId).getData();

        //用于存放不同对象类型的测点id集合
        Map<String, List<String>> mapKey = new HashMap<>();
        this.classifyObj(mapKey);

        //所属场站与对象类型存在联系
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.Station_Type.getCode()).getData();
        Map<String, DictData> dictDataMap = dictDataList.stream().collect(Collectors.toMap(DictData::getCode, Function.identity()));

        //获取所有单位
        List<PvTerminalTreeVO> deptList = deptFeignClient.allDeptList().getData();
        Map<String,PvTerminalTreeVO> deptMap = deptList.stream().collect(Collectors.toMap(PvTerminalTreeVO::getCode,Function.identity()));

        //获取数据完整性相关数据
        List<RStatIntegrityD> integrityDataList = getStatIntegrityData(calculatedParam.getDataDate());

        //下面先从表里获取在运测点相关数据，当表里没数据时候再从接口获取
        //首先获取pms_run_statistic表是否存在执行日期的数据
        List<PmsRunStatisticD> pmsRunStatisticsListD = runStatisticDMapper.selectList(new LambdaQueryWrapper<PmsRunStatisticD>().eq(PmsRunStatisticD::getStatisticDate, calculatedParam.getDataDate()));
        Map<String, PmsRunStatisticD> pmsRunStatisticMap = pmsRunStatisticsListD.stream().collect(Collectors.toMap(PmsRunStatisticD::getDeptId, Function.identity()));

        List<LineDTO> lineDTOList = new ArrayList<>();
        if (pmsRunStatisticMap.containsKey(dept.getCode())) {
            String runMonitorIds = pmsRunStatisticMap.get(dept.getCode()).getRunMonitorIds();
            if(StrUtil.isNotBlank(runMonitorIds)){
                List<String> monitorIds = CollectionUtil.toList(runMonitorIds.split(StrUtil.COMMA));
                lineDTOList = commLineClient.getLineDetailBatch(monitorIds).getData();
            }
        }
        //过滤出在线的监测点
        List<LineDTO> finalLineDTOList = lineDTOList;

        //筛选国网上送监测点
        List<DeptGetChildrenMoreDTO> deptAll = calculatedParam.getIdList();
        deptAll.forEach(item -> {
            //跳过全国这个单位
            if (Objects.equals(Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_1.getCode()), item.getDeptLevel())) {
                return;
            }


            //筛选出国网

            //存放在运监测点的集合
            List<LineDevGetDTO> newBaseList;

            //存放在线监测点的集合
            List<LineDevGetDTO> newOnlineBaseList;

            //存放在运监测点集合
            List<String> runMonitorIds;

            //存放在线监测点集合
            List<String> onlineMonitorIds;

            //存放在运装置的集合
            List<String> upDevIds;


            if (CollectionUtil.isEmpty(pmsRunStatisticsListD)) {
                //非正常流程
                newBaseList = item.getLineBaseList().stream().filter(o -> Objects.equals(o.getIsUpToGrid(), 1)).collect(toList());
                runMonitorIds = newBaseList.stream().map(LineDevGetDTO::getPointId).distinct().collect(toList());
                upDevIds = newBaseList.stream().map(LineDevGetDTO::getDevId).distinct().collect(toList());
            } else {
                if(pmsRunStatisticMap.containsKey(item.getUnitId())){
                    PmsRunStatisticD pmsRunStatisticD = pmsRunStatisticMap.get(item.getUnitId());
                    if(StrUtil.isNotBlank(pmsRunStatisticD.getRunMonitorIds())){
                        List<String> temIds = Arrays.stream(pmsRunStatisticD.getRunMonitorIds().split(StrUtil.COMMA)).collect(toList());
                        newBaseList = finalLineDTOList.stream().filter(o -> temIds.contains(o.getLineId())).map(it -> {
                            LineDevGetDTO lineDevGetDTO = new LineDevGetDTO();
                            lineDevGetDTO.setPointId(it.getLineId());
                            lineDevGetDTO.setDevId(it.getDevId());
                            lineDevGetDTO.setObjType(it.getObjType());
                            return lineDevGetDTO;
                        }).collect(toList());
                        runMonitorIds = newBaseList.stream().map(LineDevGetDTO::getPointId).distinct().collect(toList());
                        upDevIds = newBaseList.stream().map(LineDevGetDTO::getDevId).distinct().collect(toList());
                    }else{
                        newBaseList = item.getLineBaseList().stream().filter(o -> Objects.equals(o.getIsUpToGrid(), 1)).collect(toList());
                        upDevIds = newBaseList.stream().map(LineDevGetDTO::getDevId).distinct().collect(toList());
                        runMonitorIds = newBaseList.stream().map(LineDevGetDTO::getPointId).distinct().collect(toList());
                    }
                }else{
                    newBaseList = item.getLineBaseList().stream().filter(o -> Objects.equals(o.getIsUpToGrid(), 1)).collect(toList());
                    upDevIds = newBaseList.stream().map(LineDevGetDTO::getDevId).distinct().collect(toList());
                    runMonitorIds = newBaseList.stream().map(LineDevGetDTO::getPointId).distinct().collect(toList());
                }

            }


            List<RStatIntegrityD> runMonitorIntegrity = integrityDataList.stream().filter(it -> newBaseList.stream().map(LineDevGetDTO::getPointId).collect(toList()).contains(it.getLineIndex())).collect(toList());
            //获取在线监测点
            List<RStatIntegrityD> rStatIntegrityDList = runMonitorIntegrity.stream().filter(me -> me.getRealTime() > 0).collect(Collectors.toList());
            onlineMonitorIds = rStatIntegrityDList.stream().map(RStatIntegrityD::getLineIndex).distinct().collect(Collectors.toList());
            List<String> finalOnlineMonitorIds = onlineMonitorIds;
            newOnlineBaseList = newBaseList.stream().filter(i-> finalOnlineMonitorIds.contains(i.getPointId())).collect(Collectors.toList());


            List<String> finalUpDevIds = upDevIds;
            List<String> finalRunMonitorIds = runMonitorIds;
            mapKey.forEach((key, val) -> {
                RUploadPointStatisticalDataD rUploadPointStatisticalDataD = new RUploadPointStatisticalDataD();

                int due = runMonitorIntegrity.stream().mapToInt(RStatIntegrityD::getDueTime).sum();
                int real = runMonitorIntegrity.stream().mapToInt(RStatIntegrityD::getRealTime).sum();
                rUploadPointStatisticalDataD.setExpectCollectNum(due);
                rUploadPointStatisticalDataD.setActualCollectNum(real);
                rUploadPointStatisticalDataD.setRunTerminalNum(finalUpDevIds.size());
                rUploadPointStatisticalDataD.setRunMonitorNum(finalRunMonitorIds.size());
                rUploadPointStatisticalDataD.setOnlineMonitorNum(onlineMonitorIds.size());
                double rate = runMonitorIntegrity.size() == 0 ? 0d : BigDecimal.valueOf(rUploadPointStatisticalDataD.getOnlineMonitorNum() * 100.0 / rUploadPointStatisticalDataD.getRunMonitorNum()).setScale(4, RoundingMode.HALF_UP).doubleValue();
                rUploadPointStatisticalDataD.setOnlineMonitorRate(rate>100 ? 100:rate);
                if (due == 0 || real == 0) {
                    rUploadPointStatisticalDataD.setDataFullRate(BigDecimal.valueOf(0).setScale(4, RoundingMode.HALF_UP).doubleValue());
                } else {
                    double inVal = BigDecimal.valueOf(real * 100.0 / due).setScale(4, RoundingMode.HALF_UP).doubleValue();
                    rUploadPointStatisticalDataD.setDataFullRate(inVal>100?100:inVal);
                }

                rUploadPointStatisticalDataD.setId(IdUtil.simpleUUID());
                rUploadPointStatisticalDataD.setProvinceId(dept.getCode());
                rUploadPointStatisticalDataD.setProvinceName(dept.getName());
                rUploadPointStatisticalDataD.setStatisticalDate(calculatedParam.getDataDate());
                rUploadPointStatisticalDataD.setComputeDate(calculatedParam.getDataDate());
                rUploadPointStatisticalDataD.setStatisticalType(UploadEnum.STATISTICAL_TYPE_03.getCode());
                rUploadPointStatisticalDataD.setUploadStatus(Integer.parseInt(UploadEnum.UPLOAD_STATUS_0.getCode()));
                //fixme         主配网标识文档中没有,先随便定义一个,后期调整
                rUploadPointStatisticalDataD.setDistributionFlag(UploadEnum.DISTRIBUTION_FLAG_01.getCode());
                //fixme over
                judgeLevel(item.getDeptLevel(), rUploadPointStatisticalDataD, item.getUnitId(), item.getUnitName(), deptList, deptMap);



                List<LineDevGetDTO> keyItem;
                if(key.equals("9999")){
                    //其他
                    keyItem = newOnlineBaseList.stream().filter(o -> !val.contains(o.getObjType())).collect(toList());
                }else {
                    keyItem = newOnlineBaseList.stream().filter(o -> val.contains(o.getObjType())).collect(toList());
                }
                long pointCount = keyItem.stream().map(LineDevGetDTO::getPointId).distinct().count();
                rUploadPointStatisticalDataD.setStationMonitorNum((int) pointCount);

                switch (key) {
                    case "2100":
                        rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Trans_Sub.getCode()).getId());
                        break;
                    case "1200":
                        rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Converter.getCode()).getId());
                        break;
                    case "1300":
                        rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Ele_Railways.getCode()).getId());
                        break;
                    case "1401":
                        rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Wind_Farms.getCode()).getId());
                        break;
                    case "1402":
                        rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Power_Station.getCode()).getId());
                        break;
                    case "2300":
                        rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Smelting_Load.getCode()).getId());
                        break;
                    case "2400":
                        rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Imp_Users.getCode()).getId());
                        break;
                    case "9999":
                        rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Station_Other.getCode()).getId());
                        break;
                }
                result.add(rUploadPointStatisticalDataD);
            });

        });


        if (CollectionUtil.isNotEmpty(result)) {
            //查询数据如果有数据,将data_id置为null,这样就保留之前的唯一id
            LambdaQueryWrapper<RUploadPointStatisticalDataD> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(RUploadPointStatisticalDataD::getStatisticalDate, calculatedParam.getDataDate());
            List<RUploadPointStatisticalDataD> oldData = this.list(lambdaQueryWrapper);
            if (CollectionUtil.isNotEmpty(oldData)) {
                result.forEach(it -> it.setId(null));
            }
            this.saveOrUpdateBatchByMultiId(result);
        }
    }




    @Override
    public void insertPointStatisticalDataMonth(CalculatedParam<DeptGetChildrenMoreDTO> calculatedParam) {
        //开始月份
        String beginMonth = DateUtil.format(DateUtil.beginOfMonth(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_MONTH_PATTERN)), DatePattern.NORM_MONTH_PATTERN);
        //起始时间
        String startTime = DateUtil.format(DateUtil.beginOfMonth(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)), DatePattern.NORM_DATE_PATTERN);
        //结束时间
        String endTime = DateUtil.format(DateUtil.endOfMonth(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)), DatePattern.NORM_DATE_PATTERN);
        List<PmsRunStatisticM> pmsRunStatistic = runStatisticMService.selectListByDate(startTime, endTime,calculatedParam.getDataDate());
        Map<String, PmsRunStatisticM> pmsRunStatisticMap = pmsRunStatistic.stream().collect(Collectors.toMap(PmsRunStatisticM::getDeptId, Function.identity()));

        //所属场站与对象类型存在联系
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.Station_Type.getCode()).getData();
        Map<String, DictData> dictDataMap = dictDataList.stream().collect(Collectors.toMap(DictData::getCode, Function.identity()));

        //用于存放不同对象类型的测点id集合
        Map<String, List<String>> mapKey = new HashMap<>();
        this.classifyObj(mapKey);

        //获取所有单位
        List<PvTerminalTreeVO> deptList = deptFeignClient.allDeptList().getData();
        Map<String, PvTerminalTreeVO> deptMap = deptList.stream().collect(Collectors.toMap(PvTerminalTreeVO::getCode,Function.identity()));


        List<PvTerminalTreeVO> pvTerminalTreeVOList = deptList.stream().filter(it->it.getLevel() == 2).collect(toList());

        QueryWrapper<RStatIntegrityD> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("line_index,sum(due_time) due_time,sum(real_time) real_time,(sum(real_time)/sum(due_time)) as integrityData")
                .between("time_id",startTime,endTime).groupBy("line_index");
        List<RStatIntegrityD> rStatIntegrityDList = rStatIntegrityDMapper.selectList(queryWrapper);


        List<RUploadPointStatisticalDataD> resultPO = new ArrayList<>();
        pmsRunStatisticMap.forEach((deptId,item)->{
            PvTerminalTreeVO dept = deptMap.get(deptId);

            //跳过全国这个单位
            if (Objects.equals(Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_1.getCode()), dept.getLevel())) {
                return;
            }
            List<String> runMonitorIds = Arrays.stream(StrUtil.isNotBlank(item.getRunMonitorIds())?item.getRunMonitorIds().split(StrUtil.COMMA):new String[]{}).collect(toList());
            List<String> onlineMonitorIds = Arrays.stream(StrUtil.isNotBlank(item.getOnlineMonitorIds())?item.getOnlineMonitorIds().split(StrUtil.COMMA):new String[]{}).collect(toList());
            List<String> runDevIds = Arrays.stream(StrUtil.isNotBlank(item.getRunDevIds())?item.getRunDevIds().split(StrUtil.COMMA):new String[]{}).collect(toList());

            List<LineDTO> lineDTOList;
            if(CollUtil.isNotEmpty(onlineMonitorIds)) {
                lineDTOList = commLineClient.getLineDetailBatch(onlineMonitorIds).getData();
            }else {
                lineDTOList = new ArrayList<>();
            }

            List<RStatIntegrityD> deptRStatIntegrityDList = rStatIntegrityDList.stream().filter(it->runMonitorIds.contains(it.getLineIndex())).collect(toList());
            int due = deptRStatIntegrityDList.stream().mapToInt(RStatIntegrityD::getDueTime).sum();
            int real = deptRStatIntegrityDList.stream().mapToInt(RStatIntegrityD::getRealTime).sum();

            mapKey.forEach((key, val) -> {

                RUploadPointStatisticalDataD rUploadPointStatisticalDataD = new RUploadPointStatisticalDataD();

                rUploadPointStatisticalDataD.setId(IdUtil.simpleUUID());
                rUploadPointStatisticalDataD.setProvinceId(pvTerminalTreeVOList.get(0).getCode());
                rUploadPointStatisticalDataD.setProvinceName(pvTerminalTreeVOList.get(0).getName());
                rUploadPointStatisticalDataD.setStatisticalDate(beginMonth);
                rUploadPointStatisticalDataD.setComputeDate(calculatedParam.getDataDate());
                rUploadPointStatisticalDataD.setStatisticalType(UploadEnum.STATISTICAL_TYPE_02.getCode());
                rUploadPointStatisticalDataD.setUploadStatus(Integer.parseInt(UploadEnum.UPLOAD_STATUS_0.getCode()));
                //fixme         主配网标识文档中没有,先随便定义一个,后期调整
                rUploadPointStatisticalDataD.setDistributionFlag(UploadEnum.DISTRIBUTION_FLAG_01.getCode());
                //fixme over
                judgeLevel(dept.getLevel(), rUploadPointStatisticalDataD, dept.getCode(), dept.getName(), deptList, deptMap);

                rUploadPointStatisticalDataD.setRunTerminalNum(runDevIds.size());
                rUploadPointStatisticalDataD.setRunMonitorNum(runMonitorIds.size());
                rUploadPointStatisticalDataD.setOnlineMonitorNum(onlineMonitorIds.size());

                assDataRate(deptRStatIntegrityDList,due,real,rUploadPointStatisticalDataD);
                assStationType(key,val,lineDTOList,dictDataMap,rUploadPointStatisticalDataD);
                resultPO.add(rUploadPointStatisticalDataD);
            });
        });

       this.saveOrUpdateBatchByMultiId(resultPO);
    }



/*    @Override
    public void insertPointStatisticalDataMonth(CalculatedParam<DeptGetChildrenMoreDTO> calculatedParam) {
        //开始月份
        String beginMonth = DateUtil.format(DateUtil.beginOfMonth(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_MONTH_PATTERN)), DatePattern.NORM_MONTH_PATTERN);
        //起始时间
        String startTime = DateUtil.format(DateUtil.beginOfMonth(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)), DatePattern.NORM_DATE_PATTERN);
        //结束时间
        String endTime = DateUtil.format(DateUtil.endOfMonth(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)), DatePattern.NORM_DATE_PATTERN);
        List<PmsRunStatisticM> pmsRunStatistic = runStatisticMService.selectListByDate(startTime, endTime,calculatedParam.getDataDate());
        Map<String, PmsRunStatisticM> pmsRunStatisticMap = pmsRunStatistic.stream().collect(Collectors.toMap(PmsRunStatisticM::getDeptId, Function.identity()));
        //数据集
        List<RUploadPointStatisticalDataD> list = this.baseMapper.pointStatisticalMonthData(beginMonth, startTime, endTime, "02");
        dataProcessing(calculatedParam, list, pmsRunStatisticMap, BizParamConstant.STAT_BIZ_MONTH);
    }*/

    @Override
    public void insertPointStatisticalDataYear(CalculatedParam<DeptGetChildrenMoreDTO> calculatedParam) {
        //开始年
        String beginMonth = DateUtil.format(DateUtil.beginOfYear(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_YEAR_PATTERN)), DatePattern.NORM_YEAR_PATTERN);
        //起始时间
        String startTime = DateUtil.format(DateUtil.beginOfYear(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)), DatePattern.NORM_DATE_PATTERN);
        //结束时间
        String endTime = DateUtil.format(DateUtil.endOfYear(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)), DatePattern.NORM_DATE_PATTERN);
        List<PmsRunStatisticY> pmsRunStatistic = runStatisticYService.selectListByDate(startTime, endTime,calculatedParam.getDataDate());
        Map<String, PmsRunStatisticY> pmsRunStatisticMap = pmsRunStatistic.stream().collect(Collectors.toMap(PmsRunStatisticY::getDeptId, Function.identity()));
        //数据集

        //所属场站与对象类型存在联系
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.Station_Type.getCode()).getData();
        Map<String, DictData> dictDataMap = dictDataList.stream().collect(Collectors.toMap(DictData::getCode, Function.identity()));

        //用于存放不同对象类型的测点id集合
        Map<String, List<String>> mapKey = new HashMap<>();
        this.classifyObj(mapKey);

        //获取所有单位
        List<PvTerminalTreeVO> deptList = deptFeignClient.allDeptList().getData();
        Map<String, PvTerminalTreeVO> deptMap = deptList.stream().collect(Collectors.toMap(PvTerminalTreeVO::getCode,Function.identity()));


        List<PvTerminalTreeVO> pvTerminalTreeVOList = deptList.stream().filter(it->it.getLevel() == 2).collect(toList());

        QueryWrapper<RStatIntegrityD> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("line_index,sum(due_time) due_time,sum(real_time) real_time,(sum(real_time)/sum(due_time)) as integrityData")
                .between("time_id",startTime,endTime).groupBy("line_index");
        List<RStatIntegrityD> rStatIntegrityDList = rStatIntegrityDMapper.selectList(queryWrapper);


        List<RUploadPointStatisticalDataD> resultPO = new ArrayList<>();
        pmsRunStatisticMap.forEach((deptId,item)->{
            PvTerminalTreeVO dept = deptMap.get(deptId);
            //跳过全国这个单位
            if (Objects.equals(Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_1.getCode()), dept.getLevel())) {
                return;
            }
            List<String> runMonitorIds = Arrays.stream(StrUtil.isNotBlank(item.getRunMonitorIds())?item.getRunMonitorIds().split(StrUtil.COMMA):new String[]{}).collect(toList());
            List<String> onlineMonitorIds = Arrays.stream(StrUtil.isNotBlank(item.getOnlineMonitorIds())?item.getOnlineMonitorIds().split(StrUtil.COMMA):new String[]{}).collect(toList());
            List<String> runDevIds = Arrays.stream(StrUtil.isNotBlank(item.getRunDevIds())?item.getRunDevIds().split(StrUtil.COMMA):new String[]{}).collect(toList());
            List<LineDTO> lineDTOList;
            if(CollUtil.isNotEmpty(onlineMonitorIds)) {
                lineDTOList = commLineClient.getLineDetailBatch(onlineMonitorIds).getData();
            }else {
                lineDTOList = new ArrayList<>();
            }

            List<RStatIntegrityD> deptRStatIntegrityDList = rStatIntegrityDList.stream().filter(it->runMonitorIds.contains(it.getLineIndex())).collect(toList());
            int due = deptRStatIntegrityDList.stream().mapToInt(RStatIntegrityD::getDueTime).sum();
            int real = deptRStatIntegrityDList.stream().mapToInt(RStatIntegrityD::getRealTime).sum();

            mapKey.forEach((key, val) -> {

                RUploadPointStatisticalDataD rUploadPointStatisticalDataD = new RUploadPointStatisticalDataD();

                rUploadPointStatisticalDataD.setId(IdUtil.simpleUUID());
                rUploadPointStatisticalDataD.setProvinceId(pvTerminalTreeVOList.get(0).getCode());
                rUploadPointStatisticalDataD.setProvinceName(pvTerminalTreeVOList.get(0).getName());
                rUploadPointStatisticalDataD.setStatisticalDate(beginMonth);
                rUploadPointStatisticalDataD.setComputeDate(calculatedParam.getDataDate());
                rUploadPointStatisticalDataD.setStatisticalType(UploadEnum.STATISTICAL_TYPE_01.getCode());
                rUploadPointStatisticalDataD.setUploadStatus(Integer.parseInt(UploadEnum.UPLOAD_STATUS_0.getCode()));
                //fixme         主配网标识文档中没有,先随便定义一个,后期调整
                rUploadPointStatisticalDataD.setDistributionFlag(UploadEnum.DISTRIBUTION_FLAG_01.getCode());

                rUploadPointStatisticalDataD.setRunTerminalNum(runDevIds.size());
                rUploadPointStatisticalDataD.setRunMonitorNum(runMonitorIds.size());
                rUploadPointStatisticalDataD.setOnlineMonitorNum(onlineMonitorIds.size());
                //fixme over
                judgeLevel(dept.getLevel(), rUploadPointStatisticalDataD, dept.getCode(), dept.getName(), deptList, deptMap);


                assDataRate(deptRStatIntegrityDList,due,real,rUploadPointStatisticalDataD);
                assStationType(key,val,lineDTOList,dictDataMap,rUploadPointStatisticalDataD);
                resultPO.add(rUploadPointStatisticalDataD);
            });
        });

       this.saveOrUpdateBatchByMultiId(resultPO);
    }


    /**
     * 组装所属场站
     * @author cdf
     * @date 2024/5/30
     */
    private void assStationType(String key,List<String> val,List<LineDTO> lineDTOList,Map<String, DictData> dictDataMap,RUploadPointStatisticalDataD rUploadPointStatisticalDataD){
        List<LineDTO> keyItem;
        if(key.equals("9999")){
            //其他
            keyItem = lineDTOList.stream().filter(o -> !val.contains(o.getObjType())).collect(toList());
        }else {
            keyItem = lineDTOList.stream().filter(o -> val.contains(o.getObjType())).collect(toList());
        }
        long pointCount = keyItem.stream().map(LineDTO::getLineId).distinct().count();
        rUploadPointStatisticalDataD.setStationMonitorNum((int) pointCount);
        switch (key) {
            case "2100":
                rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Trans_Sub.getCode()).getId());
                break;
            case "1200":
                rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Converter.getCode()).getId());
                break;
            case "1300":
                rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Ele_Railways.getCode()).getId());
                break;
            case "1401":
                rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Wind_Farms.getCode()).getId());
                break;
            case "1402":
                rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Power_Station.getCode()).getId());
                break;
            case "2300":
                rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Smelting_Load.getCode()).getId());
                break;
            case "2400":
                rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Imp_Users.getCode()).getId());
                break;
            case "9999":
                rUploadPointStatisticalDataD.setStationType(dictDataMap.get(DicDataEnum.Station_Other.getCode()).getId());
                break;
        }
    }

    /**
     * 数据完整性赋值
     * @author cdf
     * @date 2024/5/30
     */
    private void assDataRate(List<RStatIntegrityD> deptRStatIntegrityDList,int due,int real,RUploadPointStatisticalDataD rUploadPointStatisticalDataD){
        rUploadPointStatisticalDataD.setExpectCollectNum(due);
        rUploadPointStatisticalDataD.setActualCollectNum(real);
        BigDecimal onlineMonitorRate = BigDecimal.ZERO;
        if (deptRStatIntegrityDList.size() != 0) {
            BigDecimal onlineMonitorNum = BigDecimal.valueOf(rUploadPointStatisticalDataD.getOnlineMonitorNum());
            BigDecimal runMonitorNum = BigDecimal.valueOf(rUploadPointStatisticalDataD.getRunMonitorNum());
            onlineMonitorRate = onlineMonitorNum.multiply(BigDecimal.valueOf(100))
                    .divide(runMonitorNum, 4, RoundingMode.HALF_UP);
            onlineMonitorRate = onlineMonitorRate.min(BigDecimal.valueOf(100)); // 确保不超过100
        }
        rUploadPointStatisticalDataD.setOnlineMonitorRate(onlineMonitorRate.doubleValue());

        BigDecimal dataFullRate = BigDecimal.ZERO;
        if (due != 0 && real != 0) {
            BigDecimal realValue = BigDecimal.valueOf(real);
            BigDecimal dueValue = BigDecimal.valueOf(due);
            dataFullRate = realValue.multiply(BigDecimal.valueOf(100))
                    .divide(dueValue, 4, RoundingMode.HALF_UP);
            dataFullRate = dataFullRate.min(BigDecimal.valueOf(100)); // 确保不超过100
        }
        rUploadPointStatisticalDataD.setDataFullRate(dataFullRate.doubleValue());
    }

    /**
     * @param calculatedParam
     * @param list            数据处理
     */
    private void dataProcessing(CalculatedParam<DeptGetChildrenMoreDTO> calculatedParam, List<RUploadPointStatisticalDataD> list, Map<String, ?> pmsRunStatisticMap, String type) {
        //数据分组
        Map<String, List<RUploadPointStatisticalDataD>> listMap = list.stream().collect(Collectors.groupingBy(x -> x.getProvinceId() + x.getCityId() + x.getCountyId()));
        //获取省级单位id
        Dept root = deptFeignClient.getRootDept().getData();
        String provinceId = deptFeignClient.getDepSonIdByDeptId(root.getId()).getData().get(0);
        Dept dept = deptFeignClient.getDeptById(provinceId).getData();

        //获取所有单位
        List<PvTerminalTreeVO> deptList = deptFeignClient.allDeptList().getData();
        Map<String,PvTerminalTreeVO> deptMap = deptList.stream().collect(Collectors.toMap(PvTerminalTreeVO::getCode,Function.identity()));

        //站别大类
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.Station_Type.getCode()).getData();
        Map<String, DictData> dictDataMap = dictDataList.stream().collect(Collectors.toMap(DictData::getCode, Function.identity()));
        //获取对象类型下字类型
        Map<String, List<String>> mapKey = new HashMap<>();
        classifyObj(mapKey);

        List<LineDTO> lineDTOList=new ArrayList<>();
        if (pmsRunStatisticMap.containsKey(dept.getCode())) {
            List<String> monitorIds;
            String runMonitorIds;
            if (BizParamConstant.STAT_BIZ_MONTH.equals(type)) {
                runMonitorIds = ((PmsRunStatisticM) pmsRunStatisticMap.get(dept.getCode())).getRunMonitorIds();
            } else {
                runMonitorIds = ((PmsRunStatisticY) pmsRunStatisticMap.get(dept.getCode())).getRunMonitorIds();
            }
            if(StrUtil.isNotBlank(runMonitorIds)){
                monitorIds = CollectionUtil.toList(runMonitorIds.split(StrUtil.COMMA));
                lineDTOList = commLineClient.getLineDetailBatch(monitorIds).getData();
            }
        }
        RUploadPointStatisticalDataD data;
        for (DeptGetChildrenMoreDTO item : calculatedParam.getIdList()) {
            //获取国网上送监测点
            List<LineDevGetDTO> temBaseList;
            long devCount;
            if (CollectionUtil.isEmpty(pmsRunStatisticMap)) {
                //正常流程
                temBaseList = item.getLineBaseList().stream().filter(o -> Objects.equals(o.getIsUpToGrid(), 1)).collect(Collectors.toList());
                devCount = temBaseList.stream().map(LineDevGetDTO::getDevId).distinct().count();
            } else {
                List<String> temIds=new ArrayList<>();
                List<String> onDevIds=new ArrayList<>();
                String runMonitorIds;
                String devIds;
                if (BizParamConstant.STAT_BIZ_MONTH.equals(type)) {
                    runMonitorIds = ((PmsRunStatisticM) pmsRunStatisticMap.get(item.getUnitId())).getRunMonitorIds();
                    devIds = ((PmsRunStatisticM) pmsRunStatisticMap.get(item.getUnitId())).getRunDevIds();
                } else {
                    runMonitorIds = ((PmsRunStatisticY) pmsRunStatisticMap.get(item.getUnitId())).getRunMonitorIds();
                    devIds = ((PmsRunStatisticY) pmsRunStatisticMap.get(item.getUnitId())).getRunDevIds();
                }
                if(StrUtil.isNotBlank(runMonitorIds)){
                    temIds = CollectionUtil.toList(runMonitorIds.split(StrUtil.COMMA));
                }
                if(StrUtil.isNotBlank(devIds)){
                    onDevIds = CollectionUtil.toList(devIds.split(StrUtil.COMMA));
                }
                List<String> finalTemIds = temIds;
                List<LineDevGetDTO> collect = lineDTOList.stream().filter(o -> finalTemIds.contains(o.getLineId())).map(it -> {
                            LineDevGetDTO lineDevGetDTO = new LineDevGetDTO();
                            lineDevGetDTO.setPointId(it.getLineId());
                            lineDevGetDTO.setDevId(it.getDevId());
                            lineDevGetDTO.setObjType(it.getObjType());
                            return lineDevGetDTO;
                        }).collect(toList());
                if(CollUtil.isEmpty(collect)){
                    temBaseList = item.getLineBaseList().stream().filter(o -> Objects.equals(o.getIsUpToGrid(), 1)).collect(Collectors.toList());
                    devCount = temBaseList.stream().map(LineDevGetDTO::getDevId).distinct().count();
                }else {
                    temBaseList = collect;
                    if(onDevIds.size()==0){
                        devCount = temBaseList.stream().map(LineDevGetDTO::getDevId).distinct().count();
                    }else{
                        devCount = onDevIds.size();
                    }
                }
            }

            long monitorCount = temBaseList.stream().map(LineDevGetDTO::getPointId).distinct().count();

            //其他类型
            data = new RUploadPointStatisticalDataD();
            data.setProvinceId(dept.getCode());
            data.setProvinceName(dept.getName());
            judgeLevel(item.getDeptLevel(), data, item.getUnitId(), item.getUnitName(), deptList, deptMap);

            if (listMap.containsKey(data.getProvinceId() + data.getCityId() + data.getCountyId())) {
                List<RUploadPointStatisticalDataD> orgData = listMap.get(data.getProvinceId() + data.getCityId() + data.getCountyId());
                //根据所属站别进行分类
                Map<String, RUploadPointStatisticalDataD> stationTypeMap = orgData.stream().collect(Collectors.toMap(x -> x.getStationType(), Function.identity()));
                mapKey.forEach((key, val) -> {
                    List<LineDevGetDTO> keyItem = temBaseList.stream().filter(o -> val.contains(o.getObjType())).collect(Collectors.toList());
                    String stationType = "";
                    switch (key) {
                        case "2100":
                            stationType = dictDataMap.get(DicDataEnum.Trans_Sub.getCode()).getId();
                            break;
                        case "1200":
                            stationType = dictDataMap.get(DicDataEnum.Converter.getCode()).getId();
                            break;
                        case "1300":
                            stationType = dictDataMap.get(DicDataEnum.Ele_Railways.getCode()).getId();
                            break;
                        case "1401":
                            stationType = dictDataMap.get(DicDataEnum.Wind_Farms.getCode()).getId();
                            break;
                        case "1402":
                            stationType = dictDataMap.get(DicDataEnum.Power_Station.getCode()).getId();
                            break;
                        case "2300":
                            stationType = dictDataMap.get(DicDataEnum.Smelting_Load.getCode()).getId();
                            break;
                        case "2400":
                            stationType = dictDataMap.get(DicDataEnum.Imp_Users.getCode()).getId();
                            break;
                    }

                    if (stationTypeMap.containsKey(stationType)) {
                        long pointCount = keyItem.stream().map(LineDevGetDTO::getPointId).distinct().count();
                        RUploadPointStatisticalDataD rUploadPointStatisticalDataD = stationTypeMap.get(stationType);
                        rUploadPointStatisticalDataD.setStationMonitorNum((int) pointCount);
                        rUploadPointStatisticalDataD.setRunTerminalNum((int) devCount);
                        rUploadPointStatisticalDataD.setOnlineMonitorNum((int) monitorCount);
                        rUploadPointStatisticalDataD.setRunMonitorNum((int) monitorCount);
                        rUploadPointStatisticalDataD.setOnlineMonitorRate(monitorCount == 0 ? 0d : BigDecimal.valueOf(rUploadPointStatisticalDataD.getOnlineMonitorNum() * 100.0 / rUploadPointStatisticalDataD.getRunMonitorNum()).setScale(4, RoundingMode.HALF_UP).doubleValue());

                    }

                });

        /*        //其他类型
                if (stationTypeMap.containsKey(dictDataMap.get(DicDataEnum.Station_Other.getCode()).getId())) {
                    List<LineDevGetDTO> otherMonitor = item.getLineBaseList().stream().filter(me -> !otherIds.contains(me.getObjType())).collect(Collectors.toList());
                    long pointCount = otherMonitor.stream().map(LineDevGetDTO::getPointId).distinct().count();
                    RUploadPointStatisticalDataD rUploadPointStatisticalDataD = stationTypeMap.get(dictDataMap.get(DicDataEnum.Station_Other.getCode()).getId());
                    rUploadPointStatisticalDataD.setRunTerminalNum((int) devCount);
                    rUploadPointStatisticalDataD.setOnlineMonitorNum((int) monitorCount);
                    rUploadPointStatisticalDataD.setRunMonitorNum((int) monitorCount);
                    rUploadPointStatisticalDataD.setStationMonitorNum((int) pointCount);
                    rUploadPointStatisticalDataD.setOnlineMonitorRate(monitorCount == 0 ? 0d : BigDecimal.valueOf(rUploadPointStatisticalDataD.getOnlineMonitorNum() * 100.0 / rUploadPointStatisticalDataD.getRunMonitorNum()).setScale(4, RoundingMode.HALF_UP).doubleValue());
                }*/

            }
        }
        if (CollUtil.isNotEmpty(list)) {
            list.forEach(item -> {
                item.setId(IdUtil.simpleUUID());
                item.setComputeDate(calculatedParam.getDataDate());
                if (item.getOnlineMonitorNum() > item.getRunMonitorNum()) {
                    item.setOnlineMonitorRate(100.0);
                    item.setOnlineMonitorNum(item.getRunMonitorNum());
                }
            });
            this.saveOrUpdateBatchByMultiId(list, 1000);
        }
    }


    /**
     * r_stat_integrity_d表中获取数据应收数、实收数
     */
    public List<RStatIntegrityD> getStatIntegrityData(String time) {
        LambdaQueryWrapper<RStatIntegrityD> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(RStatIntegrityD::getTimeId, time);
        return rStatIntegrityDMapper.selectList(lambdaQueryWrapper);
    }


    /**
     * 判断单位层级
     */
    public void judgeLevel(Integer level, RUploadPointStatisticalDataD rUploadPointStatisticalDataD, String id, String name, List<PvTerminalTreeVO> deptList, Map<String,PvTerminalTreeVO> map) {
        String result = "";
        if (Objects.equals(level, Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_2.getCode()))) {
            result = UploadEnum.STATISTICAL_LEVEL_3.getCode();
            rUploadPointStatisticalDataD.setCityId("");
            rUploadPointStatisticalDataD.setCountyId("");
        } else if (Objects.equals(level, Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_3.getCode()))) {
            result = UploadEnum.STATISTICAL_LEVEL_4.getCode();
            rUploadPointStatisticalDataD.setCityId(id);
            rUploadPointStatisticalDataD.setCityName(name);
            rUploadPointStatisticalDataD.setCountyId("");
        } else if (Objects.equals(level, Integer.parseInt(UploadEnum.NJCN_DEPT_LEVEL_4.getCode()))) {
            result = UploadEnum.STATISTICAL_LEVEL_5.getCode();
            String[] tem = map.get(id).getPids().split(",");
            List<String> list = Arrays.stream(tem).map(String::trim).collect(toList());
            String parentCode = deptList.stream().filter(o -> Objects.equals(o.getId(), list.get(3))).findFirst().orElse(null).getCode();
            rUploadPointStatisticalDataD.setCityId(parentCode);
            rUploadPointStatisticalDataD.setCityName(map.get(parentCode).getName());
            rUploadPointStatisticalDataD.setCountyId(id);
            rUploadPointStatisticalDataD.setCountyName(name);
        }
        rUploadPointStatisticalDataD.setStatisticalLevel(result);
    }


    /**
     * 分类所属场站
     * @author cdf
     * @date 2024/5/27
     */
    private void classifyObj(Map<String, List<String>> mapKey){
        List<String> noOtherIds = new ArrayList<>();
        //查询所有一级树字典
        List<SysDicTreePO> sysDicTreePOList = dictTreeFeignClient.queryAll().getData();

        //获取所有需要统计的对象类型字典
        List<SysDicTreePO> temTreeList = sysDicTreePOList.stream().filter(item -> Objects.equals(item.getCode(), DicTreeEnum.Trans_Sub.getCode())
                || Objects.equals(item.getCode(), DicTreeEnum.Converter.getCode()) || Objects.equals(item.getCode(), DicTreeEnum.Ele_Railways.getCode())
                || Objects.equals(item.getCode(), DicTreeEnum.Wind_Farms.getCode()) || Objects.equals(item.getCode(), DicTreeEnum.Power_Station.getCode())
                || Objects.equals(item.getCode(), DicTreeEnum.Smelting_Load.getCode()) || Objects.equals(item.getCode(), DicTreeEnum.Imp_Users.getCode())
        ).collect(toList());

        for (SysDicTreePO sysDicTreePO : temTreeList) {
            List<SysDicTreePO> temList;
            if (Objects.equals(sysDicTreePO.getCode(), DicTreeEnum.Smelting_Load.getCode())) {
                temList = sysDicTreePOList.stream()
                        .filter(item -> Objects.equals(item.getCode(), DicTreeEnum.Electric_Heating_Load.getCode()) ||
                                Objects.equals(item.getCode(), DicTreeEnum.Rolling_Mill.getCode()) ||
                                Objects.equals(item.getCode(), DicTreeEnum.Welding_Load.getCode()) ||
                                Objects.equals(item.getCode(), DicTreeEnum.Lifting_Load.getCode()) ||
                                Objects.equals(item.getCode(), DicTreeEnum.Electrolytic_Load.getCode())
                        )
                        .collect(toList());
            } else {
                temList = sysDicTreePOList.stream().filter(item -> item.getPid().equals(sysDicTreePO.getId()) ||
                        item.getId().equals(sysDicTreePO.getId())
                ).collect(toList());
            }
            List<String> ids = temList.stream().map(SysDicTreePO::getId).distinct().collect(toList());
            mapKey.put(sysDicTreePO.getCode(), ids);
            noOtherIds.addAll(ids);
        }
        mapKey.put("9999", noOtherIds);
    }
}
