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

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.device.biz.pojo.dto.DeptGetChildrenMoreDTO;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.pms.api.MonitorClient;
import com.njcn.device.pms.api.PmsGeneratrixClient;
import com.njcn.device.pms.api.StatationStatClient;
import com.njcn.device.pms.pojo.dto.PmsGeneratrixDTO;
import com.njcn.device.pms.pojo.param.PmsBaseParam;
import com.njcn.device.pms.pojo.param.PmsGeneratrixParam;
import com.njcn.device.pms.pojo.po.Monitor;
import com.njcn.device.pms.pojo.po.StatationStat;
import com.njcn.event.pojo.po.RMpEventDetailD;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.po.send.ConverterIndexStatisticsPO;
import com.njcn.prepare.harmonic.mapper.mysql.send.ConverterIndexStatisticsPOMapper;
import com.njcn.prepare.harmonic.pojo.bo.CalculatedParam;
import com.njcn.prepare.harmonic.pojo.mysql.ROperatingMonitorDPO;
import com.njcn.prepare.harmonic.service.mysql.day.IRStatLimitRateDService;
import com.njcn.prepare.harmonic.service.mysql.line.RMpEventDetailDService;
import com.njcn.prepare.harmonic.service.mysql.line.ROperatingMonitorService;
import com.njcn.prepare.harmonic.service.mysql.send.ConverterIndexStatisticsPOService;
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.vo.PvTerminalTreeVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 
 * Description:
 * Date: 2023/12/11  11:35【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
public class ConverterIndexStatisticsPOServiceImpl extends ServiceImpl<ConverterIndexStatisticsPOMapper, ConverterIndexStatisticsPO> implements ConverterIndexStatisticsPOService {


    private final MonitorClient monitorClient;
    private final DeptFeignClient deptFeignClient;
    private final StatationStatClient statationStatClient;
    private final PmsGeneratrixClient pmsGeneratrixClient;
    private final DicDataFeignClient dicDataFeignClient;
    private final IRStatLimitRateDService irStatLimitRateDService;
    private final ROperatingMonitorService rOperatingMonitorService;
    private final RMpEventDetailDService rMpEventDetailDService;

