package cn.cecep.talroad.service.strategy.support.gt;

import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.common.core.utils.StringUtils;
import cn.cecep.talroad.common.redis.service.RedisService;
import cn.cecep.talroad.domain.AmProblemFi;
import cn.cecep.talroad.domain.BasDevice;
import cn.cecep.talroad.domain.BasDeviceSalAnalysis;
import cn.cecep.talroad.domain.BasDeviceZlConfig;
import cn.cecep.talroad.domain.MonDevReal;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisCo;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisConverter;
import cn.cecep.talroad.enums.EnIndustry;
import cn.cecep.talroad.enums.GtDeviceTypeEnum;
import cn.cecep.talroad.enums.ProblemTypeEnum;
import cn.cecep.talroad.enums.ReleaseStatusEnum;
import cn.cecep.talroad.enums.TimeTypeEnum;
import cn.cecep.talroad.service.IBasDeviceService;
import cn.cecep.talroad.service.IBasDeviceZlConfigService;
import cn.cecep.talroad.service.IMonDevRealService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisConverterService;
import cn.cecep.talroad.vo.FactoryDeviceVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Auther: cjh
 * @Date: 2023-03-25 16:11
 * @Class: GtZlmqAdapter
 * @Deseription: 任务调度-转炉煤气放散
 * @Version V1.0
 */
@Slf4j
@Service("GTZLMQ")
public class GtZlmqAdapter extends GtStatusStrategyAdapter {

    @Autowired
    private IBasDeviceZlConfigService basDeviceZlConfigService;
    @Autowired
    private ISRaRealTimeAnalysisConverterService raRealTimeAnalysisConverterService;
    @Autowired
    private IBasDeviceService basDeviceService;
    @Autowired
    private IMonDevRealService monDevRealService;
    @Autowired
    private RedisService redisService;

    private final static String ZLMQ_START = "GT_ZLMQ_START_";
    private final static String ZLMQ_END = "GT_ZLMQ_END_";


