package com.njcn.event.service.majornetwork.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.param.StatisticsBizBaseParam;
import com.njcn.event.mapper.majornetwork.RStatEventOrgMMapper;
import com.njcn.event.pojo.param.EventTypeParam;
import com.njcn.event.pojo.param.REventMParam;
import com.njcn.event.pojo.po.RStatEventOrgM;
import com.njcn.event.pojo.vo.RArrayVO;
import com.njcn.event.pojo.vo.RStatEventMVO;
import com.njcn.event.service.majornetwork.RStatEventOrgMService;
import com.njcn.event.utils.DeptUtil;
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.user.api.DeptFeignClient;
import com.njcn.user.pojo.dto.DeptDTO;
import com.njcn.user.pojo.po.Dept;
import com.njcn.web.utils.WebUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author rui.wu
 * @since 2022-10-11
 */
@Service
@RequiredArgsConstructor
public class RStatEventOrgMServiceImpl extends ServiceImpl<RStatEventOrgMMapper, RStatEventOrgM> implements RStatEventOrgMService {


    private final DicDataFeignClient dicDataFeignClient;
    private final DeptFeignClient deptFeignClient;
    private final RStatEventOrgMMapper statEventOrgMMapper;

    @Override
    public List<RArrayVO> getRStatEventOrgMAll(StatisticsBizBaseParam param) {
        //子节点 获取所有得各单位类型
        List<DeptDTO> deptList = deptFeignClient.getDeptDescendantIndexes(param.getId(), WebUtil.filterDeptType()).getData();
        List<DeptDTO> deptDTOList= DeptUtil.getDeptSubsetVOList(deptList,param.getId());

        //获取部门id集合
        List<String> deptIds = deptDTOList.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        Map<String, DeptDTO> deptMap = deptDTOList.stream().collect(Collectors.toMap(DeptDTO::getCode, Function.identity()));

        //对象主节点 获取所有得暂降类型
        List<DictData> lineTypeData = dicDataFeignClient.getDicDataByTypeCode(
                DicDataTypeEnum.EVENT_STATIS.getCode()).getData();
        Map<String, DictData> lineTypeMap = lineTypeData.stream()
                .collect(Collectors.toMap(DictData::getId, Function.identity()));
        //获取主网id信息
        DictData mainnetData = dicDataFeignClient.getDicDataByCode(DicDataEnum.MAINNET_POINT.getCode()).getData();

        //数据库查询
        List<RStatEventOrgM> list = statEventOrgMMapper.selectList(new LambdaQueryWrapper<RStatEventOrgM>()
                .eq(RStatEventOrgM::getDataType, mainnetData.getId())
                .in(RStatEventOrgM::getOrgNo, deptIds)
                .ge(StrUtil.isNotBlank(param.getStartTime()), RStatEventOrgM::getDataDate, param.getStartTime())
                .le(StrUtil.isNotBlank(param.getEndTime()), RStatEventOrgM::getDataDate, param.getEndTime()));

        //初始化指标类型（横向）
        List<RArrayVO> arrayVOList = new ArrayList<>();
        List<RStatEventMVO> rm = new ArrayList<>();
        for (DeptDTO deptDTO : deptDTOList) {
            RStatEventMVO r = new RStatEventMVO();
            r.setEventName(deptDTO.getName());
            r.setSort(deptDTO.getSort());
            r.setEventMeasurementAverage(0.0F);
            r.setEventMeasurementAccrued(0);
            r.setEventFreq(0.0F);
            r.setEventCount(0);
            r.setEventMeasurementRatioAverage(0.0F);
            r.setEventMeasurementRatioAccrued(0.0F);
            rm.add(r);
        }
        for (DictData lineTypeDatum : lineTypeData) {
            RArrayVO r = new RArrayVO();
            r.setRowName(lineTypeDatum.getName());
            r.setColumns(rm);
            r.setSort(lineTypeDatum.getSort());
            arrayVOList.add(r);
        }
        //根据检测点对象分组
        Map<String, List<RStatEventOrgM>> MeasurementTypeClassMap = list.stream().collect(Collectors.groupingBy(RStatEventOrgM::getEventType));
        //重新生成数据结构
        MeasurementTypeClassMap.forEach((key, value) -> {
            if (lineTypeMap.containsKey(key)) {
                RArrayVO arrayVO = new RArrayVO();
                DictData data = lineTypeMap.get(key);
                arrayVO.setRowName(data.getName());
                arrayVO.setSort(data.getSort());
                List<RStatEventMVO> b = new ArrayList<>();
                b.addAll(rm);
                for (RStatEventOrgM orgM : value) {
                    if(deptMap.containsKey(orgM.getOrgNo())){
                        RStatEventMVO r = BeanUtil.copyProperties(orgM, RStatEventMVO.class);
                        DeptDTO data1 = deptMap.get(orgM.getOrgNo());
                        r.setEventName(data1.getName());
                        r.setSort(data1.getSort());
                        b.add(r);
                    }

                }
                Map<String, RStatEventMVO> linkedHashMap = new LinkedHashMap<>();
                for (RStatEventMVO harmonicMVO : b) {
                    linkedHashMap.put(harmonicMVO.getEventName(), harmonicMVO);
                }
                List<RStatEventMVO> aa = new ArrayList<>(linkedHashMap.values());
                aa.sort(Comparator.comparing(rStatEventMVO -> rStatEventMVO.getSort()));
                arrayVO.setColumns(aa);
                arrayVOList.add(arrayVO);
            }

        });
        Map<String, RArrayVO> linkedHashMap = new LinkedHashMap<>();
        for (RArrayVO rArrayVO : arrayVOList) {
            linkedHashMap.put(rArrayVO.getRowName(), rArrayVO);
        }
        List<RArrayVO> aa = new ArrayList<>(linkedHashMap.values());
        arrayVOList.sort(Comparator.comparing(rArrayVO -> rArrayVO.getSort()));
        return aa;
    }

