package com.njcn.device.pms.service.majornetwork.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.device.pms.mapper.majornetwork.OverviewMapper;
import com.njcn.device.pms.pojo.param.OverviewParam;
import com.njcn.device.pms.pojo.po.RMpMonitorAlarmCountM;
import com.njcn.device.pms.pojo.po.RStatAreaAlarmCountM;
import com.njcn.device.pms.pojo.vo.DistributionMonitorVO;
import com.njcn.device.pms.pojo.vo.OverviewVO;
import com.njcn.device.pms.service.majornetwork.OverviewService;
import com.njcn.device.pms.service.majornetwork.RMpMonitorAlarmCountMService;
import com.njcn.device.pms.service.majornetwork.RStatAreaAlarmCountMService;
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.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

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

/**
 * <分布式光伏概览业务>
 *
 * @author wr
 * @createTime: 2022-12-29
 */
@Service
@RequiredArgsConstructor
public class OverviewServiceImpl implements OverviewService {


    private final OverviewMapper overviewMapper;
    private final DeptFeignClient deptFeignClient;
    private final DicDataFeignClient dicDataFeignClient;
    private final RMpMonitorAlarmCountMService rMpMonitorAlarmCountMService;
    private final RStatAreaAlarmCountMService rStatAreaAlarmCountMService;
    private static final String XIONG_AN_CITY="雄安新区";

