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

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.device.biz.commApi.CommLineClient;
import com.njcn.device.biz.pojo.dto.LineDTO;
import com.njcn.harmonic.pojo.po.RMpPartHarmonicDetailD;
import com.njcn.harmonic.pojo.po.RMpSurplusHarmonicDetailD;
import com.njcn.prepare.harmonic.mapper.mysql.line.RMpPartHarmonicDetailDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.line.RMpPassRateDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.line.RMpSurplusHarmonicDetailDMapper;
import com.njcn.prepare.harmonic.pojo.bo.CalculatedParam;
import com.njcn.harmonic.pojo.po.algorithm.line.RMpMonitorEvaluateD;
import com.njcn.prepare.harmonic.pojo.mysql.po.line.RMpPassRateDPO;
import com.njcn.prepare.harmonic.pojo.mysql.po.line.RMpPassRateMPO;
import com.njcn.prepare.harmonic.pojo.mysql.po.line.RMpPassRateQPO;
import com.njcn.prepare.harmonic.pojo.mysql.po.line.RMpPassRateYPO;
import com.njcn.prepare.harmonic.service.mysql.line.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.ListUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Description:
 * 接口文档访问地址：http://serverIP:port/swagger-ui.html
 * Date: 2023/2/28  15:39【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
public class RMpPassRateDServiceImpl extends MppServiceImpl<RMpPassRateDMapper, RMpPassRateDPO> implements RMpPassRateDService {
    private final CommLineClient commLineClient;
    private final RMpMonitorEvaluateDService rMpMonitorEvaluateDService;
    private final RMpPartHarmonicDetailDMapper rMpPartHarmonicDetailDMapper;
    private final RMpSurplusHarmonicDetailDMapper rMpSurplusHarmonicDetailDMapper;

    private final RMpPassRateMService rMpPassRateMService;
    private final RMpPassRateQService rMpPassRateQService;
    private final RMpPassRateYService rMpPassRateYService;


