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


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.device.pms.api.LineIntegrityDataClient;
import com.njcn.device.pms.api.MonitorClient;
import com.njcn.device.pms.pojo.param.DataQualityDetailsParam;
import com.njcn.device.pms.pojo.param.gw.TypicalSourceParam;
import com.njcn.device.pms.pojo.vo.gw.TypicalOverIndex;
import com.njcn.device.pms.pojo.vo.gw.TypicalOverStation;
import com.njcn.device.pms.pojo.vo.gw.TypicalSourceEffectiveLine;
import com.njcn.device.pms.pojo.vo.gw.TypicalSourceOnLine;
import com.njcn.device.pq.pojo.po.RStatIntegrityD;
import com.njcn.harmonic.mapper.RStatLimitTargetDMapper;
import com.njcn.harmonic.mapper.upload.PmsRunStatisticDMapper;
import com.njcn.harmonic.mapper.upload.PmsRunStatisticMMapper;
import com.njcn.harmonic.mapper.upload.PmsRunStatisticYMapper;
import com.njcn.harmonic.pojo.po.upload.PmsRunStatisticD;
import com.njcn.harmonic.pojo.po.upload.PmsRunStatisticM;
import com.njcn.harmonic.pojo.po.upload.PmsRunStatisticY;
import com.njcn.harmonic.pojo.vo.RStatLimitTargetVO;
import com.njcn.harmonic.service.upload.TypicalSourceLoadDownService;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.web.pojo.dto.PmsPage;
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;

@Service
@RequiredArgsConstructor
public class TypicalSourceLoadDownServiceImpl implements TypicalSourceLoadDownService {

    private final MonitorClient monitorClient;
    private final RStatLimitTargetDMapper rStatLimitTargetDMapper;
    private final LineIntegrityDataClient integrityDataClient;
    private final PmsRunStatisticDMapper pmsRunStatisticDMapper;
    private final PmsRunStatisticMMapper pmsRunStatisticMMapper;
    private final PmsRunStatisticYMapper pmsRunStatisticYMapper;


    @Override
    public PmsPage<TypicalSourceOnLine> getOnlineDetail(TypicalSourceParam param) {
        setMonitorIds(param);
        Page<TypicalSourceOnLine> typicalSourceOnLinePage = monitorClient.monitorTypicalList(param).getData();
        PmsPage pmsPage = BeanUtil.copyProperties(typicalSourceOnLinePage, PmsPage.class);
        pmsPage.setList(typicalSourceOnLinePage.getRecords());
        return pmsPage;

    }
    @Override
    public PmsPage<TypicalSourceOnLine> getMonitorDetail(TypicalSourceParam param) {
        setMonitorIds(param);
        DataQualityDetailsParam integrityParam=new DataQualityDetailsParam();
        integrityParam.setStartTime(param.getStartTime());
        integrityParam.setEndTime(param.getEndTime());
        integrityParam.setCheckRules(param.getMonitorIds());
        List<RStatIntegrityD> integrityDS = integrityDataClient.getIntegrityData(integrityParam).getData();
        Map<String, List<RStatIntegrityD>> integrityMap = integrityDS.stream().collect(Collectors.groupingBy(RStatIntegrityD::getLineIndex));
        List<String> ids = new ArrayList<>();
        integrityMap.forEach((paramKey, paramValue) -> {
            int realTime = paramValue.stream().mapToInt(RStatIntegrityD::getRealTime).sum();
            int dueTime = paramValue.stream().mapToInt(RStatIntegrityD::getDueTime).sum();
            float v = NumberUtil.round(realTime * 100.0 / dueTime, 2).floatValue();
            if(v>95.0){
                ids.add(paramKey);
            }
        });
        param.setMonitorIds(ids);
        Page<TypicalSourceOnLine> typicalSourceOnLinePage = monitorClient.monitorTypicalList(param).getData();
        PmsPage pmsPage = BeanUtil.copyProperties(typicalSourceOnLinePage, PmsPage.class);
        pmsPage.setList(typicalSourceOnLinePage.getRecords());
        return pmsPage;
    }