    @Override
    public List<RStatEventMVO> getRStatHarmonicOrgMIcon(REventMParam param) {
        //各单位
        List<DeptDTO> deptList = deptFeignClient.getDeptDescendantIndexes(param.getId(), WebUtil.filterDeptType()).getData();
        List<DeptDTO> deptDTOList= DeptUtil.getDeptSubsetVOList(deptList,param.getId());

        Map<String, DeptDTO> deptMap = deptDTOList.stream().collect(Collectors.toMap(DeptDTO::getCode, Function.identity()));
        //获取部门id集合
        List<String> deptIds = deptDTOList.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        //指标对象类型属性
        DictData eventData;
        //判断是是否传入检测点信息值（电压）
        if (StrUtil.isBlank(param.getStasisID()) && StrUtil.isBlank(param.getMonitorID())) {
            //指标对象类型
            List<DictData> indicatorTypeDate = dicDataFeignClient.getDicDataByTypeCode(
                    DicDataTypeEnum.EVENT_STATIS.getCode()).getData();
            indicatorTypeDate.sort(Comparator.comparing(data -> data.getSort()));
            eventData = indicatorTypeDate.get(0);
        } else {
            //获取指标对象（频率偏差）
            eventData = dicDataFeignClient.getDicDataById(
                    param.getStasisID()).getData();
        }
        //反防止参数查询数据报错
        Assert.isTrue(
                CollUtil.isNotEmpty(deptDTOList) || ObjectUtil.isNotNull(eventData)
                , "各单位或者指标类型为空,请检查入参是否准确");
        //获取主网id信息
        DictData mainnetData = dicDataFeignClient.getDicDataByCode(DicDataEnum.MAINNET_POINT.getCode()).getData();

        //初始化对象
        List<RStatEventMVO> arrayVOList = new ArrayList<>();
        List<RStatEventOrgM> rStatHarmonicVoltageMS = statEventOrgMMapper.selectList(new LambdaQueryWrapper<RStatEventOrgM>()
                .eq(RStatEventOrgM::getDataType, mainnetData.getId())
                .in(RStatEventOrgM::getOrgNo, deptIds)
                .eq(RStatEventOrgM::getEventType, eventData.getId())
                .ge(StrUtil.isNotBlank(param.getStartTime()), RStatEventOrgM::getDataDate, param.getStartTime())
                .le(StrUtil.isNotBlank(param.getEndTime()), RStatEventOrgM::getDataDate, param.getEndTime())
        );
        //将数据转换为map进行便利
        Map<String, List<RStatEventOrgM>> voltageMMap = rStatHarmonicVoltageMS.stream()
                .collect(Collectors.groupingBy(RStatEventOrgM::getOrgNo));
        //对象
        if (CollUtil.isNotEmpty(rStatHarmonicVoltageMS)) {
            voltageMMap.forEach((key, value) -> {
                if (deptMap.containsKey(key)) {
                    DeptDTO data = deptMap.get(key);
                    for (RStatEventOrgM orgM : value) {
                        RStatEventMVO rStatEventMVO = BeanUtil.copyProperties(orgM, RStatEventMVO.class);
                        rStatEventMVO.setEventName(data.getName());
                        rStatEventMVO.setSort(data.getSort());
                        arrayVOList.add(rStatEventMVO);
                    }

                }
            });
        }
        //处理主节点不存在的集合
        List<DeptDTO> notMeasurementList = deptDTOList.stream().filter(r -> !voltageMMap.containsKey(r.getCode()))
                .collect(Collectors.toList());
        for (DeptDTO notData : notMeasurementList) {
            RStatEventMVO iconVO = new RStatEventMVO();
            iconVO.setSort(notData.getSort());
            iconVO.setEventName(notData.getName());
            iconVO.setEventMeasurementAverage(0.0F);
            iconVO.setEventMeasurementAccrued(0);
            iconVO.setEventFreq(0.0F);
            iconVO.setEventCount(0);
            iconVO.setEventMeasurementRatioAverage(0.0F);
            iconVO.setEventMeasurementRatioAccrued(0.0F);
            arrayVOList.add(iconVO);
        }
        arrayVOList.sort(Comparator.comparing(rIconVO -> rIconVO.getSort()));
        return arrayVOList;
    }

