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


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.device.pms.pojo.po.GeneratrixWire;
import com.njcn.device.pms.pojo.po.Monitor;
import com.njcn.device.pq.pojo.po.RStatIntegrityD;
import com.njcn.harmonic.pojo.po.day.RStatDataVDPO;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.po.upload.RDimBusUpD;
import com.njcn.prepare.harmonic.mapper.mysql.area.PmsMonitorPOMapper;
import com.njcn.prepare.harmonic.mapper.mysql.day.RStatDataVDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.day.RStatIntegrityDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.day.RStatLimitRateDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.dim.GeneratrixWireMapper;
import com.njcn.prepare.harmonic.mapper.mysql.upload.RDimBusUpDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.upload.RDimBusUpMMapper;
import com.njcn.harmonic.pojo.po.upload.RDimBusUpM;
import com.njcn.prepare.harmonic.service.mysql.upload.IRDimBusUpMService;
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 java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 母线越限详情 服务实现类
 * </p>
 *
 * @author cdf
 * @since 2024-05-09
 */
@Service
@RequiredArgsConstructor
public class RDimBusUpMServiceImpl extends MppServiceImpl<RDimBusUpMMapper, RDimBusUpM> implements IRDimBusUpMService {

    private final RDimBusUpDMapper rDimBusUpDMapper;

    private final RStatIntegrityDMapper rStatIntegrityDMapper;

    private final DicDataFeignClient dicDataFeignClient;

    private final PmsMonitorPOMapper pmsMonitorPOMapper;

    private final GeneratrixWireMapper generatrixWireMapper;

    private final RStatDataVDMapper rStatDataVDMapper;

    private final RStatLimitRateDMapper rStatLimitRateDMapper;

    @Override
    public void handMonth(String date) {
        TimeInterval timeInterval = new TimeInterval();
        DateTime start = DateUtil.beginOfMonth(DateUtil.parse(date,DatePattern.NORM_DATE_PATTERN));
        DateTime end = DateUtil.parse(date);
        LocalDate statDate = LocalDate.parse(DateUtil.format(start, DatePattern.NORM_DATE_PATTERN));

        QueryWrapper<RStatIntegrityD> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("line_index","avg(real_time/due_time) as integrityData","avg(real_time) as realTime","avg(due_time) as dueTime").
                between("time_id",start,end).last("group by line_index");
        List<RStatIntegrityD> rStatIntegrityDList = rStatIntegrityDMapper.selectList(queryWrapper);
        //TODO 测试暂时注释
        //List<RStatIntegrityD> integrityDList = rStatIntegrityDList.stream().filter(it->it.getIntegrityData()>0.95).collect(Collectors.toList());

        DictData dictData = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.RUN.getCode(), DicDataTypeEnum.LINE_STATE.getCode()).getData();
        List<Monitor> monitorList = pmsMonitorPOMapper.selectList(new LambdaQueryWrapper<Monitor>().eq(Monitor::getIsUpToGrid,1).eq(Monitor::getMonitorState,dictData.getId()));
        List<String> allMonitorIds = monitorList.stream().map(Monitor::getId).distinct().collect(Collectors.toList());

        List<String> lineIds = monitorList.stream().map(Monitor::getLineId).distinct().collect(Collectors.toList());
        List<GeneratrixWire> generatrixWireList = generatrixWireMapper.selectList(new LambdaQueryWrapper<GeneratrixWire>().in(GeneratrixWire::getId,lineIds));
        Map<String,GeneratrixWire>  generatrixWireMap = generatrixWireList.stream().collect(Collectors.toMap(GeneratrixWire::getId, Function.identity()));

        List<RStatDataVDPO> rStatDataVDPOList = rStatDataVDMapper.selectList(new QueryWrapper<RStatDataVDPO>()
                        .select("line_id","phasic_type","avg(rms) as rms").lambda()
                .in(RStatDataVDPO::getLineId,allMonitorIds)
                .between(RStatDataVDPO::getTime,start,end)
                .eq(RStatDataVDPO::getValueType,"AVG")
                .in(RStatDataVDPO::getPhaseType, Stream.of("A","B","C").collect(Collectors.toList()))
                .groupBy(RStatDataVDPO::getLineId,RStatDataVDPO::getPhaseType));
        Map<String,List<RStatDataVDPO>> vMap = rStatDataVDPOList.stream().collect(Collectors.groupingBy(RStatDataVDPO::getLineId));