    @Override
    protected void doProcessGTStatus(String industry, String deviceType, List<MonDevReal> list,Date lastDate, Date tempDate) {

        List<BasDeviceSalAnalysis> deviceStatusList = new ArrayList<>();
        List<SRaRealTimeAnalysisCo> coList = new ArrayList<>();
        List<AmProblemFi> alarmList = new ArrayList<>();
        Map<String,BasDeviceSalAnalysis> salAnalysisMap = new HashMap<>();
        QueryWrapper<BasDevice> deviceQueryWrapper = new QueryWrapper<>();
        deviceQueryWrapper.eq("industry", EnIndustry.GT.id());
        deviceQueryWrapper.eq("type",GtDeviceTypeEnum.ZL.getCode());
        deviceQueryWrapper.eq("is_status","1");
        List<BasDevice> deviceList = basDeviceService.list(deviceQueryWrapper);

        if (deviceList != null && deviceList.size() > 0) {
            deviceList.forEach(device -> {
                QueryWrapper<BasDeviceZlConfig> zlConfigQueryWrapper = new QueryWrapper<>();
                zlConfigQueryWrapper.eq("factory_id",device.getFactoryId());
                zlConfigQueryWrapper.eq("device_id",device.getDeviceId());
                List<BasDeviceZlConfig> zlList = basDeviceZlConfigService.list(zlConfigQueryWrapper);
                if(zlList!=null&&zlList.size()>0){
                    List<String> deviceIds = zlList.stream().map(BasDeviceZlConfig::getFsDeviceId).collect(Collectors.toList());
                    if(deviceIds!=null&&deviceIds.size()>0) {
                        QueryWrapper<MonDevReal> realQueryWrapper = new QueryWrapper<>();
                        realQueryWrapper.eq("factory_id", device.getFactoryId());
                        realQueryWrapper.eq("time_type", TimeTypeEnum.REAL.getCode());
                        if (deviceIds.size() > 1) {
                            realQueryWrapper.in("device_id", deviceIds);
                        } else {
                            realQueryWrapper.eq("device_id", deviceIds.get(0));
                        }
                        realQueryWrapper.between("data_time",lastDate,tempDate);
                        List<MonDevReal> realList = monDevRealService.list(realQueryWrapper);

                        Date start = DateUtils.addHours(tempDate, -4);
                        QueryWrapper<SRaRealTimeAnalysisConverter> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("device_id", device.getDeviceId());
                        queryWrapper.eq("factory_id", device.getFactoryId());
                        queryWrapper.gt("analyse_time", start);
                        queryWrapper.last("limit 2");
                        queryWrapper.orderByDesc("analyse_time");
                        List<SRaRealTimeAnalysisConverter> result = raRealTimeAnalysisConverterService.list(queryWrapper);
                        FactoryDeviceVo vo = basDeviceService.selectFactoryDeviceVoByDeviceId(device.getDeviceId());
                        if (deviceIds.size() == 1) {
                            // ZL设备与放散设备1比1
                            processSingleData(lastDate, deviceStatusList, coList, salAnalysisMap, realList, result, vo,alarmList);
                        } else {
                            Map<Date, List<MonDevReal>> groupMap = realList.stream().collect(Collectors.groupingBy(MonDevReal::getDataTime));
                            //判断炉数全部为0
                            boolean flag = result.stream().allMatch(t -> t.getConverterNumber() == 0);
                            if (result.size() == 0 || flag) {
                                realList.forEach(treal->{
                                    // 炉数相同，未放散
                                    SRaRealTimeAnalysisCo co = super.doProcessAnalysisCoData(vo, treal.getDataTime(), treal.getDataTime(), ReleaseStatusEnum.UNREAL);
                                    coList.add(co);
                                });

                                BasDeviceSalAnalysis oldSal = salAnalysisMap.get(vo.getDeviceId());
                                if (oldSal == null) {
                                    BasDeviceSalAnalysis basStatus = super.doProcessDeviceAnalysisStatus(vo.getFactoryId(), vo.getDeviceId(), "", ReleaseStatusEnum.UNREAL.getName());
                                    salAnalysisMap.put(vo.getDeviceId(), basStatus);
                                    deviceStatusList.add(basStatus);
                                }
                            } else {
                                groupMap.forEach((dateTime, reals) -> {
                                    if (!flag && reals.size() == deviceIds.size()) {
                                        AtomicInteger total = new AtomicInteger();
                                        AtomicInteger ycTotal = new AtomicInteger();
                                        // 判断放散口温度是否缺失
                                        boolean tempIsMiss = reals.stream().anyMatch(s -> StringUtils.isEmpty(s.getMq5()));
                                        if (tempIsMiss) {
                                            ycTotal.getAndIncrement();
                                        } else {
                                            // 放散口平均温度大于100
                                            Double maxTemp = reals.stream().mapToDouble(s -> Double.valueOf(s.getMq5())).max().getAsDouble();
                                            //放散口温度
                                            if (maxTemp >= Double.valueOf(100)) {
                                                total.getAndIncrement();
                                            }
                                        }
                                        if (ycTotal.get() > 0) {
                                            BasDeviceSalAnalysis basStatus = super.doProcessDeviceAnalysisStatus(vo.getFactoryId(), vo.getDeviceId(), "", ReleaseStatusEnum.YC.getName());
                                            deviceStatusList.add(basStatus);
                                            SRaRealTimeAnalysisCo co = super.doProcessAnalysisCoData(vo, dateTime, dateTime, ReleaseStatusEnum.YC);
                                            coList.add(co);
                                        } else {
                                            if (total.get() > 0) {
                                                // 正常放散
                                                BasDeviceSalAnalysis basStatus = super.doProcessDeviceAnalysisStatus(vo.getFactoryId(), vo.getDeviceId(), "", ReleaseStatusEnum.NORMAL.getName());
                                                deviceStatusList.add(basStatus);
                                                SRaRealTimeAnalysisCo co = super.doProcessAnalysisCoData(vo, dateTime, dateTime, ReleaseStatusEnum.NORMAL);
                                                coList.add(co);
                                                String ycBegin = ZLMQ_START + vo.getDeviceId();
                                                String ycEnd = ZLMQ_END + vo.getDeviceId();
                                                // 异常放散开始日期
                                                String stDate = redisService.getCacheObject(ycBegin);
                                                // 异常放散结束日期
                                                String stEnd = redisService.getCacheObject(ycEnd);
                                                if (StringUtils.isNotEmpty(stDate)) {
                                                    stEnd = StringUtils.isEmpty(stEnd) ? stDate : stEnd;
                                                    StringBuffer sb = new StringBuffer();
                                                    sb.append(vo.getDeviceName()).append("于").append(stDate).append("-")
                                                        .append(stEnd).append("存在CO异常放散情况。");
                                                    if(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",stDate).compareTo(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",stEnd))<0) {
                                                        AmProblemFi problemFi = doProcessAlaram(vo.getFactoryId(), vo.getDeviceId(), vo.getDeviceName(),
                                                            DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", stDate),
                                                            DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", stEnd), ProblemTypeEnum.RELEASE,
                                                            sb.toString(), "炉数,吹氧量", "p1,p2");
                                                        alarmList.add(problemFi);
                                                    }
                                                    // 删除异常放散缓存
                                                    redisService.deleteObject(ycBegin);
                                                    redisService.deleteObject(ycEnd);
                                                }

                                            } else {
                                                // 异常放散
                                                BasDeviceSalAnalysis basStatus = super.doProcessDeviceAnalysisStatus(vo.getFactoryId(), vo.getDeviceId(), "", ReleaseStatusEnum.ERROR.getName());
                                                deviceStatusList.add(basStatus);
                                                SRaRealTimeAnalysisCo errorCo = super.doProcessAnalysisCoData(vo, dateTime, dateTime, ReleaseStatusEnum.ERROR);
                                                coList.add(errorCo);
                                                // 转炉煤气开启
                                                String ycBegin = ZLMQ_START + vo.getDeviceId();
                                                String ycEnd = ZLMQ_END + vo.getDeviceId();
                                                // 异常放散开始日期
                                                String stDate = redisService.getCacheObject(ycBegin);
                                                if (StringUtils.isEmpty(stDate)) {
                                                    //设置缓存
                                                    redisService.setCacheObject(ycBegin, DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", dateTime));
                                                } else {
                                                    redisService.setCacheObject(ycEnd, DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", dateTime));
                                                }
                                            }
                                        }
                                    }
                                });
                            }
                        }
                    }
                }
            });

            // 批量处理
            super.doSaveBatchSRaRealTimeAnalysisCo(coList);
            super.doSaveOrUpdateBatchDeviceStatus(deviceStatusList);
            super.doSaveBatchAlarm(alarmList);
        }
    }

