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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.common.utils.PubUtils;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.harmonic.pojo.po.RMpDevEvaluateDetailPO;
import com.njcn.prepare.harmonic.mapper.mysql.area.RMpDevEvaluateDetailPOMapper;
import com.njcn.prepare.harmonic.mapper.mysql.line.ROperatingMonitorDMapper;
import com.njcn.prepare.harmonic.pojo.bo.CalculatedParam;
import com.njcn.prepare.harmonic.pojo.mysql.ROperatingMonitorDPO;
import com.njcn.prepare.harmonic.pojo.po.RMpDevSolveDetailPO;
import com.njcn.prepare.harmonic.service.mysql.area.RMpDevEvaluateDetailPOService;
import com.njcn.prepare.harmonic.service.mysql.device.RMpDevSolveDetailPOService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 
 * Description:
 * 接口文档访问地址：http://serverIP:port/swagger-ui.html
 * Date: 2022/12/1  9:18【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RMpDevEvaluateDetailPOServiceImpl extends MppServiceImpl<RMpDevEvaluateDetailPOMapper, RMpDevEvaluateDetailPO> implements RMpDevEvaluateDetailPOService{

    private final ROperatingMonitorDMapper rOperatingMonitorDMapper;
    private final RMpDevSolveDetailPOService rMpDevSolveDetailPOService;
    private final CommTerminalGeneralClient commTerminalGeneralClient;


    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void devEvaluateDetail(CalculatedParam calculatedParam) {
        log.info(LocalDateTime.now()+"===>终端评价详情-日统计算法开始");
        List<RMpDevEvaluateDetailPO> rMpDevEvaluateDetailPOList = new ArrayList<>();
        List<ROperatingMonitorDPO> operatingMonitorList = new ArrayList<>();
        List<RMpDevSolveDetailPO> devSolveDetailList = new ArrayList<>();
        List<LineDevGetDTO> lineDevGetList = new ArrayList<>();
        List<String> deviceList = new ArrayList<>();
        List<String> lineIds = calculatedParam.getIdList();
        //以尺寸100分片,查询数据
        List<List<String>> pendingIds =  ListUtils.partition(lineIds,5);
        for (List<String> pendingId : pendingIds) {
            //获取监测点评价详情
            LambdaQueryWrapper<ROperatingMonitorDPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(ROperatingMonitorDPO::getMeasurementPointId,pendingId)
                    .eq(ROperatingMonitorDPO::getDataDate,calculatedParam.getDataDate());
            List<ROperatingMonitorDPO> ls = rOperatingMonitorDMapper.selectList(lambdaQueryWrapper);
            operatingMonitorList.addAll(ls);
            //监测点详情
            lineDevGetList.addAll(commTerminalGeneralClient.getMonitorDetailList(pendingId).getData());
        }
        Map<String,List<ROperatingMonitorDPO>> map1 = operatingMonitorList.stream().collect(Collectors.groupingBy(ROperatingMonitorDPO::getDevId));
        Map<String,List<LineDevGetDTO>> map2 = lineDevGetList.stream().collect(Collectors.groupingBy(LineDevGetDTO::getDevId));
        //获取装置集合
        map2.forEach((k,v)->{
            if (!deviceList.contains(k)){
                deviceList.add(k);
            }
        });
        //以尺寸100分片,查询装置数据
        List<List<String>> devIds =  ListUtils.partition(deviceList,100);
        for (List<String> devId : devIds) {
            //获取终端消缺明细数据
            LambdaQueryWrapper<RMpDevSolveDetailPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(RMpDevSolveDetailPO::getDeviceId,devId)
                    .eq(RMpDevSolveDetailPO::getDataDate,calculatedParam.getDataDate());
            List<RMpDevSolveDetailPO> ls = rMpDevSolveDetailPOService.list(lambdaQueryWrapper);
            devSolveDetailList.addAll(ls);
        }
        Map<String,List<RMpDevSolveDetailPO>> map3 = devSolveDetailList.stream().collect(Collectors.groupingBy(RMpDevSolveDetailPO::getDeviceId));
        map2.forEach((k,v)->{
            RMpDevEvaluateDetailPO rMpDevEvaluateDetailPO = new RMpDevEvaluateDetailPO();
            rMpDevEvaluateDetailPO.setDeviceId(k);
            rMpDevEvaluateDetailPO.setDataDate(LocalDateTimeUtil.parseDate(calculatedParam.getDataDate(),DatePattern.NORM_DATE_FORMATTER));
            rMpDevEvaluateDetailPO.setDevScore(Objects.isNull(map3.get(k)) ? null: PubUtils.getDefectSeverity(map3.get(k).get(0).getDefectSeverity()));
            if (!Objects.isNull(map1.get(k))){
                List<ROperatingMonitorDPO> ls = map1.get(k);
                double d1 = ls.stream().mapToDouble(po -> po.getDataIntegrityRate().doubleValue()).average().getAsDouble();
                double d2 = ls.stream().mapToDouble(po -> po.getIndexIntegrityRate().doubleValue()).average().getAsDouble();
                rMpDevEvaluateDetailPO.setDevDataRate(d1*100.0);
                rMpDevEvaluateDetailPO.setDevTargetRate(d2*100.0);
                long count = ls.stream().filter(po -> po.getIsUnusual() == 1 && po.getDataIntegrityRate().compareTo(new BigDecimal(0.95)) == 1).count();
                double d3 = (double) count / ls.size();
                rMpDevEvaluateDetailPO.setDevEffectiveRate(d3*100.0);
            }else {
                rMpDevEvaluateDetailPO.setDevDataRate(0.0);
                rMpDevEvaluateDetailPO.setDevTargetRate(0.0);
                rMpDevEvaluateDetailPO.setDevEffectiveRate(0.0);
            }
            rMpDevEvaluateDetailPOList.add(rMpDevEvaluateDetailPO);
        });
        if (CollectionUtil.isNotEmpty(rMpDevEvaluateDetailPOList)){
            this.saveOrUpdateBatchByMultiId(rMpDevEvaluateDetailPOList,100);
        }
    }
}