        StringBuilder stringBuilder = new StringBuilder();
        for(int i =2;i<26;i++){
            stringBuilder.append(",").append("sum(uharm_").append(i).append("_overtime) as ").append("uharm_").append(i).append("_overtime");
        }
        List<RStatLimitRateDPO> rStatLimitRateDPOList = rStatLimitRateDMapper.selectList(
                new QueryWrapper<RStatLimitRateDPO>().select("my_index as lineId,phasic_type,sum(all_time) as allTime,sum(flicker_all_time) as flickerAllTime,sum(freq_dev_overtime) as freqDevOvertime," +
                                "sum(voltage_dev_overtime) as voltageDevOvertime,sum(ubalance_overtime) as ubalanceOvertime,sum(flicker_overtime) as flickerOvertime,sum(uaberrance_overtime)as uaberranceOvertime,sum(i_neg_overtime)as i_neg_overtime"+stringBuilder)
                        .lambda().in(RStatLimitRateDPO::getLineId,allMonitorIds)
                        .between(RStatLimitRateDPO::getTime,start,end)
                        .in(RStatLimitRateDPO::getPhasicType,Stream.of("A","B","C").collect(Collectors.toList())).groupBy(RStatLimitRateDPO::getLineId,RStatLimitRateDPO::getPhasicType));
        Map<String,List<RStatLimitRateDPO>> limtMap = rStatLimitRateDPOList.stream().collect(Collectors.groupingBy(RStatLimitRateDPO::getLineId));

        Map<String,List<Monitor>> listMap = monitorList.stream().collect(Collectors.groupingBy(Monitor::getLineId));
        List<RDimBusUpM> poList = new ArrayList<>();
        listMap.forEach((key,val)->{
            List<String> monitorIds = val.stream().map(Monitor::getId).collect(Collectors.toList());
            List<RStatIntegrityD> temIntegrity = rStatIntegrityDList.stream().filter(it->monitorIds.contains(it.getLineIndex())).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(temIntegrity)){
                RStatIntegrityD maxR =  temIntegrity.stream().max(Comparator.comparing(RStatIntegrityD::getIntegrityData)).orElse(null);
                assert maxR != null;

                GeneratrixWire generatrixWire = generatrixWireMap.get(key);
                String effectIds = temIntegrity.stream().map(RStatIntegrityD::getLineIndex).collect(Collectors.joining(StrUtil.COMMA));

                Double temAvg= 3.14159;
                if(vMap.containsKey(maxR.getLineIndex())){
                    List<RStatDataVDPO> vList = vMap.get(maxR.getLineIndex());
                    temAvg =  vList.stream().mapToDouble(RStatDataVDPO::getRms).average().orElse(3.14159);
                }

                if(limtMap.containsKey(maxR.getLineIndex())){
                    List<RStatLimitRateDPO> rStatLimitRateDPOS = limtMap.get(maxR.getLineIndex());
                    for(RStatLimitRateDPO rStatLimitRateDPO: rStatLimitRateDPOS){
                        RDimBusUpM rDimBusUpM = new RDimBusUpM();
                        BeanUtil.copyProperties(rStatLimitRateDPO,rDimBusUpM);
                        rDimBusUpM.setBusId(key);
                        rDimBusUpM.setMidBusId(generatrixWire.getMidBusId());
                        rDimBusUpM.setStatisticDate(statDate);
                        rDimBusUpM.setEffectId(maxR.getLineIndex());
                        rDimBusUpM.setEffectIds(effectIds);
                        rDimBusUpM.setVoltageLevel(generatrixWire.getScale());
                        rDimBusUpM.setV(temAvg);
                        poList.add(rDimBusUpM);
                    }
                }
            }
        });

        this.saveOrUpdateBatchByMultiId(poList);
        System.out.println("母线月算法执行时间(S)-----------------------"+timeInterval.intervalSecond());
    }

    public String findMostFrequentElement(List<RDimBusUpD> list) {
        Map<String, Integer> frequencyMap = new HashMap<>();
        for (RDimBusUpD item : list) {
            if (StrUtil.isNotBlank(item.getEffectId())) {
                frequencyMap.put(item.getEffectId(), frequencyMap.getOrDefault(item.getEffectId(), 0) + 1);
            }

        }

        // 找到出现次数最多的元素
        String mostFrequentElement = null;
        int maxFrequency = 0;
        for (Map.Entry<String, Integer> entry : frequencyMap.entrySet()) {
            if (entry.getValue() > maxFrequency) {
                maxFrequency = entry.getValue();
                mostFrequentElement = entry.getKey();
            }
        }
        return mostFrequentElement;
    }
}