    @Override
    public PmsPage<TypicalSourceEffectiveLine> getValidMonitorList(TypicalSourceParam param) {
        setMonitorIds(param);
        List<TypicalSourceEffectiveLine> info = new ArrayList<>();
        Page<TypicalSourceOnLine> monitorList = monitorClient.monitorTypicalList(param).getData();
        List<String> monitorIds = monitorList.getRecords().stream().map(TypicalSourceOnLine::getId).collect(Collectors.toList());
        if(CollUtil.isNotEmpty(monitorIds)) {
            DataQualityDetailsParam integrityParam=new DataQualityDetailsParam();
            integrityParam.setStartTime(param.getStartTime());
            integrityParam.setEndTime(param.getEndTime());
            integrityParam.setCheckRules(monitorIds);
            List<RStatIntegrityD> integrityDS = integrityDataClient.getIntegrityData(integrityParam).getData();
            Map<String, List<RStatIntegrityD>> integritDMap = new HashMap<>();
            if(CollUtil.isNotEmpty(integrityDS)){
                integritDMap.putAll(integrityDS.stream().collect(Collectors.groupingBy(RStatIntegrityD::getLineIndex)));
            }
            TypicalSourceEffectiveLine line ;
            for (TypicalSourceOnLine monitor : monitorList.getRecords()) {
                line = new TypicalSourceEffectiveLine();
                //母线信息
                line.setBusId(monitor.getBusId());
                line.setBusName(monitor.getName());
                line.setBusVoltageLevel(monitor.getBusVoltageLevel());
                line.setBusVoltageLevelName(monitor.getBusVoltageLevelName());
                line.setCityOrg(monitor.getCityOrg());
                line.setCityOrgName(monitor.getCityOrgName());
                line.setId(monitor.getId());
                line.setMaintOrg(monitor.getMaintOrg());
                line.setMaintOrgName(monitor.getMaintOrgName());
                line.setMonitorId(monitor.getMonitorId());
                line.setMonitorName(monitor.getName());
                //运行状态
                line.setStatus(monitor.getRunStatus());
                line.setStatusName(monitor.getRunStatusName());
                line.setStationId(monitor.getStationId());
                line.setStationName(monitor.getStationName());
                line.setStatDate(param.getStatDate());
                if(integritDMap.containsKey(monitor.getId())){
                    List<RStatIntegrityD> integrityDSList = integritDMap.get(monitor.getId());
                    line.setActualCollectNum(integrityDSList.stream().mapToInt(RStatIntegrityD::getRealTime).sum());
                    line.setExpectCollectNum(integrityDSList.stream().mapToInt(RStatIntegrityD::getDueTime).sum());
                    line.setDataFullRate(NumberUtil.round(line.getActualCollectNum()*100.0/ line.getExpectCollectNum(), 2).floatValue());
                }else {
                    line.setActualCollectNum(0);
                    line.setExpectCollectNum(0);
                    line.setDataFullRate(0.0f);
                }
//                line.setWhetherOptimal();
//                line.setWhetherOptimalName();
                info.add(line);
            }
        }
        PmsPage pmsPage = BeanUtil.copyProperties(monitorList, PmsPage.class);
        pmsPage.setList(info);
        return pmsPage;
    }

