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


import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.device.biz.pojo.dto.DeptGetChildrenMoreDTO;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.pms.pojo.po.Monitor;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.po.dim.RDimObjTargetY;
import com.njcn.prepare.harmonic.mapper.mysql.dim.RDimObjTargetYMapper;
import com.njcn.prepare.harmonic.mapper.mysql.line.PmsMonitorMapper;
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.dim.IRDimObjTargetYService;
import com.njcn.prepare.harmonic.service.mysql.line.ROperatingMonitorService;
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 lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author cdf
 * @since 2023-11-22
 */
@Service
@RequiredArgsConstructor
public class RDimObjTargetYServiceImpl extends MppServiceImpl<RDimObjTargetYMapper, RDimObjTargetY> implements IRDimObjTargetYService {
    private final DicDataFeignClient dicDataFeignClient;
    private final ROperatingMonitorService rOperatingMonitorService;
    private final IRStatLimitRateDService irStatLimitRateDService;
    //咨询后直接用Mapper查询，这个算法只用pms补考虑pq，后续不知道要不要改
    private final PmsMonitorMapper pmsMonitorMapper;
    @Override
    public void handleYear(CalculatedParam<DeptGetChildrenMoreDTO> calculatedParam) {
        List<RDimObjTargetY> rdiObjTargetys = new ArrayList<>();

        String begin = LocalDateTimeUtil.format(DateUtil.beginOfYear(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)).toLocalDateTime(),DatePattern.NORM_DATE_PATTERN);
        String end = LocalDateTimeUtil.format(DateUtil.endOfYear(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN)).toLocalDateTime(),DatePattern.NORM_DATE_PATTERN);
        LocalDate localDate = LocalDateTimeUtil.parseDate(begin, DatePattern.NORM_DATE_PATTERN);

        List<DictData> indicatorTypeDate = dicDataFeignClient.getDicDataByTypeCode(
                DicDataTypeEnum.STEADY_STATIS.getCode()).getData();
        //过滤电压总谐波畸变率、2-50次谐波电流、三相不平衡、负序电流、闪变
        List<DictData> finalIndicatorTypeDate  = indicatorTypeDate.stream().filter(temp -> Objects.equals(temp.getCode(), DicDataEnum.VOLTAGE_DEV.getCode()) ||
                Objects.equals(temp.getCode(), DicDataEnum.FLICKER.getCode()) ||
                Objects.equals(temp.getCode(), DicDataEnum.PHASE_VOLTAGE.getCode()) ||
                Objects.equals(temp.getCode(), DicDataEnum.THD_V.getCode())||
                Objects.equals(temp.getCode(), DicDataEnum.HARMONIC_CURRENT.getCode())).collect(Collectors.toList());

        List<DictData> monitoringLabels = dicDataFeignClient.getDicDataByTypeCode(
                DicDataTypeEnum.MONITORING_LABELS.getCode()).getData();
        //过滤监测对象包括牵引站、风电场、光伏电站、重要，敏感用户
        List<String> monitoringLabelIds = monitoringLabels.stream().filter(temp -> Objects.equals(
                temp.getCode(), DicDataEnum.POWER_STATION.getCode()) ||
                Objects.equals(temp.getCode(), DicDataEnum.WIND_FARM.getCode()) ||
                Objects.equals(temp.getCode(), DicDataEnum.SENSITIVE_USERS.getCode()) ||
                Objects.equals(temp.getCode(), DicDataEnum.IMPORTANT_USERS.getCode())||
                Objects.equals(temp.getCode(), DicDataEnum.TRACTION_STATION.getCode())).map(DictData::getId).collect(Collectors.toList());

        for (DeptGetChildrenMoreDTO deptGetChildrenMoreDTO : calculatedParam.getIdList()) {
            if (!CollectionUtils.isEmpty(deptGetChildrenMoreDTO.getLineBaseList())) {
                List<LineDevGetDTO> lineBaseList = deptGetChildrenMoreDTO.getLineBaseList();
                if (CollectionUtils.isEmpty(lineBaseList)) {
                    continue;
                }
                List<String> collect2 = lineBaseList.stream().map(LineDevGetDTO::getPointId).collect(Collectors.toList());
                List<ROperatingMonitorDPO> list = rOperatingMonitorService.lambdaQuery().
                        in(ROperatingMonitorDPO::getMeasurementPointId, collect2).
                        between(ROperatingMonitorDPO::getDataDate, begin,end).
                        ge(ROperatingMonitorDPO::getDataIntegrityRate, 0.95).
                        eq(ROperatingMonitorDPO::getIsUnusual, 1).list();
                List<Monitor> monitorList = new ArrayList<>();

                if(CollectionUtils.isEmpty(list)){
                    continue;
                }
                List<String> collect = list.stream().map(ROperatingMonitorDPO::getMeasurementPointId).distinct().collect(Collectors.toList());
                monitorList = pmsMonitorMapper.queryEffectiveBusbars(collect);
                monitorList = monitorList.stream().filter(temp -> monitoringLabelIds.contains(temp.getMonitorTag())).collect(Collectors.toList());
                Map<String, List<Monitor>> collect1 = monitorList.stream().
                        collect(Collectors.groupingBy(Monitor::getMonitorTag));

                List<String> linids = monitorList.stream().map(Monitor::getId).collect(Collectors.toList());
                List<RStatLimitRateDPO> rStatLimitRateDPOS = irStatLimitRateDService.findList(linids, begin, end);
                if(CollectionUtils.isEmpty(rStatLimitRateDPOS)){
                    continue;
                }
                collect1.forEach((tag, monitors)->{
                    finalIndicatorTypeDate.stream().forEach(temp->{
                        RDimObjTargetY rDimObjTargetY = new RDimObjTargetY();
                        rDimObjTargetY.setOrgId(deptGetChildrenMoreDTO.getUnitId());
                        rDimObjTargetY.setStatisDate(localDate);
                        rDimObjTargetY.setTargetType(temp.getId());
                        rDimObjTargetY.setObjectType(tag);
                        //有效接入监测点
                        long effectivePoint = monitors.stream().map(Monitor::getId).distinct().count();
                        //对应指标的超表监测点
                        int overLimitsPoint = overLimitsPointCount(temp,rStatLimitRateDPOS);
                        double v = Double.valueOf(overLimitsPoint) / effectivePoint;
                        rDimObjTargetY.setMonitorRate(Math.round(v * 100.0) / 100.0);
                        rDimObjTargetY.setLimitRate(Math.round(v * 100.0) / 100.0);
                        rdiObjTargetys.add(rDimObjTargetY);
                    });
                });


            }
        }
        if (!CollectionUtils.isEmpty(rdiObjTargetys)) {
            this.saveOrUpdateBatchByMultiId(rdiObjTargetys, 500);
        }
    }

    private int overLimitsPointCount(DictData temp, List<RStatLimitRateDPO> rStatLimitRateDPOS) {
        Integer overLimiCount =0;

        if (Objects.equals(temp.getCode(), DicDataEnum.THD_V.getCode())) {
            overLimiCount = Integer.valueOf(rStatLimitRateDPOS.stream().filter(po->po.getUaberranceOvertime()>0).distinct().count()+"");
        } else if ( Objects.equals(temp.getCode(), DicDataEnum.HARMONIC_CURRENT.getCode())) {
            overLimiCount = Integer.valueOf(rStatLimitRateDPOS.stream().filter(po->
                            po.getIharm2Overtime()>0||
                            po.getIharm3Overtime() >0||
                            po.getIharm4Overtime() >0||
                            po.getIharm5Overtime() >0||
                            po.getIharm6Overtime() >0||
                            po.getIharm7Overtime() >0||
                            po.getIharm8Overtime() >0||
                            po.getIharm9Overtime() >0||
                            po.getIharm10Overtime() >0||
                            po.getIharm11Overtime() >0||
                            po.getIharm12Overtime() >0||
                            po.getIharm13Overtime() >0||
                            po.getIharm14Overtime() >0||
                            po.getIharm15Overtime() >0||
                            po.getIharm16Overtime() >0||
                            po.getIharm17Overtime() >0||
                            po.getIharm18Overtime() >0||
                            po.getIharm19Overtime() >0||
                            po.getIharm20Overtime() >0||
                            po.getIharm21Overtime() >0||
                            po.getIharm22Overtime() >0||
                            po.getIharm23Overtime() >0||
                            po.getIharm24Overtime() >0||
                            po.getIharm25Overtime() >0).distinct().count()+"");

        } else if ( Objects.equals(temp.getCode(), DicDataEnum.PHASE_VOLTAGE.getCode())) {
            overLimiCount = Integer.valueOf(rStatLimitRateDPOS.stream().filter(po->po.getUaberranceOvertime()>0).distinct().count()+"");
        } else if ( Objects.equals(temp.getCode(), DicDataEnum.FLICKER.getCode())) {
            overLimiCount = Integer.valueOf(rStatLimitRateDPOS.stream().filter(po->po.getFlickerOvertime()>0).distinct().count()+"");
        } else if (Objects.equals(temp.getCode(), DicDataEnum.NEG_CURRENT.getCode())){
            overLimiCount = Integer.valueOf(rStatLimitRateDPOS.stream().filter(po->po.getINegOvertime()>0).distinct().count()+"");
        }
        return overLimiCount;
    }
}