    /**
     * ZL设备与放散设备1比1时
     * @param lastDate
     * @param deviceStatusList
     * @param coList
     * @param salAnalysisMap
     * @param realList
     * @param result
     * @param vo
     */
    private void processSingleData(Date lastDate, List<BasDeviceSalAnalysis> deviceStatusList, List<SRaRealTimeAnalysisCo> coList,
        Map<String, BasDeviceSalAnalysis> salAnalysisMap, List<MonDevReal> realList, List<SRaRealTimeAnalysisConverter> result, FactoryDeviceVo vo,List<AmProblemFi> alarmList) {
        //判断炉数全部为0
        boolean flag = result.stream().allMatch(t -> t.getConverterNumber() == 0);

        realList.forEach(real ->{
            AtomicInteger total = new AtomicInteger();
            if (result.size()==0||flag) {
                // 炉数相同，未放散
                SRaRealTimeAnalysisCo co = super.doProcessAnalysisCoData(vo, lastDate, real.getDataTime(), ReleaseStatusEnum.UNREAL);
                coList.add(co);

                BasDeviceSalAnalysis oldSal = salAnalysisMap.get(vo.getDeviceId());
                if(oldSal==null) {
                    BasDeviceSalAnalysis basStatus = super.doProcessDeviceAnalysisStatus(vo.getFactoryId(), vo.getDeviceId(), "", ReleaseStatusEnum.UNREAL.getName());
                    salAnalysisMap.put(vo.getDeviceId(),basStatus);
                    deviceStatusList.add(basStatus);
                }
            } else {
                //炉数发生变化，放散
                if (StringUtils.isNotEmpty(real.getMq5())) {
                    //放散口温度
                    if (Double.valueOf(real.getMq5()) >= Double.valueOf(100)) {
                        total.getAndIncrement();
                    }
                    if (total.get() > 0) {
                        // 正常放散
                        BasDeviceSalAnalysis basStatus = super.doProcessDeviceAnalysisStatus(vo.getFactoryId(), vo.getDeviceId(), "", ReleaseStatusEnum.NORMAL.getName());
                        deviceStatusList.add(basStatus);
                        SRaRealTimeAnalysisCo co = super.doProcessAnalysisCoData(vo, lastDate,real.getDataTime(), ReleaseStatusEnum.NORMAL);
                        coList.add(co);
                        String ycBegin = ZLMQ_START+vo.getDeviceId();
                        String ycEnd = ZLMQ_END+vo.getDeviceId();
                        // 异常放散开始日期
                        String stDate = redisService.getCacheObject(ycBegin);
                        // 异常放散结束日期
                        String stEnd = redisService.getCacheObject(ycEnd);
                        if(StringUtils.isNotEmpty(stDate)) {
                            stEnd = StringUtils.isEmpty(stEnd)?stDate:stEnd;
                            StringBuffer sb = new StringBuffer();
                            sb.append(vo.getDeviceName()).append("于").append(stDate).append("-")
                                .append(stEnd).append("存在CO异常放散情况。");
                            if(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",stDate).compareTo(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",stEnd))<=0) {
                                AmProblemFi problemFi = doProcessAlaram(vo.getFactoryId(), vo.getDeviceId(), vo.getDeviceName(), DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", stDate),
                                    DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", stEnd), ProblemTypeEnum.RELEASE, sb.toString(),
                                    "炉数,吹氧量", "p1,p2");
                                alarmList.add(problemFi);
                            }
                            redisService.deleteObject(ycBegin);
                            redisService.deleteObject(ycEnd);
                        }
                    } else {
                        // 异常放散
                        BasDeviceSalAnalysis basStatus = super.doProcessDeviceAnalysisStatus(vo.getFactoryId(), vo.getDeviceId(), "",ReleaseStatusEnum.ERROR.getName());
                        deviceStatusList.add(basStatus);

                        SRaRealTimeAnalysisCo co = super.doProcessAnalysisCoData(vo, lastDate,real.getDataTime(),ReleaseStatusEnum.ERROR);
                        coList.add(co);
                        // 转炉煤气开启
                        String ycBegin = ZLMQ_START+vo.getDeviceId();
                        String ycEnd = ZLMQ_END+vo.getDeviceId();
                        // 异常放散开始日期
                        String stDate = redisService.getCacheObject(ycBegin);
                        if(StringUtils.isEmpty(stDate)){
                            //设置缓存
                            redisService.setCacheObject(ycBegin,DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",real.getDataTime()));
                            redisService.setCacheObject(ycEnd,DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",real.getDataTime()));
                        }else {
                            redisService.setCacheObject(ycEnd,DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",real.getDataTime()));
                        }

                    }
                }else{
                    BasDeviceSalAnalysis basStatus = super.doProcessDeviceAnalysisStatus(vo.getFactoryId(), vo.getDeviceId(), "",ReleaseStatusEnum.YC.getName());
                    deviceStatusList.add(basStatus);
                    SRaRealTimeAnalysisCo co = super.doProcessAnalysisCoData(vo, lastDate,real.getDataTime(),ReleaseStatusEnum.YC);
                    coList.add(co);
                }
            }
        });
    }

}