    @Override
    public PmsPage<TypicalOverStation> getOverStationList(TypicalSourceParam param) {
        setMonitorIds(param);
        List<TypicalOverStation> info=new ArrayList<>();
        //获取监测点信息的信息
        Page<TypicalSourceOnLine> monitorList = monitorClient.monitorTypicalList(param).getData();
        //根据监测点id集合获取超标监测信息
        List<String> monitorIds = monitorList.getRecords().stream().map(TypicalSourceOnLine::getId).distinct().collect(Collectors.toList());
        //获取超标监测点天数
        List<RStatLimitTargetVO> sumTargetDetails = rStatLimitTargetDMapper.getSumTargetDetails(monitorIds,
                param.getStartTime(),
                param.getEndTime());
        Map<String, RStatLimitTargetVO> targetDetailMap = sumTargetDetails.stream()
                .collect(Collectors.toMap(RStatLimitTargetVO::getLineId, Function.identity()));
        TypicalOverStation overStation;
        for (TypicalSourceOnLine record : monitorList.getRecords()) {
            overStation = new TypicalOverStation();
            overStation.setAuxiliarySubstationId(record.getAuxiliarySubstationId());
            overStation.setAuxiliarySubstationName(record.getAuxiliarySubstationName());
            overStation.setAuxiliaryVoltageLevel(record.getAuxiliaryVoltageLevel());
            overStation.setAuxiliaryVoltageLevelName(record.getAuxiliaryVoltageLevelName());
            overStation.setBusVoltageLevel(record.getBusVoltageLevel());
            overStation.setBusVoltageLevelName(record.getBusVoltageLevelName());
            overStation.setCapacity(record.getCapacity());
            overStation.setCityOrg(record.getCityOrg());
            overStation.setCityOrgName(record.getCityOrgName());
            overStation.setEffectMonitorNum(record.getEffectMonitorNum());
            overStation.setId(record.getId());
            overStation.setMainSubstationId(record.getMainSubstationId());
            overStation.setMainSubstationName(record.getMainSubstationName());
            overStation.setMainVoltageLevel(record.getMainVoltageLevel());
            overStation.setMainVoltageLevelName(record.getMainVoltageLevelName());
            overStation.setMaintOrg(record.getMaintOrg());
            overStation.setMaintOrgName(record.getMaintOrgName());
            overStation.setMonitorObjectType(record.getMonitorObjectType());
            overStation.setMonitorObjectTypeName(record.getMonitorObjectTypeName());
            overStation.setName(record.getName());
            overStation.setRailWayName(record.getRailWayName());
            overStation.setRailWayNumber(record.getRailWayNumber());
            overStation.setRailWayType(record.getRailWayType());
            overStation.setRailWayTypeName(record.getRailWayTypeName());
            overStation.setRunStatus(record.getRunStatus());
            overStation.setRunStatusName(record.getRunStatusName());
            overStation.setStationId(record.getStationId());
            overStation.setStationName(record.getStationName());
            overStation.setStationType(record.getStationType());
            overStation.setStationVoltageLevel(record.getStationVoltageLevel());
            overStation.setStationVoltageLevelName(record.getStationVoltageLevelName());
            overStation.setTradeCode(record.getTradeCode());
            overStation.setTradeCodeName(record.getTradeCodeName());
            overStation.setVoltageLevel(record.getVoltageLevel());
            overStation.setVoltageLevelName(record.getVoltageLevelName());

            overStation.setMonitorDate(param.getStatDate());
            if (targetDetailMap.containsKey(record.getId())) {
                RStatLimitTargetVO rStatLimitTargetVO = targetDetailMap.get(record.getId());
                overStation.setFlicker(rStatLimitTargetVO.getFlickerOvertime());
                overStation.setGi(rStatLimitTargetVO.getIharmOvertime());
                overStation.setGv(rStatLimitTargetVO.getUharmOvertime());
                overStation.setUnban(rStatLimitTargetVO.getUbalanceOvertime());
                overStation.setInseq(rStatLimitTargetVO.getINegOvertime());
                overStation.setIsFlicker(overStation.getFlicker()>0?"是":"否");
                overStation.setIsGi(overStation.getGi()>0?"是":"否");
                overStation.setIsGv(overStation.getGv()>0?"是":"否");
                overStation.setIsInseq(overStation.getInseq()>0?"是":"否");
                overStation.setIsUnban(overStation.getUnban()>0?"是":"否");
            }else{
                overStation.setFlicker(0);
                overStation.setGi(0);
                overStation.setGv(0);
                overStation.setUnban(0);
                overStation.setInseq(0);
                overStation.setIsFlicker("否");
                overStation.setIsGi("否");
                overStation.setIsGv("否");
                overStation.setIsInseq("否");
                overStation.setIsUnban("否");
            }
            info.add(overStation);
        }
        PmsPage pmsPage = BeanUtil.copyProperties(monitorList, PmsPage.class);
        pmsPage.setList(info);
        return pmsPage;
    }