    @Override
    public OverviewVO getMonitorYoY(OverviewParam param) {
        OverviewVO vos=new OverviewVO();
        //获取监测点类别集合（配网1-2-3类监测点）
        List<DictData> lineData = dicDataFeignClient.getDicDataByTypeCode(
                DicDataTypeEnum.LINE_SORT.getCode()).getData();

        //获取部门数据
        List<DeptDTO> data = deptFeignClient.getDeptDescendantIndexes(param.getId(), WebUtil.filterDeptType()).getData();
        List<String> deptListCode = data.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(deptListCode)){

            List<OverviewVO.MonitorObject>  overviewVOS = overviewMapper.selectYoY(deptListCode, param);
            Map<String, OverviewVO.MonitorObject> voMap = overviewVOS.stream().
                    collect(Collectors.toMap(OverviewVO.MonitorObject::getMonitorSort, Function.identity()));

            //不存在监测点赋值初始值
            List<DictData> notMeasurementList = lineData.stream().filter(r -> !voMap.containsKey(r.getId()))
                    .collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(notMeasurementList)){
                OverviewVO.MonitorObject overviewVO;
                for (DictData notData : notMeasurementList) {
                    overviewVO=new OverviewVO.MonitorObject();
                    overviewVO.setMonitorSort(notData.getId());
                    overviewVO.setSumNum("0");
                    overviewVO.setYtbSumNum("0");
                    overviewVO.setYhbSumNum("0");
                    overviewVO.setSameNum("0");
                    overviewVO.setRingNum("0");
                    overviewVOS.add(overviewVO);
                }
            }
            //获取电压字典
            List<DictData> voltageData = dicDataFeignClient.getDicDataByTypeCode(
                    DicDataTypeEnum.DEV_VOLTAGE.getCode()).getData();
            //低压字典
            List<String> lowPressure=new ArrayList<>();
            //中压字典
            List<String> inPressure=new ArrayList<>();
            for (DictData voltageDatum : voltageData) {
                if(DicDataEnum.AC_380V.getCode().equals( voltageDatum.getCode())&&"0.38".equals(voltageDatum.getValue())){
                    lowPressure.add(voltageDatum.getId());
                }
                if(DicDataEnum.DY_380V.getCode().equals( voltageDatum.getCode())&&"0.38".equals(voltageDatum.getValue())){
                    lowPressure.add(voltageDatum.getId());
                }
                if(DicDataEnum.DY_10KV.getCode().equals( voltageDatum.getCode())){
                    inPressure.add(voltageDatum.getId());
                }
            }
            //查询分布式光伏概览用户数量和装机容量
            List<OverviewVO.PhotoVoltaicVoltage> voltageList = overviewMapper.selectPhotovoltaicUser(deptListCode, lowPressure, inPressure);
            //光伏用户
            OverviewVO.PhotovoltaicUser photovoltaicUser=new OverviewVO.PhotovoltaicUser();
            //装机容量
            OverviewVO.PhotovoltaicCapacity photovoltaicCapacity=new OverviewVO.PhotovoltaicCapacity();
            for (OverviewVO.PhotoVoltaicVoltage value : voltageList) {
                if("1".equals(value.getType())){
                    photovoltaicUser.setLowPressure(value.getNum());
                    photovoltaicCapacity.setLowCapacity(value.getCapacity());
                }else{
                    photovoltaicUser.setHighPressure(value.getNum());
                    photovoltaicCapacity.setHighCapacity(value.getCapacity());
                }

            }
            vos.setMonitorObjects(overviewVOS);
            vos.setPhotovoltaicUser(photovoltaicUser);
            vos.setPhotovoltaicCapacity(photovoltaicCapacity);
        }
        return vos;
    }

    @Override
    public List<OverviewVO.AlarmVO> getAlarmProportion(OverviewParam.OverviewDateParam param) {
        List<OverviewVO.AlarmVO> alarmVOS=new ArrayList<>();
        //获取部门数据
        List<DeptDTO> deptDTOS = deptFeignClient.getDeptDescendantIndexes(param.getId(), WebUtil.filterDeptType()).getData();
        List<String> deptListCode = deptDTOS.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        DictData data = dicDataFeignClient.getDicDataByCode(DicDataEnum.DISTRIBUTION_POINT.getCode()).getData();

        //获取监测点类别集合（配网1-2-3类监测点）
        List<DictData> lineData = dicDataFeignClient.getDicDataByTypeCode(
                DicDataTypeEnum.LINE_SORT.getCode()).getData();

        if(CollectionUtil.isNotEmpty(deptListCode)){
            //数据统计(配网监测点)
            List<DistributionMonitorVO> distributionMonitors = overviewMapper.selectListAll(deptListCode);
            Map<String, DistributionMonitorVO> distributionMonitorMap =
                    distributionMonitors.stream().collect(Collectors.toMap(DistributionMonitorVO::getMonitorId, Function.identity(),(key1,key2)->key2));

            //数据 key:监测点类别 value:数量
            Map<String, Long> map = distributionMonitors.stream().collect(Collectors.groupingBy(dm -> dm.getMonitorSort(), Collectors.counting()));
            //获取监测点id
            List<String> ids = distributionMonitors.stream().map(DistributionMonitorVO::getMonitorId).collect(Collectors.toList());


            //获取数据库数据
            List<RMpMonitorAlarmCountM> list = rMpMonitorAlarmCountMService.list(new LambdaQueryWrapper<RMpMonitorAlarmCountM>()
                    .in(RMpMonitorAlarmCountM::getMeasurementPointId, ids)
//                    .eq(RMpMonitorAlarmCountM::getDataType,data.getId())
                    .ge(StringUtils.isNotBlank(param.getStartTime()), RMpMonitorAlarmCountM::getDataDate, param.getStartTime())
                    .le(StringUtils.isNotBlank(param.getEndTime()), RMpMonitorAlarmCountM::getDataDate, param.getEndTime())
            );
            //为数据添加监测点类型类型(1-2-3监测点)
            List<OverviewVO.MonitorAlarmCountVO> info=new ArrayList<>();
            OverviewVO.MonitorAlarmCountVO monitorAlarmCountVO;
            for (RMpMonitorAlarmCountM rMpMonitorAlarmCountM : list) {
                //添加监测点的类型
                if(distributionMonitorMap.containsKey(rMpMonitorAlarmCountM.getMeasurementPointId())){
                    monitorAlarmCountVO = BeanUtil.copyProperties(rMpMonitorAlarmCountM, OverviewVO.MonitorAlarmCountVO.class);
                    DistributionMonitorVO distributionMonitor = distributionMonitorMap.get(rMpMonitorAlarmCountM.getMeasurementPointId());
                    monitorAlarmCountVO.setMonitorSort(distributionMonitor.getMonitorSort());
                    info.add(monitorAlarmCountVO);
                }
            }
            //根据数据类型进行分组
            Map<String, List<OverviewVO.MonitorAlarmCountVO>> listMap = info.stream()
                    .collect(Collectors.groupingBy(OverviewVO.MonitorAlarmCountVO::getMonitorSort));

            listMap.forEach((key,value)->{
                //谐波电压，闪变，三项不平横
                Integer vAlarmInfo=0, flickerAlarmInfo=0, unbalanceAlarmInfo=0;

                for (OverviewVO.MonitorAlarmCountVO alarmCountVO : value) {
                    if(alarmCountVO.getVAlarmInfo()==1){
                        vAlarmInfo=vAlarmInfo+1;
                    }
                    if(alarmCountVO.getFlickerAlarmInfo()==1){
                        flickerAlarmInfo=flickerAlarmInfo+1;
                    }
                    if(alarmCountVO.getUnbalanceAlarmInfo()==1){
                        unbalanceAlarmInfo=unbalanceAlarmInfo+1;
                    }
                }
                DecimalFormat df = new DecimalFormat("###.00");
                Float vAlarm = Float.parseFloat(
                        df.format(vAlarmInfo / (map.get(key) * 1.0)));
                Float flickerAlarm = Float.parseFloat(
                        df.format(flickerAlarmInfo / (map.get(key) * 1.0)));
                Float unbalanceAlarm = Float.parseFloat(
                        df.format(unbalanceAlarmInfo / (map.get(key) * 1.0)));
                //计算占比
                OverviewVO.AlarmVO alarmVO=new OverviewVO.AlarmVO();
                alarmVO.setMonitorSort(key);
                alarmVO.setVAlarm(vAlarm);
                alarmVO.setFlickerAlarm(flickerAlarm);
                alarmVO.setUnbalanceAlarm(unbalanceAlarm);
                alarmVOS.add(alarmVO);

            });
            //判断不存在监测点集合
            Map<String, OverviewVO.AlarmVO> voMap = alarmVOS.stream()
                    .collect(Collectors.toMap(OverviewVO.AlarmVO::getMonitorSort, Function.identity()));
            List<DictData> notMeasurementList = lineData.stream().filter(r -> !voMap.containsKey(r.getId()))
                    .collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(notMeasurementList)){
                OverviewVO.AlarmVO overviewVO;
                for (DictData notData : notMeasurementList) {
                    overviewVO=new OverviewVO.AlarmVO();
                    overviewVO.setMonitorSort(notData.getId());
                    overviewVO.setVAlarm(0.0f);
                    overviewVO.setFlickerAlarm(0.0f);
                    overviewVO.setUnbalanceAlarm(0.0f);
                    alarmVOS.add(overviewVO);
                }
            }

        }
        return alarmVOS;
    }

    @Override
    public Map<String, List<DistributionMonitorVO>> getMonitorDistributed(OverviewParam param) {
        Map<String, List<DistributionMonitorVO>> info =new LinkedHashMap<>();
        //获取监测点类别集合（配网1-2-3类监测点）
        List<DictData> lineData = dicDataFeignClient.getDicDataByTypeCode(
                DicDataTypeEnum.LINE_SORT.getCode()).getData();
        for (DictData dictData : lineData) {
            info.put(dictData.getId(),new ArrayList<>());
        }
        //获取部门数据
        List<DeptDTO> subDeptListCode = getSubDeptListCode(param.getId());
        List<String> deptListCode = subDeptListCode.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(deptListCode)){
            //获取所有配网监测点信息
            List<DistributionMonitorVO> distributionMonitors = overviewMapper.selectListAll(deptListCode);
            info.putAll(distributionMonitors.stream().collect(Collectors.groupingBy(DistributionMonitorVO::getMonitorSort)));
        }
        return info;
    }

    @Override
    public List<OverviewVO.AreaAlarmCountVO> getAlarmRating(OverviewParam.OverviewDateParam param) {
        List<DeptDTO> subDeptListCode = getSubDeptListCode(param.getId());
        List<String> deptListCode = subDeptListCode.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        Map<String, DeptDTO> deptMap = subDeptListCode.stream().collect(Collectors.toMap(DeptDTO::getCode, Function.identity()));

        //查询配网信息
        DictData dictData = dicDataFeignClient.getDicDataByCode(DicDataEnum.DISTRIBUTION_POINT.getCode()).getData();

        List<RStatAreaAlarmCountM> list = rStatAreaAlarmCountMService.list(new LambdaQueryWrapper<RStatAreaAlarmCountM>()
                .in(RStatAreaAlarmCountM::getOrgNo, deptListCode)
                .eq(RStatAreaAlarmCountM::getDataType, dictData.getId())
                .ge(StringUtils.isNotBlank(param.getStartTime()), RStatAreaAlarmCountM::getDataDate, param.getStartTime())
                .le(StringUtils.isNotBlank(param.getEndTime()), RStatAreaAlarmCountM::getDataDate, param.getEndTime())
        );
        List<OverviewVO.AreaAlarmCountVO>  alarmCountMVOS= new ArrayList<>();
        OverviewVO.AreaAlarmCountVO alarmCountVO;
        for (RStatAreaAlarmCountM alarmCountMVO : list) {
            if(deptMap.containsKey(alarmCountMVO.getOrgNo())){
                alarmCountVO=new OverviewVO.AreaAlarmCountVO();
                String name = deptMap.get(alarmCountMVO.getOrgNo()).getName();

                String replace = name.replace("供电公司","");
                if(XIONG_AN_CITY.equals(replace)){
                    alarmCountVO.setOrgName(XIONG_AN_CITY);
                }else{
                    alarmCountVO.setOrgName(replace+"市");
                }
                alarmCountVO.setEventTypeGrade(alarmCountMVO.getEventTypeGrade());
                alarmCountVO.setHarmonicTypeGrade(alarmCountMVO.getHarmonicTypeGrade());
                alarmCountMVOS.add(alarmCountVO);
            }
        }

        return alarmCountMVOS;
    }


    /**
     * 当前部门通用方法
     * @param id
     * @return
     */
    public List<String> getDeptListCode(String id){
        //获取部门数据
        Dept data = deptFeignClient.getDeptById(id).getData();
        if(ObjectUtil.isNotNull(data)){
            return Arrays.asList(data.getCode());
        }
        return new ArrayList<>();
    }

    /**
     * 当前部门下子部门通用方法
     * @param deptId
     * @return
     */
    public List<DeptDTO> getSubDeptListCode(String deptId){
        List<DeptDTO> deptDTOList = deptFeignClient.getDeptDescendantIndexes(deptId, WebUtil.filterDeptType()).getData();
        //获取子部门
        List<DeptDTO> directDeptInfos = deptDTOList.stream()
                .filter(deptDTO -> deptDTO.getPid().equals(deptId))
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(directDeptInfos)) {
            //没有直接子部门，获取当前部门所有信息
            List<DeptDTO> dept = deptDTOList.stream()
                    .filter(deptDTO -> deptDTO.getId().equals(deptId))
                    .collect(Collectors.toList());
            return dept;
        }
        return directDeptInfos;
    }

}