    @Override
    public List<RArrayVO> getPwRStatEventOrgMAll(StatisticsBizBaseParam param) {
        //对象主节点 获取所有得暂降类型
        List<DictData> eventData = dicDataFeignClient.getDicDataByTypeCode(
                DicDataTypeEnum.EVENT_STATIS.getCode()).getData();
        Map<String, DictData> eventMap = eventData.stream()
                .collect(Collectors.toMap(DictData::getId, Function.identity()));

        //子节点 获取所有得各单位类型
        List<DeptDTO> deptList = deptFeignClient.getDeptDescendantIndexes(param.getId(), WebUtil.filterDeptType()).getData();
        List<DeptDTO> deptDTOList= DeptUtil.getDeptSubsetVOList(deptList,param.getId());

        //获取部门id集合
        List<String> deptIds = deptDTOList.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        Map<String, DeptDTO> deptMap = deptDTOList.stream().collect(Collectors.toMap(DeptDTO::getCode, Function.identity()));

        //获取配网信息
        DictData distributionData = dicDataFeignClient.getDicDataByCode(DicDataEnum.DISTRIBUTION_POINT.getCode()).getData();

        //数据库查询
        List<RStatEventOrgM> list = statEventOrgMMapper.selectList(new LambdaQueryWrapper<RStatEventOrgM>()
                .eq(RStatEventOrgM::getDataType, distributionData.getId())
                .in(RStatEventOrgM::getOrgNo, deptIds)
                .ge(StrUtil.isNotBlank(param.getStartTime()), RStatEventOrgM::getDataDate, param.getStartTime())
                .le(StrUtil.isNotBlank(param.getEndTime()), RStatEventOrgM::getDataDate, param.getEndTime()));

        //初始化指标类型（横向）
        List<RArrayVO> arrayVOList = new ArrayList<>();

        //根据检测点对象分组
        Map<String, List<RStatEventOrgM>> measurementTypeClassMap = list.stream().collect(Collectors.groupingBy(RStatEventOrgM::getEventType));
        if (CollUtil.isNotEmpty(list)) {
            //重新生成数据结构
            measurementTypeClassMap.forEach((key, value) -> {
                if (eventMap.containsKey(key)) {
                    List<RStatEventMVO> eventVO = new ArrayList<>();
                    RArrayVO arrayVO = new RArrayVO();
                    DictData data = eventMap.get(key);
                    arrayVO.setRowName(data.getName());
                    arrayVO.setSort(data.getSort());
                    for (RStatEventOrgM org : value) {
                        if(deptMap.containsKey(org.getOrgNo())){
                            RStatEventMVO r = BeanUtil.copyProperties(org, RStatEventMVO.class);
                            DeptDTO deptDTO = deptMap.get(org.getOrgNo());
                            r.setEventName(deptDTO.getName());
                            r.setSort(deptDTO.getSort());
                            eventVO.add(r);
                        }

                    }
                    //根据监测点类别获取差集
                    Map<String, List<RStatEventOrgM>> listMap = value.stream().collect(Collectors.groupingBy(RStatEventOrgM::getOrgNo));
                    List<DeptDTO> notDeptList = deptDTOList.stream().filter(r -> !listMap.containsKey(r.getCode()))
                            .collect(Collectors.toList());
                    this.assignDept(notDeptList, eventVO, arrayVO);
                    eventVO.sort(Comparator.comparing(rStatEventMVO -> rStatEventMVO.getSort()));
                    arrayVOList.add(arrayVO);
                }
            });
        }
        //处理主节点不存在的集合
        List<DictData> notMeasurementList = eventData.stream().filter(r -> !measurementTypeClassMap.containsKey(r.getId()))
                .collect(Collectors.toList());
        for (DictData notData : notMeasurementList) {
            List<RStatEventMVO> eventVO = new ArrayList<>();
            RArrayVO arrayVO = new RArrayVO();
            arrayVO.setRowName(notData.getName());
            arrayVO.setSort(notData.getSort());
            this.assignDept(deptDTOList, eventVO, arrayVO);
            eventVO.sort(Comparator.comparing(rStatEventMVO -> rStatEventMVO.getSort()));
            arrayVOList.add(arrayVO);
        }
        arrayVOList.sort(Comparator.comparing(rArrayVO -> rArrayVO.getSort()));
        return arrayVOList;
    }

