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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.device.biz.pojo.dto.DeptGetChildrenDTO;
import com.njcn.device.pms.pojo.po.Monitor;
import com.njcn.event.pojo.po.RMpEventDetailD;
import com.njcn.harmonic.pojo.po.RMpTargetWarnDPO;
import com.njcn.prepare.harmonic.mapper.mysql.area.PmsMonitorPOMapper;
import com.njcn.prepare.harmonic.mapper.mysql.area.RMpTargetWarnDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.dim.RDimObjEventDMapper;
import com.njcn.prepare.harmonic.mapper.mysql.line.RMpEventDetailDMapper;
import com.njcn.prepare.harmonic.pojo.bo.CalculatedParam;
import com.njcn.prepare.harmonic.pojo.param.EventParam;
import com.njcn.harmonic.pojo.po.dim.RDimObjEventD;
import com.njcn.prepare.harmonic.service.mysql.dim.IRDimObjEventDService;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 监测到暂态指标的用户-日表 服务实现类
 * </p>
 *
 * @author xuyang
 * @since 2023-11-23
 */
@Service
@RequiredArgsConstructor
public class RDimObjEventDServiceImpl extends MppServiceImpl<RDimObjEventDMapper, RDimObjEventD> implements IRDimObjEventDService {

    private final RMpTargetWarnDMapper rMpTargetWarnDMapper;
    private final PmsMonitorPOMapper pmsMonitorPOMapper;
    private final DicDataFeignClient dicDataFeignClient;
    private final RMpEventDetailDMapper rMpEventDetailDMapper;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void eventUserRatio(CalculatedParam<DeptGetChildrenDTO> calculatedParam) {
        List<RDimObjEventD> result = new ArrayList<>();
        List<DeptGetChildrenDTO> deptList = calculatedParam.getIdList();
        //获取敏感用户、重要用户字典id
        String sensitiveUserId = dicDataFeignClient.getDicDataByCode(DicDataEnum.SENSITIVE_USERS.getCode()).getData().getId();
        String importantUserId = dicDataFeignClient.getDicDataByCode(DicDataEnum.IMPORTANT_USERS.getCode()).getData().getId();
        deptList.forEach(item->{
            RDimObjEventD rDimObjEventD = new RDimObjEventD();
            rDimObjEventD.setOrgId(item.getDeptId());
            rDimObjEventD.setStatisDate(LocalDate.parse(calculatedParam.getDataDate(), DatePattern.NORM_DATE_FORMATTER));
            rDimObjEventD.setMonitorRate(3.1415926f);
            rDimObjEventD.setLimitFreqRate(3.1415926f);
            List<String> lineList = item.getLineIds();
            if (CollectionUtil.isNotEmpty(lineList)){
                //获取当前单位下的重要用户、敏感用户监测点信息
                List<Monitor> monitorList = getUser(lineList,Arrays.asList(sensitiveUserId,importantUserId));
                if(CollectionUtil.isNotEmpty(monitorList)){
                    List<String> userList = monitorList.stream().map(Monitor::getId).collect(Collectors.toList());
                    //获取当前单位下的有效接入重要、敏感用户监测点信息
                    List<RMpTargetWarnDPO> effectiveList = getEffective(userList,calculatedParam.getDataDate());
                    if (CollectionUtil.isNotEmpty(effectiveList)){
                        EventParam param = getEventTimes(userList,calculatedParam.getDataDate());
                        //获取发生暂态的监测点数
                        rDimObjEventD.setMonitorRate((float)param.getEventLineCount()/effectiveList.size()*100);
                        //获取重要用户、敏感用户监测点发生的暂态次数之和
                        if (!Objects.equals(3.1415926f,param.getEventCount())){
                            rDimObjEventD.setLimitFreqRate(param.getEventCount()/effectiveList.size());
                        }
                    } else {
                        rDimObjEventD.setMonitorRate(-1.0f);
                        rDimObjEventD.setLimitFreqRate(-1.0f);
                    }
                }
            }
            result.add(rDimObjEventD);
        });
        if (CollectionUtil.isNotEmpty(result)){
            this.saveOrUpdateBatchByMultiId(result,100);
        }
    }

    public List<Monitor> getUser(List<String> lineList, List<String> monitorTag) {
        LambdaQueryWrapper<Monitor> monitorLambdaQueryWrapper = new LambdaQueryWrapper<>();
        monitorLambdaQueryWrapper.select(Monitor::getId, Monitor::getMonitorTag)
                .in(Monitor::getId, lineList)
                .in(Monitor::getMonitorTag, monitorTag)
                .eq(Monitor::getStatus, DataStateEnum.ENABLE.getCode());
        return pmsMonitorPOMapper.selectList(monitorLambdaQueryWrapper);
    }

    public List<RMpTargetWarnDPO> getEffective(List<String> lineList, String time) {
        LambdaQueryWrapper<RMpTargetWarnDPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(RMpTargetWarnDPO::getMeasurementPointId)
                .in(RMpTargetWarnDPO::getMeasurementPointId,lineList)
                .eq(RMpTargetWarnDPO::getDataDate,time)
                .eq(RMpTargetWarnDPO::getIsEffective, DataStateEnum.ENABLE.getCode());
        return rMpTargetWarnDMapper.selectList(lambdaQueryWrapper);
    }

    public EventParam getEventTimes(List<String> lineList, String time) {
        EventParam eventParam = new EventParam();
        float result = 3.1415926f;
        int data = 0;
        int count = 0;
        LambdaQueryWrapper<RMpEventDetailD> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(RMpEventDetailD::getSwellTimes, RMpEventDetailD::getSagTimes, RMpEventDetailD::getInterruptTimes)
                .in(RMpEventDetailD::getMeasurementPointId,lineList)
                .eq(RMpEventDetailD::getDataDate,time);
        List<RMpEventDetailD> eventDay = rMpEventDetailDMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(eventDay)){
            for (RMpEventDetailD item : eventDay) {
                int times = item.getSwellTimes() + item.getSagTimes() + item.getInterruptTimes();
                if (times == 0){
                    count++;
                }
                data = data + times;
            }
            result = (float) data;
        }
        eventParam.setEventLineCount(count);
        eventParam.setEventCount(result);
        return eventParam;
    }

}