    @Override
    public PmsPage<TypicalOverIndex> getOverIndexList(TypicalSourceParam param) {
        setMonitorIds(param);
        List<TypicalOverIndex> info=new ArrayList<>();
        //获取监测点信息的信息
        Page<TypicalSourceOnLine> monitorList = monitorClient.monitorTypicalList(param).getData();
        //根据监测点id集合获取超标监测信息
        List<String> monitorIds = monitorList.getRecords().stream().map(TypicalSourceOnLine::getId).distinct().collect(Collectors.toList());

        //TODO 缺少信息，获取监测点信息，rStatLimitRateDMapper

        TypicalOverIndex overIndex;
        for (TypicalSourceOnLine record : monitorList.getRecords()) {
            overIndex = new TypicalOverIndex();
            overIndex.setAuxiliarySubstationId(record.getAuxiliarySubstationId());
            overIndex.setAuxiliarySubstationName(record.getAuxiliarySubstationName());
            overIndex.setAuxiliaryVoltageLevel(record.getAuxiliaryVoltageLevel());
            overIndex.setAuxiliaryVoltageLevelName(record.getAuxiliaryVoltageLevelName());
            overIndex.setBusId(record.getBusId());
            overIndex.setBusName(record.getBusName());
            overIndex.setBusVoltageLevel(record.getBusVoltageLevel());
            overIndex.setBusVoltageLevelName(record.getBusVoltageLevelName());
            overIndex.setCapacity(record.getCapacity());
            overIndex.setCityOrg(record.getCityOrg());
            overIndex.setCityOrgName(record.getCityOrgName());
            overIndex.setEffectMonitorNum(record.getEffectMonitorNum());
            overIndex.setId(record.getId());
            overIndex.setMainSubstationId(record.getMainSubstationId());
            overIndex.setMainSubstationName(record.getMainSubstationName());
            overIndex.setMainVoltageLevel(record.getMainVoltageLevel());
            overIndex.setMainVoltageLevelName(record.getMainVoltageLevelName());
            overIndex.setMaintOrg(record.getMaintOrg());
            overIndex.setMaintOrgName(record.getMaintOrgName());
            overIndex.setMonitorId(record.getMonitorId());
            overIndex.setMonitorObjectType(record.getMonitorObjectType());
            overIndex.setMonitorObjectTypeName(record.getMonitorObjectTypeName());
            overIndex.setName(record.getName());
            overIndex.setRailWayName(record.getRailWayName());
            overIndex.setRailWayNumber(record.getRailWayNumber());
            overIndex.setRailWayType(record.getRailWayType());
            overIndex.setRailWayTypeName(record.getRailWayTypeName());
            overIndex.setRunStatus(record.getRunStatus());
            overIndex.setRunStatusName(record.getRunStatusName());
            overIndex.setStationId(record.getStationId());
            overIndex.setStationName(record.getStationName());
            overIndex.setStationType(record.getStationType());
            overIndex.setStationVoltageLevel(record.getStationVoltageLevel());
            overIndex.setStationVoltageLevelName(record.getStationVoltageLevelName());
            overIndex.setTradeCode(record.getTradeCode());
            overIndex.setTradeCodeName(record.getTradeCodeName());
            overIndex.setVoltageLevel(record.getVoltageLevel());
            overIndex.setVoltageLevelName(record.getVoltageLevelName());


            overIndex.setMonitorDate(param.getStatDate());
            /*
            //日平均值
            overIndex.setAvgValue();
            //谐波次数
            overIndex.setHarmonicNum();
            //日最大值
            overIndex.setMaxValue();
            //日最小值
            overIndex.setMinValue();
            //日95值
            overIndex.setNfValue();
            //一般限值
            overIndex.setNormalLimit();
            //相别
            overIndex.setSeq();
            //短时限值
            overIndex.setShortLimit();
            */

            info.add(overIndex);
        }
        PmsPage pmsPage = BeanUtil.copyProperties(monitorList, PmsPage.class);
        pmsPage.setList(info);
        return pmsPage;
    }


    private void setMonitorIds(TypicalSourceParam param){
        List<String> temBusIds = new ArrayList<>();
        LocalDate begin = LocalDate.parse(param.getStartTime());
        String statisticType = param.getStatType();
        QueryWrapper<?> dayLam = new QueryWrapper<>();
        dayLam.eq("statistic_date", begin).eq("dept_id", param.getNodeId());
        Object pmsRunStatistic = null;
        if (DicDataEnum.STATISTICAL_TYPE_D.getCode().equals(statisticType)) {
            pmsRunStatistic = pmsRunStatisticDMapper.selectOne((QueryWrapper<PmsRunStatisticD>) dayLam);
        } else if (DicDataEnum.STATISTICAL_TYPE_M.getCode().equals(statisticType)) {
            pmsRunStatistic = pmsRunStatisticMMapper.selectOne((QueryWrapper<PmsRunStatisticM>) dayLam);
        } else if (DicDataEnum.STATISTICAL_TYPE_Y.getCode().equals(statisticType)) {
            pmsRunStatistic = pmsRunStatisticYMapper.selectOne((QueryWrapper<PmsRunStatisticY>) dayLam);
        }

        if (Objects.nonNull(pmsRunStatistic)) {
            String onlineBusMidIds;
            if (pmsRunStatistic instanceof PmsRunStatisticD) {
                onlineBusMidIds = ((PmsRunStatisticD) pmsRunStatistic).getTypicalOnlineIds();
            } else if (pmsRunStatistic instanceof PmsRunStatisticM) {
                onlineBusMidIds = ((PmsRunStatisticM) pmsRunStatistic).getTypicalOnlineIds();
            } else {
                onlineBusMidIds = ((PmsRunStatisticY) pmsRunStatistic).getTypicalOnlineIds();
            }
            if (onlineBusMidIds != null) {
                temBusIds.addAll(Arrays.asList(onlineBusMidIds.split(StrUtil.COMMA)));
            }
        }
        param.setMonitorIds(temBusIds);
    }
}