    @Override
    public List<RStatEventMVO> getPwRStatHarmonicOrgMIcon(REventMParam param) {
        //各单位
        List<DeptDTO> deptList = deptFeignClient.getDeptDescendantIndexes(param.getId(), WebUtil.filterDeptType()).getData();
        List<DeptDTO> deptDTOList= DeptUtil.getDeptSubsetVOList(deptList,param.getId());

        Map<String, DeptDTO> deptMap = deptDTOList.stream().collect(Collectors.toMap(DeptDTO::getCode, Function.identity()));
        //获取部门id集合
        List<String> deptIds = deptDTOList.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        //指标对象类型属性
        DictData eventData;
        //判断是是否传入检测点信息值（电压）
        if (StrUtil.isBlank(param.getStasisID()) && StrUtil.isBlank(param.getMonitorID())) {
            //指标对象类型
            List<DictData> indicatorTypeDate = dicDataFeignClient.getDicDataByTypeCode(
                    DicDataTypeEnum.EVENT_STATIS.getCode()).getData();
            indicatorTypeDate.sort(Comparator.comparing(data -> data.getSort()));
            eventData = indicatorTypeDate.get(0);
        } else {
            //获取指标对象（频率偏差）
            eventData = dicDataFeignClient.getDicDataById(
                    param.getStasisID()).getData();
        }
        //反防止参数查询数据报错
        Assert.isTrue(
                CollUtil.isNotEmpty(deptDTOList) || ObjectUtil.isNotNull(eventData)
                , "各单位或者指标类型为空,请检查入参是否准确");
        //获取配网信息
        DictData distributionData = dicDataFeignClient.getDicDataByCode(DicDataEnum.DISTRIBUTION_POINT.getCode()).getData();

        //初始化对象
        List<RStatEventMVO> arrayVOList = new ArrayList<>();
        List<RStatEventOrgM> rStatHarmonicVoltageMS = statEventOrgMMapper.selectList(new LambdaQueryWrapper<RStatEventOrgM>()
                .eq(RStatEventOrgM::getDataType, distributionData.getId())
                .in(RStatEventOrgM::getOrgNo, deptIds)
                .eq(RStatEventOrgM::getEventType, eventData.getId())
                .ge(StrUtil.isNotBlank(param.getStartTime()), RStatEventOrgM::getDataDate, param.getStartTime())
                .le(StrUtil.isNotBlank(param.getEndTime()), RStatEventOrgM::getDataDate, param.getEndTime())
        );
        //将数据转换为map进行便利
        Map<String, List<RStatEventOrgM>> voltageMMap = rStatHarmonicVoltageMS.stream()
                .collect(Collectors.groupingBy(RStatEventOrgM::getOrgNo));
        //对象
        if (CollUtil.isNotEmpty(rStatHarmonicVoltageMS)) {
            voltageMMap.forEach((key, value) -> {
                if (deptMap.containsKey(key)) {
                    DeptDTO data = deptMap.get(key);
                    for (RStatEventOrgM orgM : value) {
                        RStatEventMVO rStatEventMVO = BeanUtil.copyProperties(orgM, RStatEventMVO.class);
                        rStatEventMVO.setEventName(data.getName());
                        rStatEventMVO.setSort(data.getSort());
                        arrayVOList.add(rStatEventMVO);
                    }

                }
            });
        }
        //处理主节点不存在的集合
        List<DeptDTO> notMeasurementList = deptDTOList.stream().filter(r -> !voltageMMap.containsKey(r.getCode()))
                .collect(Collectors.toList());
        for (DeptDTO notData : notMeasurementList) {
            RStatEventMVO iconVO = new RStatEventMVO();
            iconVO.setSort(notData.getSort());
            iconVO.setEventName(notData.getName());
            iconVO.setEventMeasurementAverage(0.0F);
            iconVO.setEventMeasurementAccrued(0);
            iconVO.setEventFreq(0.0F);
            iconVO.setEventCount(0);
            iconVO.setEventMeasurementRatioAverage(0.0F);
            iconVO.setEventMeasurementRatioAccrued(0.0F);
            arrayVOList.add(iconVO);
        }
        arrayVOList.sort(Comparator.comparing(rIconVO -> rIconVO.getSort()));
        return arrayVOList;
    }