    @Override
    public void handleDay(CalculatedParam calculatedParam) {

        LocalDate localDate = LocalDateTimeUtil.parseDate(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN);
        List<List<String>> pendingIds = ListUtils.partition(calculatedParam.getIdList(), 100);
        LocalDateTime begin = LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));
        LocalDateTime end = LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));

        List<RMpPassRateDPO> rMpPassRateDPOList = new ArrayList<> ( );
        QueryWrapper<RMpMonitorEvaluateD> rMpMonitorEvaluateDPOQueryWrapper = new QueryWrapper<>( );

        QueryWrapper<RMpPartHarmonicDetailD> queryWrapper = new QueryWrapper<>( );
        QueryWrapper<RMpSurplusHarmonicDetailD> surplusHarmonicDetailDQueryWrapper = new QueryWrapper<>( );

        for (List<String> pendingId : pendingIds) {

            List<LineDTO> lineDTOList = commLineClient.getLineDetailBatch(pendingId).getData();
            for (LineDTO lineDTO : lineDTOList) {
                Integer statisticalInterval = lineDTO.getTimeInterval ();

                rMpMonitorEvaluateDPOQueryWrapper.clear ();
                rMpMonitorEvaluateDPOQueryWrapper.select ("effective_minute_count").
                        eq ("measurement_point_id", lineDTO.getLineId()).
                        eq ("data_date", calculatedParam.getDataDate ( ));
                RMpMonitorEvaluateD one = rMpMonitorEvaluateDService.getOne (rMpMonitorEvaluateDPOQueryWrapper);
                if (Objects.isNull(one)) {
                    continue;

                }
                queryWrapper.clear ( );
                queryWrapper.select ("freq_times", "v_dev_times").
                        eq ("measurement_point_id", lineDTO.getLineId()).
                        eq ("data_date", calculatedParam.getDataDate ( ));
                RMpPartHarmonicDetailD rMpPartHarmonicDetailD = rMpPartHarmonicDetailDMapper.selectOne (queryWrapper);
                if (Objects.isNull(rMpPartHarmonicDetailD)) {
                    continue;
                }
                surplusHarmonicDetailDQueryWrapper.clear ( );
                surplusHarmonicDetailDQueryWrapper.select ("flicker_times").
                        eq ("measurement_point_id", lineDTO.getLineId()).
                        eq ("data_date", calculatedParam.getDataDate ( ));
                RMpSurplusHarmonicDetailD rMpSurplusHarmonicDetailD = rMpSurplusHarmonicDetailDMapper.selectOne (surplusHarmonicDetailDQueryWrapper);
                if (Objects.isNull(rMpSurplusHarmonicDetailD)) {
                    continue;
                }
                RMpPassRateDPO rMpPassRateDPO = new RMpPassRateDPO ( );
                rMpPassRateDPO.setMeasurementPointId (lineDTO.getLineId());
                rMpPassRateDPO.setDataDate (localDate);
                rMpPassRateDPO.setEffectiveTime (statisticalInterval *one.getEffectiveMinuteCount ());
                rMpPassRateDPO.setFreqTime (statisticalInterval * rMpPartHarmonicDetailD.getFreqTimes ( ));
                rMpPassRateDPO.setVDevTime (statisticalInterval * rMpPartHarmonicDetailD.getVDevTimes ( ));
                rMpPassRateDPO.setFlickerTime (2*60* rMpSurplusHarmonicDetailD.getFlickerTimes ( ));
                rMpPassRateDPOList.add (rMpPassRateDPO);

            }
        }

        this.saveOrUpdateBatchByMultiId(rMpPassRateDPOList, 500);
    }

    @Override
    public void handleMonth(CalculatedParam calculatedParam) {
        List<RMpPassRateMPO> rMpPassRateMPOList = new ArrayList<> ( );

        List<String> lineIds = calculatedParam.getIdList();

        //以尺寸1000分片
        List<List<String>> pendingIds = ListUtils.partition(lineIds, 1000);
        DateTime begin = DateUtil.beginOfMonth(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));
        DateTime end = DateUtil.endOfMonth(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));
        LocalDate localDate = LocalDateTimeUtil.parseDate( DateUtil.format(begin, DatePattern.NORM_DATE_PATTERN), DatePattern.NORM_DATE_PATTERN);

        QueryWrapper<RMpPassRateDPO> queryWrapper = new QueryWrapper<> ();

        for (List<String> pendingId : pendingIds) {
            queryWrapper.clear();
            queryWrapper.in ("measurement_point_id", pendingId).
                    between("data_date",begin,end);
            List<RMpPassRateDPO> rMpPassRateDPOList = this.getBaseMapper ( ).selectList (queryWrapper);

            if (CollectionUtils.isEmpty(rMpPassRateDPOList)) {
                continue;

            }
            Map<String, List<RMpPassRateDPO>> collect1 = rMpPassRateDPOList.stream().collect(Collectors.groupingBy(RMpPassRateDPO::getMeasurementPointId));
            collect1.forEach((k,v)->{
                RMpPassRateMPO rMpPassRateMPO = new RMpPassRateMPO();
                rMpPassRateMPO.setMeasurementPointId (k);
                rMpPassRateMPO.setDataDate (localDate);
                int sumEffectiveTime = v.stream ( ).mapToInt (RMpPassRateDPO::getEffectiveTime).sum ( );
                int sumFreqTime = v.stream ( ).mapToInt (RMpPassRateDPO::getFreqTime).sum ( );
                int sumDevTime = v.stream ( ).mapToInt (RMpPassRateDPO::getVDevTime).sum ( );
                int sumFlickerTime = v.stream ( ).mapToInt (RMpPassRateDPO::getFlickerTime).sum ( );

                rMpPassRateMPO.setFreqPassRate (calculatePassRate(sumEffectiveTime,sumFreqTime));
                rMpPassRateMPO.setVDevPassRate (calculatePassRate(sumEffectiveTime,sumDevTime));
                rMpPassRateMPO.setFlickerPassRate (calculatePassRate(sumEffectiveTime,sumFlickerTime));
                rMpPassRateMPOList.add (rMpPassRateMPO);
            });
        }

        rMpPassRateMService.saveOrUpdateBatchByMultiId (rMpPassRateMPOList, 500);
    }

    @Override
    public void handleQtr(CalculatedParam calculatedParam) {

        List<RMpPassRateQPO> rMpPassRateQPOList = new ArrayList<> ( );
        List<String> lineIds = calculatedParam.getIdList();

        //以尺寸1000分片
        List<List<String>> pendingIds = ListUtils.partition(lineIds, 1000);
        DateTime begin = DateUtil.beginOfQuarter(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));
        DateTime end = DateUtil.endOfQuarter(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));
        LocalDate localDate = LocalDateTimeUtil.parseDate( DateUtil.format(begin, DatePattern.NORM_DATE_PATTERN), DatePattern.NORM_DATE_PATTERN);

        QueryWrapper<RMpPassRateDPO> queryWrapper = new QueryWrapper<> ();
        for (List<String> pendingId : pendingIds) {
            queryWrapper.clear();
            queryWrapper.in ("measurement_point_id", pendingId).
                    between("data_date",begin,end);
            List<RMpPassRateDPO> rMpPassRateDPOList = this.getBaseMapper ( ).selectList (queryWrapper);

            if (CollectionUtils.isEmpty(rMpPassRateDPOList)) {
                continue;

            }
            Map<String, List<RMpPassRateDPO>> collect1 = rMpPassRateDPOList.stream().collect(Collectors.groupingBy(RMpPassRateDPO::getMeasurementPointId));
            collect1.forEach((k,v)->{
                RMpPassRateQPO rMpPassRateQPO = new RMpPassRateQPO();
                rMpPassRateQPO.setMeasurementPointId (k);
                rMpPassRateQPO.setDataDate (localDate );
                int sumEffectiveTime = rMpPassRateDPOList.stream ( ).mapToInt (RMpPassRateDPO::getEffectiveTime).sum ( );
                int sumFreqTime = rMpPassRateDPOList.stream ( ).mapToInt (RMpPassRateDPO::getFreqTime).sum ( );
                int sumDevTime = rMpPassRateDPOList.stream ( ).mapToInt (RMpPassRateDPO::getVDevTime).sum ( );
                int sumFlickerTime = rMpPassRateDPOList.stream ( ).mapToInt (RMpPassRateDPO::getFlickerTime).sum ( );

                rMpPassRateQPO.setFreqPassRate (calculatePassRate(sumEffectiveTime,sumFreqTime));
                rMpPassRateQPO.setVDevPassRate (calculatePassRate(sumEffectiveTime,sumDevTime));
                rMpPassRateQPO.setFlickerPassRate (calculatePassRate(sumEffectiveTime,sumFlickerTime));
                rMpPassRateQPOList.add (rMpPassRateQPO);
            });

        };
        rMpPassRateQService.saveOrUpdateBatchByMultiId (rMpPassRateQPOList, 500);
    }

    @Override
    public void handleYear(CalculatedParam calculatedParam) {
        List<RMpPassRateYPO> rMpPassRateYPOList = new ArrayList<> ( );
        List<String> lineIds = calculatedParam.getIdList();

        //以尺寸1000分片
        List<List<String>> pendingIds = ListUtils.partition(lineIds, 1000);
        DateTime begin = DateUtil.beginOfYear(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));
        DateTime end = DateUtil.endOfYear(DateUtil.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_PATTERN));
        LocalDate localDate = LocalDateTimeUtil.parseDate( DateUtil.format(begin, DatePattern.NORM_DATE_PATTERN), DatePattern.NORM_DATE_PATTERN);
        QueryWrapper<RMpPassRateDPO> queryWrapper = new QueryWrapper<> ();
        for (List<String> pendingId : pendingIds) {
            queryWrapper.clear();
            queryWrapper.in ("measurement_point_id", pendingId).
                    between("data_date",begin,end);
            List<RMpPassRateDPO> rMpPassRateDPOList = this.getBaseMapper ( ).selectList (queryWrapper);

            if (CollectionUtils.isEmpty(rMpPassRateDPOList)) {
                continue;

            }
            Map<String, List<RMpPassRateDPO>> collect1 = rMpPassRateDPOList.stream().collect(Collectors.groupingBy(RMpPassRateDPO::getMeasurementPointId));
            collect1.forEach((k,v)->{
                RMpPassRateYPO rMpPassRateYPO = new RMpPassRateYPO();
                rMpPassRateYPO.setMeasurementPointId (k);
                rMpPassRateYPO.setDataDate (localDate);
                int sumEffectiveTime = rMpPassRateDPOList.stream ( ).mapToInt (RMpPassRateDPO::getEffectiveTime).sum ( );
                int sumFreqTime = rMpPassRateDPOList.stream ( ).mapToInt (RMpPassRateDPO::getFreqTime).sum ( );
                int sumDevTime = rMpPassRateDPOList.stream ( ).mapToInt (RMpPassRateDPO::getVDevTime).sum ( );
                int sumFlickerTime = rMpPassRateDPOList.stream ( ).mapToInt (RMpPassRateDPO::getFlickerTime).sum ( );

                rMpPassRateYPO.setFreqPassRate (calculatePassRate(sumEffectiveTime,sumFreqTime));
                rMpPassRateYPO.setVDevPassRate (calculatePassRate(sumEffectiveTime,sumDevTime));
                rMpPassRateYPO.setFlickerPassRate (calculatePassRate(sumEffectiveTime,sumFlickerTime));
                rMpPassRateYPOList.add (rMpPassRateYPO);
            });

        };
        rMpPassRateYService.saveOrUpdateBatchByMultiId (rMpPassRateYPOList, 500);

    }


    private Double calculatePassRate(int sumEffectiveTime, int sumFreqTime) {
        Double result =0.00;
        if(sumEffectiveTime==0||sumEffectiveTime<=sumFreqTime){
            return result;
        }
        result = ((sumEffectiveTime-sumFreqTime)*100.0/sumEffectiveTime);
        return result;
    }
}
