package com.njcn.prepare.harmonic.service.mysql.Impl.line;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.device.pms.api.DistributionMonitorClient;
import com.njcn.device.pms.api.MonitorClient;
import com.njcn.device.pms.pojo.po.DistributionMonitor;
import com.njcn.device.pms.pojo.po.Monitor;
import com.njcn.device.pq.pojo.po.DataV;
import com.njcn.device.pq.pojo.po.RMpIntegrityD;
import com.njcn.influx.pojo.po.DataFlicker;
import com.njcn.prepare.harmonic.constant.AlgorithmParam;
import com.njcn.prepare.harmonic.mapper.mysql.line.RMpIntegrityDMapper;
import com.njcn.prepare.harmonic.pojo.oracle.PqLinedetailPO;
import com.njcn.prepare.harmonic.pojo.param.LineParam;
import com.njcn.prepare.harmonic.pojo.vo.DataFlickerOracleVO;
import com.njcn.prepare.harmonic.pojo.vo.DataVOracleVO;
import com.njcn.prepare.harmonic.service.influxdb.DataIntegrityRateInfluxService;
import com.njcn.prepare.harmonic.service.mysql.line.DataIntegrityRateService;
import com.njcn.prepare.harmonic.service.oracle.DataFlickerOracleService;
import com.njcn.prepare.harmonic.service.oracle.DataVOraclePOService;
import com.njcn.prepare.harmonic.service.oracle.PqLinedetailPOService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 数据完整率算法
 *
 * @author qijian
 * @version 1.0.0
 * @createTime 2022/11/29 - 10:09
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DataIntegrityRateServiceImpl implements DataIntegrityRateService {

    private final RMpIntegrityDMapper rMpIntegrityDMapper;

    private final DistributionMonitorClient distributionMonitorClient;

    private final MonitorClient monitorClient;

    private final DataIntegrityRateInfluxService dataIntegrityRateInfluxService;

    private final PqLinedetailPOService pqLinedetailPOService;

    private final DataVOraclePOService dataVOraclePOService;

    private final DataFlickerOracleService dataFlickerOracleService;

    /**
     * 监测点日数据完整率
     * @author qijian
     * @date 2022/11/29
     */
    @Override
    @Async("asyncExecutor")
    public boolean lineDataIntegrityRate(LineParam lineParam) {
        if (Objects.equals(lineParam.getDataSource(), AlgorithmParam.ORACLE_DATA)) {
            hanlderOracleData(lineParam);
        } else if (Objects.equals(lineParam.getDataSource(), AlgorithmParam.INFLUX_DATA)) {
            hanlderInfluxData(lineParam);
        }
        return true;

    }

    /**
     * 处理数据（influxDB>mysql）
     * @author qijian
     * @date 2022/12/01
     */
    private void hanlderInfluxData(LineParam lineParam) {
        //初始化
        Date date = DateUtil.parse(lineParam.getDataDate());
        List<String> lineIds = lineParam.getLineIds();
        Integer lineType = lineParam.getLineType();
        Integer type = lineParam.getType();
        //有效接入分钟数量：根据监测点编号获取统计间隔（15），1440 / 15 = 有效接入分钟数量
        Integer effectiveMinuteCount = 1440 / AlgorithmParam.TIME_INTERVAL;

        //获取监测点数据，进行入库操作
        if (CollUtil.isEmpty(lineIds)){
            //先获取主网的监测点信息，再获取配网的监测点信息
            List<Monitor> monitorList = monitorClient.getMonitorList(lineIds).getData();
            for (Monitor monitor : monitorList) {
                processInfluxData(date,type,effectiveMinuteCount, monitor.getLineId());
            }
            List<DistributionMonitor> distributionMonitorList = distributionMonitorClient.distributionMonitorList(lineIds).getData();
            for (DistributionMonitor distributionMonitor : distributionMonitorList) {
                processInfluxData(date,type,effectiveMinuteCount, distributionMonitor.getMonitorId());
            }
        } else {
            //根据监测点类型取数据
            for (String lineId : lineIds) {
                processInfluxData(date,type,effectiveMinuteCount, lineId);
            }
        }
    }

    /**
     * 处理数据（influxDB>mysql）
     * @author qijian
     * @date 2022/12/01
     */
    private void processInfluxData(Date date, Integer type, Integer effectiveMinuteCount, String lineId) {
        RMpIntegrityD rMpIntegrityD = new RMpIntegrityD();
        rMpIntegrityD.setEffectiveMinuteCount(effectiveMinuteCount);
        rMpIntegrityD.setMeasurementPointId(lineId);
        rMpIntegrityD.setDataDate(date);

        //1、根据data_v表获取五项稳态指标日数量
        DataV dataV = dataIntegrityRateInfluxService.getFiveSteadyData(lineId, date,type);

        rMpIntegrityD.setFreqCount(dataV == null ? 0 : dataV.getFreqCount());
        rMpIntegrityD.setPhaseVoltageCount(dataV == null ? 0 : dataV.getRmsCount());
        rMpIntegrityD.setLineVoltageCount(dataV == null ? 0 : dataV.getRmsLvrCount());
        rMpIntegrityD.setVThdCount(dataV == null ? 0 : dataV.getVThdCount());
        rMpIntegrityD.setUnbalanceCount(dataV == null ? 0 : dataV.getVUnbalanceCount());

        //2、根据data_flicker表获取两项闪变指标数量
        DataFlicker dataFlicker = dataIntegrityRateInfluxService.getTwoFlickerData(lineId, date,type);
        rMpIntegrityD.setPstCount(dataFlicker == null ? 0 : dataFlicker.getPstCount());
        rMpIntegrityD.setPltCount(dataFlicker == null ? 0 : dataFlicker.getPltCount());

        //3、存库
        addData(rMpIntegrityD);
    }

    /**
     * 处理数据（oracle>mysql）
     * @author qijian
     * @date 2022/12/01
     */
    private void hanlderOracleData(LineParam lineParam) {
        //初始化
        Date date = DateUtil.parse(lineParam.getDataDate());
        List<String> lineIds = lineParam.getLineIds();
        Integer lineType = lineParam.getLineType();
        Integer type = lineParam.getType();
        //有效接入分钟数量：根据监测点编号获取统计间隔（15），1440 / 15 = 有效接入分钟数量
        Integer effectiveMinuteCount = 1440 / AlgorithmParam.TIME_INTERVAL;

        //获取监测点数据，进行入库操作
        if (CollUtil.isEmpty(lineIds)){
            //先获取主网的监测点信息，再获取配网的监测点信息
            List<Monitor> monitorList = monitorClient.getMonitorList(lineIds).getData();
            for (Monitor monitor : monitorList) {
                //根据mysql监测点取oracle监测点信息
                PqLinedetailPO pqLinedetailPO = pqLinedetailPOService.getOracleIndexIdByMonitorId(monitor.getLineId());
                //处理数据（oracle>mysql）
                processOracleData(date,type,effectiveMinuteCount, monitor.getLineId(),pqLinedetailPO == null ? 0 : pqLinedetailPO.getLineIndex());
            }
            List<DistributionMonitor> distributionMonitorList = distributionMonitorClient.distributionMonitorList(lineIds).getData();
            for (DistributionMonitor distributionMonitor : distributionMonitorList) {
                //根据mysql监测点取oracle监测点信息
                PqLinedetailPO pqLinedetailPO = pqLinedetailPOService.getOracleIndexIdByMonitorId(distributionMonitor.getMonitorId());
                //处理数据（oracle>mysql）
                processOracleData(date,type,effectiveMinuteCount, distributionMonitor.getMonitorId(),pqLinedetailPO == null ? 0 : pqLinedetailPO.getLineIndex());
            }
        } else {
            //根据监测点类型取数据
            for (String lineId : lineIds) {
                //根据mysql监测点取oracle监测点信息
                PqLinedetailPO pqLinedetailPO = pqLinedetailPOService.getOracleIndexIdByMonitorId(lineId);
                //处理数据（oracle>mysql）
                processOracleData(date,type,effectiveMinuteCount, lineId, pqLinedetailPO == null ? 0 : pqLinedetailPO.getLineIndex());
            }
        }
    }

    /**
     * 处理数据（oracle>mysql）
     * @author qijian
     * @date 2022/12/01
     */
    private void processOracleData(Date date, Integer type, Integer effectiveMinuteCount, String lineId, Integer lineIndex) {
        RMpIntegrityD rMpIntegrityD = new RMpIntegrityD();
        rMpIntegrityD.setEffectiveMinuteCount(effectiveMinuteCount);
        rMpIntegrityD.setMeasurementPointId(lineId);
        rMpIntegrityD.setDataDate(date);

        //1、根据data_v表获取五项稳态指标日数量
        DataVOracleVO dataVOracleVO = dataVOraclePOService.getFiveCountForDataIntegrityRate(lineIndex, date, type);
        rMpIntegrityD.setFreqCount(dataVOracleVO == null ? 0 : dataVOracleVO.getFreqCount());
        rMpIntegrityD.setPhaseVoltageCount(dataVOracleVO == null ? 0 : dataVOracleVO.getRmsCount());
        rMpIntegrityD.setLineVoltageCount(dataVOracleVO == null ? 0 : dataVOracleVO.getRmsLvrCount());
        rMpIntegrityD.setVThdCount(dataVOracleVO == null ? 0 : dataVOracleVO.getVThdCount());
        rMpIntegrityD.setUnbalanceCount(dataVOracleVO == null ? 0 : dataVOracleVO.getVUnbalanceCount());

        //2、根据data_flicker表获取两项闪变指标数量
        DataFlickerOracleVO dataFlickerOracleVO = dataFlickerOracleService.getTwoCountForDataIntegrityRate(lineIndex, date, type);
        rMpIntegrityD.setPstCount(dataFlickerOracleVO == null ? 0 : dataFlickerOracleVO.getPstCount());
        rMpIntegrityD.setPltCount(dataFlickerOracleVO == null ? 0 : dataFlickerOracleVO.getPltCount());

        //3、存库
        addData(rMpIntegrityD);
    }

    /**
     * 存入数据库
     * @author qijian
     * @date 2022/12/01
     */
    private void addData(RMpIntegrityD rMpIntegrityD) {
        LambdaQueryWrapper<RMpIntegrityD> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(RMpIntegrityD::getMeasurementPointId, rMpIntegrityD.getMeasurementPointId()).eq(RMpIntegrityD::getDataDate, rMpIntegrityD.getDataDate());
        RMpIntegrityD rMpIntegrityDOne = rMpIntegrityDMapper.selectOne(lambdaQueryWrapper);
        if (Objects.nonNull(rMpIntegrityDOne)) {
            rMpIntegrityDMapper.update(rMpIntegrityD, lambdaQueryWrapper);
        } else {
            rMpIntegrityDMapper.insert(rMpIntegrityD);
        }
    }

}