    @Override
    public List<RArrayVO> getEventOrg(EventTypeParam param) {
        List<RArrayVO> info=new ArrayList<>();
        //获取当前部门信息
        Dept dept = deptFeignClient.getDeptById(param.getId()).getData();

        List<DictData> eventTypeData = dicDataFeignClient.getDicDataByTypeCode(
                DicDataTypeEnum.EVENT_STATIS.getCode()).getData();
        Map<String, DictData> eventTypeMap = eventTypeData.stream()
                .collect(Collectors.toMap(DictData::getId, Function.identity()));

        DictData distributionData=new DictData();
        //获取配网信息
        if(param.getPointType()==0){
             distributionData = dicDataFeignClient.getDicDataByCode(DicDataEnum.MAINNET_POINT.getCode()).getData();
        }else{
            distributionData = dicDataFeignClient.getDicDataByCode(DicDataEnum.DISTRIBUTION_POINT.getCode()).getData();
        }

        List<RStatEventOrgM> rStatEventOrgMS = statEventOrgMMapper.selectList(new LambdaQueryWrapper<RStatEventOrgM>()
                .eq(RStatEventOrgM::getDataType, distributionData.getId())
                .in(RStatEventOrgM::getOrgNo, dept.getCode())
                .ge(StrUtil.isNotBlank(param.getStartTime()), RStatEventOrgM::getDataDate, param.getStartTime())
                .le(StrUtil.isNotBlank(param.getEndTime()), RStatEventOrgM::getDataDate, param.getEndTime())
        );
        Map<String, RStatEventOrgM> eventOrgMMap = rStatEventOrgMS.stream().collect(Collectors.toMap(RStatEventOrgM::getEventType, Function.identity(), (Key1, kye2) -> Key1));
        eventOrgMMap.forEach((key, value) -> {
            if (eventTypeMap.containsKey(key)) {
                RArrayVO arrayVO = new RArrayVO();
                DictData data = eventTypeMap.get(key);
                arrayVO.setRowName(data.getName());
                arrayVO.setSort(data.getSort());
                List<Object> a=new ArrayList<>();
                //累计超标占比
                a.add(value.getEventMeasurementRatioAccrued());
                a.add(100-value.getEventMeasurementRatioAccrued());
                a.add(value.getEventMeasurementAccrued());
                arrayVO.setColumns(a);
                info.add(arrayVO);
            }
        });

        List<DictData> notEventOrg = eventTypeData.stream().filter(r -> !eventOrgMMap.containsKey(r.getId()))
                .collect(Collectors.toList());
        for (DictData dictData : notEventOrg) {
            RArrayVO arrayVO = new RArrayVO();
            arrayVO.setRowName(dictData.getName());
            arrayVO.setSort(dictData.getSort());
            List<Object> a=new ArrayList<>();
            //累计超标占比
            a.add(0);
            a.add(100);
            a.add(0);
            arrayVO.setColumns(a);
            info.add(arrayVO);
        }
        info.sort(Comparator.comparing(rStatEventMVO -> rStatEventMVO.getSort()));
        return info;
    }

    /**
     * 便利赋值
     *
     * @param deptDTOList 部门集合
     * @param eventVO     暂态监测点
     * @param arrayVO     初始化对象
     */
    private void assignDept(List<DeptDTO> deptDTOList, List<RStatEventMVO> eventVO, RArrayVO arrayVO) {
        for (DeptDTO dictData : deptDTOList) {
            RStatEventMVO notEventVO = new RStatEventMVO();
            notEventVO.setEventName(dictData.getName());
            notEventVO.setSort(dictData.getSort());
            notEventVO.setEventMeasurementAverage(0.0F);
            notEventVO.setEventMeasurementAccrued(0);
            notEventVO.setEventFreq(0.0F);
            notEventVO.setEventCount(0);
            notEventVO.setEventMeasurementRatioAverage(0.0F);
            notEventVO.setEventMeasurementRatioAccrued(0.0F);
            eventVO.add(notEventVO);
        }
        arrayVO.setColumns(eventVO);
    }
}