    @Override
    public void handlerDay(CalculatedParam<DeptGetChildrenMoreDTO> calculatedParam) {

        List<ConverterIndexStatisticsPO> converterIndexStatisticsPOList = new ArrayList<>();
        LocalDate localDate = LocalDateTimeUtil.parseDate(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN);


        List<DictData> supvVoltageDicList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE.getCode()).getData();
        //过滤交流电压等级
        List<String> exchangeList = supvVoltageDicList.stream().filter(temp -> temp.getName().contains("交流")).map(DictData::getId).collect(Collectors.toList());
        Map<String, DictData> mapVoltage = supvVoltageDicList.stream().collect(Collectors.toMap(DictData::getId, Function.identity()));
        List<StatationStat> stationList = statationStatClient.getstatationStatList(new PmsBaseParam()).getData();
        List<DictData> data1 = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.LINE_STATE.getCode()).getData();
        DictData run = data1.stream().filter(temp->Objects.equals(temp.getCode(),DicDataEnum.RUN.getCode())).findFirst().get();
        List<PvTerminalTreeVO> deptList = deptFeignClient.allDeptList().getData();
        Map<String, PvTerminalTreeVO> mapCode = deptList.stream().collect(Collectors.toMap(PvTerminalTreeVO::getCode, Function.identity()));
        Map<String, PvTerminalTreeVO> mapList = deptList.stream().collect(Collectors.toMap(PvTerminalTreeVO::getId, Function.identity()));

        for (DeptGetChildrenMoreDTO deptGetChildrenMoreDTO : calculatedParam.getIdList()) {

            ConverterIndexStatisticsPO converterIndexStatisticsPO = new ConverterIndexStatisticsPO();
            converterIndexStatisticsPO.setStatisticalDate(calculatedParam.getDataDate());
            converterIndexStatisticsPO.setStatisticalType("03");

            if (mapCode.containsKey(deptGetChildrenMoreDTO.getUnitId())) {
                PvTerminalTreeVO pvTerminalTreeVO = mapCode.get(deptGetChildrenMoreDTO.getUnitId());
                String[] split = (pvTerminalTreeVO.getPids() + StrUtil.COMMA + pvTerminalTreeVO.getId())
                        .split(StrUtil.COMMA);
                if (split.length != 4) {
                 continue;
                }
                for (int i = 2; i < split.length; i++) {
                    //省
                    if (i == 2) {
                        if (mapList.containsKey(split[i])) {
                            pvTerminalTreeVO = mapList.get(split[i]);
                            converterIndexStatisticsPO.setProvinceName(pvTerminalTreeVO.getName());
                            converterIndexStatisticsPO.setProvinceId(pvTerminalTreeVO.getCode());
                            converterIndexStatisticsPO.setStatisticalLevel("3");
                        }
                    }
                    //市
                    if (i == 3) {
                        if (mapList.containsKey(split[i])) {
                            pvTerminalTreeVO = mapList.get(split[i]);
                            converterIndexStatisticsPO.setCityName(pvTerminalTreeVO.getName());
                            converterIndexStatisticsPO.setCityId(pvTerminalTreeVO.getCode());
                            converterIndexStatisticsPO.setStatisticalLevel("4");

                        }
                    }
                }
            }
            converterIndexStatisticsPO.setId(converterIndexStatisticsPO.getCityId()+"-"+calculatedParam.getDataDate());

            if (!CollectionUtils.isEmpty(deptGetChildrenMoreDTO.getLineBaseList())) {
                List<LineDevGetDTO> lineBaseList = deptGetChildrenMoreDTO.getLineBaseList();
                List<String> tempLineList = lineBaseList.stream().map(LineDevGetDTO::getPointId).collect(Collectors.toList());
                List<Monitor> tempMonitor = monitorClient.getMonitorList(tempLineList).getData();
                tempMonitor = tempMonitor.stream().filter(temp -> Objects.equals(temp.getMonitorState(), run.getId())).collect(Collectors.toList());
                List<String> tempIds = tempMonitor.stream().map(Monitor::getId).collect(Collectors.toList());
                List<String> generatrixIds = tempMonitor.stream().map(Monitor::getLineId).distinct().collect(Collectors.toList());
                List<String> powerrIds = tempMonitor.stream().map(Monitor::getPowerrId).distinct().collect(Collectors.toList());
                PmsGeneratrixParam pmsGeneratrixParam = new PmsGeneratrixParam();
                pmsGeneratrixParam.setGeneratrixIds(generatrixIds);
                List<PmsGeneratrixDTO> data = pmsGeneratrixClient.getGeneratrixInfo(pmsGeneratrixParam).getData();
                List<String> exchangelineIds = data.stream().filter(temp -> exchangeList.contains(temp.getGeneratrixVoltageLevel())).
                        map(PmsGeneratrixDTO::getGeneratrixId).collect(Collectors.toList());
                converterIndexStatisticsPO.setOnlineAlternatingBusNum(exchangelineIds.size());
                converterIndexStatisticsPO.setOnlineConverterNum(powerrIds.size());
                //监测监测点
                List<ROperatingMonitorDPO> list = new ArrayList<>();
                if (!CollectionUtils.isEmpty(tempIds)) {
                    list = rOperatingMonitorService.lambdaQuery().
                            in(ROperatingMonitorDPO::getMeasurementPointId, tempIds).
                            eq(ROperatingMonitorDPO::getDataDate, calculatedParam.getDataDate()).
                            ge(ROperatingMonitorDPO::getDataIntegrityRate, 0.95).
                            eq(ROperatingMonitorDPO::getIsUnusual, 1).list();

                }
                //
                List<String> collect = list.stream().map(ROperatingMonitorDPO::getMeasurementPointId).collect(Collectors.toList());
                //监测监测点
                List<Monitor> supervisLines = tempMonitor.stream().filter(temp -> collect.contains(temp.getId())).distinct().collect(Collectors.toList());
                List<String> supervispowerrIds = supervisLines.stream().map(Monitor::getPowerrId).distinct().collect(Collectors.toList());

                List<String> supervisgeneratrixIds = supervisLines.stream().map(Monitor::getLineId).distinct().collect(Collectors.toList());
                List<String> supervisexchangelineIds = data.stream().filter(temp -> supervisgeneratrixIds.contains(temp.getGeneratrixVoltageLevel())).
                        map(PmsGeneratrixDTO::getGeneratrixId).collect(Collectors.toList());

                converterIndexStatisticsPO.setMonitorAlternatingBusCount(supervisexchangelineIds.size());
                converterIndexStatisticsPO.setMonitorConverterCount(supervispowerrIds.size());
                converterIndexStatisticsPO.setMonitorAlternatingBusNum(supervisexchangelineIds.size());
                converterIndexStatisticsPO.setMonitorConverterNum(supervispowerrIds.size());
                //发生暂态，稳态的监测点集合
                List<String> abnormallines;
                if (!CollectionUtils.isEmpty(tempIds)) {
                    List<RStatLimitRateDPO> rStatLimitRateDPOS = irStatLimitRateDService.lambdaQuery().in(RStatLimitRateDPO::getLineId,tempIds).eq(RStatLimitRateDPO::getTime,localDate).eq(RStatLimitRateDPO::getPhasicType,"T").list();
                    List<RMpEventDetailD> rMpEventDetailDList = rMpEventDetailDService.lambdaQuery().in(RMpEventDetailD::getMeasurementPointId, tempIds).eq(RMpEventDetailD::getDataDate, localDate).list();
                    List<String> limitIds = rStatLimitRateDPOS.stream().filter(temp ->
                            (temp.getVoltageDevOvertime() +
                                    temp.getFlickerOvertime() +
                                    temp.getUbalanceOvertime() +
                                    temp.getUharm2Overtime() +
                                    temp.getUharm3Overtime() +
                                    temp.getUharm4Overtime() +
                                    temp.getUharm5Overtime() +
                                    temp.getUharm6Overtime() +
                                    temp.getUharm7Overtime() +
                                    temp.getUharm8Overtime() +
                                    temp.getUharm9Overtime() +
                                    temp.getUharm10Overtime() +
                                    temp.getUharm11Overtime() +
                                    temp.getUharm12Overtime() +
                                    temp.getUharm13Overtime() +
                                    temp.getUharm14Overtime() +
                                    temp.getUharm15Overtime() +
                                    temp.getUharm16Overtime() +
                                    temp.getUharm17Overtime() +
                                    temp.getUharm18Overtime() +
                                    temp.getUharm19Overtime() +
                                    temp.getUharm20Overtime() +
                                    temp.getUharm21Overtime() +
                                    temp.getUharm22Overtime() +
                                    temp.getUharm23Overtime() +
                                    temp.getUharm24Overtime() +
                                    temp.getUharm25Overtime() +
                                    temp.getIharm2Overtime() +
                                    temp.getIharm3Overtime() +
                                    temp.getIharm4Overtime() +
                                    temp.getIharm5Overtime() +
                                    temp.getIharm6Overtime() +
                                    temp.getIharm7Overtime() +
                                    temp.getIharm8Overtime() +
                                    temp.getIharm9Overtime() +
                                    temp.getIharm10Overtime() +
                                    temp.getIharm11Overtime() +
                                    temp.getIharm12Overtime() +
                                    temp.getIharm13Overtime() +
                                    temp.getIharm14Overtime() +
                                    temp.getIharm15Overtime() +
                                    temp.getIharm16Overtime() +
                                    temp.getIharm17Overtime() +
                                    temp.getIharm18Overtime() +
                                    temp.getIharm19Overtime() +
                                    temp.getIharm20Overtime() +
                                    temp.getIharm21Overtime() +
                                    temp.getIharm22Overtime() +
                                    temp.getIharm23Overtime() +
                                    temp.getIharm24Overtime() +
                                    temp.getIharm25Overtime() +
                                    temp.getInuharm1Overtime() +
                                    temp.getInuharm2Overtime() +
                                    temp.getInuharm3Overtime() +
                                    temp.getInuharm4Overtime() +
                                    temp.getInuharm5Overtime() +
                                    temp.getInuharm6Overtime() +
                                    temp.getInuharm7Overtime() +
                                    temp.getInuharm8Overtime() +
                                    temp.getInuharm9Overtime() +
                                    temp.getInuharm10Overtime() +
                                    temp.getInuharm11Overtime() +
                                    temp.getInuharm12Overtime() +
                                    temp.getInuharm13Overtime() +
                                    temp.getInuharm14Overtime() +
                                    temp.getInuharm15Overtime() +
                                    temp.getInuharm16Overtime() +
                                    temp.getFreqDevOvertime() +
                                    temp.getINegOvertime()) > 0
                    ).map(RStatLimitRateDPO::getLineId).distinct().collect(Collectors.toList());
                    List<String> eventLineIds = rMpEventDetailDList.stream().filter(temp -> (temp.getInterruptTimes() +
                            temp.getSagTimes() +
                            temp.getSwellTimes()) > 0).map(RMpEventDetailD::getMeasurementPointId).distinct().collect(Collectors.toList());

                    limitIds.retainAll(eventLineIds);
                    abnormallines = limitIds;
                } else {
                    abnormallines = new ArrayList<>();
                }
                List<Monitor>  abnormalmonitor = tempMonitor.stream().filter(temp -> abnormallines.contains(temp.getId())).distinct().collect(Collectors.toList());

                List<String> abnormalpowerrIds = supervisLines.stream().map(Monitor::getPowerrId).distinct().collect(Collectors.toList());

                List<String> abnormalgeneratrixIds = supervisLines.stream().map(Monitor::getLineId).distinct().collect(Collectors.toList());
                converterIndexStatisticsPO.setAbnormalBusNum(abnormalgeneratrixIds.size());
                converterIndexStatisticsPO.setAbnormalBusCount(abnormalgeneratrixIds.size());
                converterIndexStatisticsPO.setAbnormalConverterCount(abnormalpowerrIds.size());
                converterIndexStatisticsPO.setAbnormalConverterNum(abnormalpowerrIds.size());

                converterIndexStatisticsPO.setAbnormalBusRate(divideAndRound(converterIndexStatisticsPO.getAbnormalBusNum(),generatrixIds.size()));
                converterIndexStatisticsPO.setAbnormalBusAvgRate(divideAndRound(converterIndexStatisticsPO.getAbnormalBusNum(),generatrixIds.size()));

                converterIndexStatisticsPO.setAbnormalConverterRate(divideAndRound(converterIndexStatisticsPO.getAbnormalConverterNum(),powerrIds.size()));
                converterIndexStatisticsPO.setAbnormalConverterAvgRate(divideAndRound(converterIndexStatisticsPO.getAbnormalConverterNum(),powerrIds.size()));

                converterIndexStatisticsPO.setMonitorConverterRate(divideAndRound(converterIndexStatisticsPO.getMonitorConverterNum(),powerrIds.size()));
                converterIndexStatisticsPO.setMonitorAlternatingBusRate(divideAndRound(converterIndexStatisticsPO.getMonitorAlternatingBusNum(),generatrixIds.size()));
            }
            converterIndexStatisticsPOList.add(converterIndexStatisticsPO);

        }
        if(!CollectionUtils.isEmpty(converterIndexStatisticsPOList)){
            this.saveOrUpdateBatch(converterIndexStatisticsPOList);
        }
    }
    /**
    * @Description: divideAndRound
    * @Param:  两个int做除法返回BigDecimal保留2位小数 考虑到被除数为0的情况
    * @return: java.math.BigDecimal
    * @Author: clam
    * @Date: 2023/12/12
    */
    public  BigDecimal divideAndRound(Integer a, Integer b) {
        if (b == 0) {
          return BigDecimal.valueOf(0.00);
        }
        BigDecimal num1 = new BigDecimal(a);
        BigDecimal num2 = new BigDecimal(b);
        BigDecimal result = num1.divide(num2, 2, RoundingMode.HALF_UP);
        return result;
    }
}
