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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Month;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.device.pms.mapper.majornetwork.RStatZwAlarmCountWMapper;
import com.njcn.device.pms.pojo.param.RStatZwAlarmCountWParam;
import com.njcn.device.pms.pojo.po.Monitor;
import com.njcn.device.pms.pojo.po.RMpTargetWarnD;
import com.njcn.device.pms.pojo.po.RStatZwAlarmCountW;
import com.njcn.device.pms.pojo.po.StatationStat;
import com.njcn.device.pms.pojo.vo.ProblemMonitorDetailVO;
import com.njcn.device.pms.pojo.vo.RStatZwAlarmCountWVO;
import com.njcn.device.pms.service.distribution.RMpPwAlarmDetailDService;
import com.njcn.device.pms.service.majornetwork.IMonitorService;
import com.njcn.device.pms.service.majornetwork.IStatationStatService;
import com.njcn.device.pms.service.majornetwork.RMpTargetWarnDService;
import com.njcn.device.pms.service.majornetwork.RStatZwAlarmCountWService;
import com.njcn.system.api.DicDataFeignClient;
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 lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

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

/**
* @author jianghf
* @description 针对表【r_stat_zw_alarm_count_w】的数据库操作Service实现
* @createDate 2022-10-08 16:35:44
*/
@Service
@RequiredArgsConstructor
public class RStatZwAlarmCountWServiceImpl extends ServiceImpl<RStatZwAlarmCountWMapper, RStatZwAlarmCountW>
implements RStatZwAlarmCountWService {

    private final DeptFeignClient deptFeignClient;

    private final RMpPwAlarmDetailDService rMpPwAlarmDetailDService; //【告警明细-日表】服务类

    private final RMpTargetWarnDService rMpTargetWarnDService; // 【监测点指标告警明细日表】服务类

    private final IMonitorService iMonitorService; //【监测点】服务类

    private final IStatationStatService iStatationStatService; //【变电站】服务类

    private final DicDataFeignClient dicDataFeignClient; //字典
    /***
     * 查询所有告警统计(周)
     * @author jianghaifei
     * @date 2022-10-09 10:22
     * @param
     * @return java.util.List<com.njcn.device.pms.pojo.po.RStatZwAlarmCountW>
     */
    @Override
    public List<RStatZwAlarmCountWVO> getAllRStatZwAlarmCountWList(RStatZwAlarmCountWParam rStatZwAlarmCountWParam) {
        //获取查询条件
        String id = rStatZwAlarmCountWParam.getId(); //单位id
        if (StringUtils.isBlank(id)) {
            throw new BusinessException(CommonResponseEnum.NO_DATA, "单位id不可为空");
        }
        String startTime = rStatZwAlarmCountWParam.getStartTime(); //开始时间 yyyy-MM-dd
        String endTime = rStatZwAlarmCountWParam.getEndTime(); //截止时间 yyyy-MM-dd
        //获取所有子部门信息
//        List<DeptDTO> deptDTOList = deptFeignClient.getDeptDescendantIndexes(id, WebUtil.filterDeptType()).getData();
        /*获取下级子部门信息*/
        List<DeptDTO> deptDTOList = deptFeignClient.getDepSonDetailByDeptId (id).getData ( );

        if (CollUtil.isEmpty(deptDTOList)) {
            throw new BusinessException(CommonResponseEnum.NO_DATA, "部门不存在");
        }
        //单位id集合
        List<String> orgCodeList = deptDTOList.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        //将单位信息转为map集合 key: 单位id  value: 单位实体
        Map<String, DeptDTO> deptDTOMap = deptDTOList.stream().collect(Collectors.toMap(DeptDTO::getCode, deptDTO -> deptDTO));
        LambdaQueryWrapper<RStatZwAlarmCountW> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //条件组装: where org_no in (orgNoList) and data_date >= startTime and data_date <= endTime
        lambdaQueryWrapper.in(CollUtil.isNotEmpty(orgCodeList), RStatZwAlarmCountW::getOrgNo, orgCodeList)
                .ge(StringUtils.isNotBlank(startTime), RStatZwAlarmCountW::getDataDate, startTime)
                .le(StringUtils.isNotBlank(endTime), RStatZwAlarmCountW::getDataDate, endTime);
        //查询告警统计(周)集合
        List<RStatZwAlarmCountW> records = this.list(lambdaQueryWrapper);
        List<RStatZwAlarmCountWVO> resultList;
        if (CollUtil.isNotEmpty(records)) {
            resultList = records.stream().map(item -> {
                RStatZwAlarmCountWVO rStatZwAlarmCountWVO = new RStatZwAlarmCountWVO();
                BeanUtils.copyProperties(item, rStatZwAlarmCountWVO);
                //单位名称
                rStatZwAlarmCountWVO.setOrgName(deptDTOMap.get(rStatZwAlarmCountWVO.getOrgNo()).getName());
                //获取有效监测点数量
                Integer monitorEffectiveCount = item.getMonitorEffectiveCount();
                //todo 有效监测点数量在实际环境中是可能为0的,不需要做异常处理
                Double warnMonitorRate = 0.0 ;
                Double monitorGradeRate = 0.0;
                if(monitorEffectiveCount<=0){
                    if(item.getWarnMonitorCount()>0){
                        warnMonitorRate=100.0;
                    }
                    if(item.getMonitorGradeCount()>0){
                        monitorGradeRate=100.0;
                    }
                }else {
                    //计算告警四次及以上监测点占比（ * 100 是直接取到百分比）
                    warnMonitorRate = Double.parseDouble(String.format("%.2f",item.getWarnMonitorCount() / (monitorEffectiveCount * 1.0) * 100));
                    //级别'较差'监测点占比（ * 100 是直接取到百分比）
                    monitorGradeRate = Double.parseDouble(String.format("%.2f",item.getMonitorGradeCount() / (monitorEffectiveCount * 1.0) * 100));
                }
                rStatZwAlarmCountWVO.setWarnMonitorRate(warnMonitorRate);
                rStatZwAlarmCountWVO.setMonitorGradeRate(monitorGradeRate);
                return rStatZwAlarmCountWVO;
            }).collect(Collectors.toList());
        } else {
            resultList = new ArrayList<>();
        }
        return resultList;
    }


    /***
     * 查询问题严重的监测点信息
     * @author jianghaifei
     * @date 2022-10-13 19:38
     * @param rStatZwAlarmCountWParam
     * @return java.util.List<com.njcn.device.pms.pojo.vo.ProblemMonitorDetailVO>
     */
    @Override
    public List<ProblemMonitorDetailVO> getProblemMonitorDetailList(RStatZwAlarmCountWParam rStatZwAlarmCountWParam) {
        //提取参数
        String id = rStatZwAlarmCountWParam.getId(); //单位id
        String startTime = rStatZwAlarmCountWParam.getStartTime();
        String endTime = rStatZwAlarmCountWParam.getEndTime();

        //获取电压等级的字典
        List<DictData> voltageLevelList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE.getCode()).getData();
        //将电压信息转成map，key：id  value：name
        Map<String, String> voltageLevelMap = voltageLevelList.stream().collect(Collectors.toMap(DictData::getId, DictData::getName));
        List<String> data = deptFeignClient.getDepSonSelfCodetByCode(id).getData();
        //查询当前单位下监测点idList
        LambdaQueryWrapper<Monitor> monitorLambdaQueryWrapper = new LambdaQueryWrapper<>();
        monitorLambdaQueryWrapper.in(Monitor::getOrgId, data);
        List<String> orgMeasurementPointIdList = iMonitorService.list(monitorLambdaQueryWrapper).stream().map(Monitor::getId).collect(Collectors.toList());
        //如果单位下没有监测点，直接返回空集合
        if (CollUtil.isEmpty(orgMeasurementPointIdList)) {
            return new ArrayList<>();
        }
        //以周为时间段，查询告警超过四次的监测点信息
        LambdaQueryWrapper<RMpTargetWarnD> targetWarnWrapper = new LambdaQueryWrapper<>();
        targetWarnWrapper
                .in(RMpTargetWarnD::getMeasurementPointId, orgMeasurementPointIdList)
                .ge(StringUtils.isNotBlank(startTime), RMpTargetWarnD::getDataDate, startTime)
                .le(StringUtils.isNotBlank(endTime), RMpTargetWarnD::getDataDate, endTime)
                .eq(RMpTargetWarnD::getIsEffective,1);
        List<RMpTargetWarnD> measurementPointIdList = rMpTargetWarnDService.list(targetWarnWrapper);
        if (CollUtil.isEmpty(measurementPointIdList)) {
            return new ArrayList<>();
        }
        //获取大于四次的监测点集合
        List<String> MonitorIdsQuartic = measurementPointIdList.stream()
                .filter(obj -> obj.getIsWarn() == 1)
                .collect(Collectors.groupingBy(RMpTargetWarnD::getMeasurementPointId, Collectors.counting()))
                .entrySet().stream()
                .filter(e -> e.getValue() >= 4).map(x->x.getKey()).collect(Collectors.toList());

        // 计算问题严重的监测点
        Map<String, Double> avgStatusOneCountByAlarmId = measurementPointIdList.stream()
                .filter(alarm -> alarm.getIsWarn() == 1)
                .collect(Collectors.groupingBy(RMpTargetWarnD::getMeasurementPointId, Collectors.counting()))
                .entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue() / 7.0));

        // 对 map 中的 value 进行从大到小的排序，并且排除 value 为 0 的元素
        List<String> sortedAvgStatusOneCountByAlarmId = avgStatusOneCountByAlarmId.entrySet().stream()
                .filter(e -> e.getValue() != 0)
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        if(CollUtil.isNotEmpty(sortedAvgStatusOneCountByAlarmId)){
            // 获取前 30% 的告警 id 数量
            double v = sortedAvgStatusOneCountByAlarmId.size() * 0.3;
            int top30PercentCount = (int) (v<1?Math.ceil(v):v);
            MonitorIdsQuartic.addAll(sortedAvgStatusOneCountByAlarmId.subList(0,top30PercentCount));
        }

        //去除集合中重复的监测点id，得到最终的有严重问题的监测点id集合
        monitorLambdaQueryWrapper.clear();
        monitorLambdaQueryWrapper.in(Monitor::getId, MonitorIdsQuartic);
        List<Monitor> monitorList = iMonitorService.list(monitorLambdaQueryWrapper);
        //提取出监测点相关的变电站id，获取变电站电压等级map（key: 变电站id  value: 电压等级）
        List<String> powerIdList = monitorList.stream().map(Monitor::getPowerrId).collect(Collectors.toList());
        LambdaQueryWrapper<StatationStat> stationLambdaQueryWrapper = new LambdaQueryWrapper<>();
        stationLambdaQueryWrapper.in(StatationStat::getPowerId, powerIdList);
        Map<String, String> stationVoltageLevelMap = iStatationStatService.list(stationLambdaQueryWrapper).stream()
                .collect(Collectors.toMap(StatationStat::getPowerId, StatationStat::getVoltageLevel));
        //封装返回数据
        List<ProblemMonitorDetailVO> resultList = monitorList.stream().map(item -> {
            ProblemMonitorDetailVO problemMonitorDetailVO = new ProblemMonitorDetailVO();
            problemMonitorDetailVO.setOrgNo(item.getOrgId()); //单位id
            problemMonitorDetailVO.setOrgName(item.getOrgName()); //单位名称
            problemMonitorDetailVO.setMonitorId(item.getId()); //监测点id
            problemMonitorDetailVO.setMonitorName(item.getName()); //监测点名称
            problemMonitorDetailVO.setPowerName(item.getPowerrName()); //变电站名称
            problemMonitorDetailVO.setVoltageLevel(stationVoltageLevelMap.get(item.getPowerrId())); //变电站电压等级id
            problemMonitorDetailVO.setVoltageLevelName(voltageLevelMap.get(stationVoltageLevelMap.get(item.getPowerrId()))); //变电站电压等级
            return problemMonitorDetailVO;
        }).collect(Collectors.toList());
        return resultList;
    }
}
