package com.chinaitop.depot.intelligent.pushs.service.impl;

import com.chinaitop.depot.intelligent.basicdata.model.TWarningThreshold;
import com.chinaitop.depot.intelligent.basicdata.service.ResolutionToSendAlarmService;
import com.chinaitop.depot.intelligent.basicdata.service.WarningThresholdService;
import com.chinaitop.depot.intelligent.grainsituation.mapper.TTestdataLayerMapper;
import com.chinaitop.depot.intelligent.grainsituation.mapper.TWarningThresholdHistoryMapper;
import com.chinaitop.depot.intelligent.grainsituation.model.TPoints;
import com.chinaitop.depot.intelligent.grainsituation.model.TTestdata;
import com.chinaitop.depot.intelligent.grainsituation.model.TTestdataLayer;
import com.chinaitop.depot.intelligent.grainsituation.model.TWarningThresholdHistory;
import com.chinaitop.depot.intelligent.grainsituation.service.TWarningThresholdHistoryService;
import com.chinaitop.depot.intelligent.grainsituation.service.TemperatureRecordService;
import com.chinaitop.depot.intelligent.pushs.service.GrainPushsService;
import com.chinaitop.depot.intelligent.utils.JsonToObjectUtils;
import com.chinaitop.depot.intelligent.utils.UuidUtils;
import com.chinaitop.depot.intelligent.utils.VerificationSourceUtils;
import com.chinaitop.depot.intelligent.utils.WarningMessage;
import com.google.common.collect.Lists;
import com.unissoft.model.ResponseEntity;
import com.unissoft.model.TypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service
@SuppressWarnings("all")
public class GrainPushsServiceImpl implements GrainPushsService {
    final static Logger logger = LoggerFactory.getLogger(GrainPushsServiceImpl.class);

    @Resource
    private TemperatureRecordService temperatureRecordService;

    @Resource
    private TTestdataLayerMapper tTestdataLayerMapper;

    @Resource
    private WarningThresholdService warningThresholdService;

    @Resource
    private TWarningThresholdHistoryMapper tWarningThresholdHistoryMapper;

    @Resource
    private UuidUtils uuidUtils;

    @Resource
    private WarningMessage warningMessage;

    @Resource
    private ResolutionToSendAlarmService resolutionToSendAlarmService;

    @Resource
    private TWarningThresholdHistoryService tWarningThresholdHistoryService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseEntity uploadGrainTemperatureData(String dataSource, String grainTemperatureData) {
        if (!VerificationSourceUtils.verificationSource(dataSource)) {
            return ResponseEntity.failed("验证失败！");
        }
        //数据来源
        String dataSource2 = VerificationSourceUtils.sourceMap().get(dataSource);
        logger.info(grainTemperatureData);
        try {
            if (StringUtils.isNotBlank(grainTemperatureData)) {
                //粮温元数据
                ArrayList<TTestdata> tTestdataList = Lists.newArrayList();
                //粮温每层数据
                ArrayList<TTestdataLayer> tTestdataLayerArrayList = Lists.newArrayList();
                //报警数据
                ArrayList<TWarningThresholdHistory> tWarningThresholdHistorieList = Lists.newArrayList();

                String replace = grainTemperatureData.replace("\"Y\"", "\"y\"").replace("\"X\"", "\"x\"").replace("\"Z\"", "\"z\"");
                ArrayList<Object> ts = JsonToObjectUtils.jsonToObjects(replace, TTestdata.class);
                ArrayList<TTestdata> tts = Lists.newArrayList();
                ts.forEach(obj -> {
                    TTestdata s = (TTestdata) obj;
                    tts.add(s);
                });
                List<String> cDcsCodes = tts.stream().map(TTestdata::getStorehouse).collect(Collectors.toList());
                List<Date> cTimes = tts.stream().map(TTestdata::getTime).collect(Collectors.toList());
                List<String> lqTypes = tts.stream().map(TTestdata::getIlqYq).collect(Collectors.toList());
                //校验重复数据
                List<TTestdata> byCodeAndTimes = temperatureRecordService.getByCodeAndTimes(cDcsCodes, cTimes, lqTypes);
                if (byCodeAndTimes != null && byCodeAndTimes.size() > 0) {
                    return ResponseEntity.failed("上传数据重复！");
                }
                String orgId = temperatureRecordService.getOrgId(cDcsCodes.get(0));
                ts.forEach(obj -> {
                    String testdataId = UuidUtils.getCode();
                    TTestdata tTestdata = (TTestdata) obj;
                    String house = tTestdata.getStorehouse();
                    Date time = tTestdata.getTime();
                    List<TPoints> ps = tTestdata.getPoints();
                    String sP = JsonToObjectUtils.listToString(ps);
                    tTestdata.settPoints(sP);
                    //获取报警阈值信息6972测温 6983温度高限 6982温度底限 6991温度预警
                    TWarningThreshold threshold = null; //温度高限
                    TWarningThreshold wLowest = null; //温度底限
                    TWarningThreshold thresholdWarning = null; //低温温度预警
                    TWarningThreshold wLowestWarning = null; //低温温度预警
                    String ilqYq = tTestdata.getIlqYq();
                    if (ilqYq.equals("0")) {
                        threshold = warningThresholdService.getByCfCodeAndwName(house, 0, "6972", "6983");//获取高温报警阀值
                        wLowest = warningThresholdService.getByCfCodeAndwName(house, 0, "6972", "6982");//获取低温报警阀值
                        thresholdWarning = warningThresholdService.getByCfCodeAndwName(house, 0, "6972", "6991");//获取高温预警
                        wLowestWarning = warningThresholdService.getByCfCodeAndwName(house, 0, "6972", "7248");//低温温度预警

                    }
                    BigDecimal wholeSum = ps.stream().filter(TPoints -> !TPoints.getTemp().equals(new BigDecimal("250.0"))).map(TPoints::getTemp).reduce(BigDecimal.ZERO, BigDecimal::add);
                    List<BigDecimal> collect = ps.stream().filter(TPoints -> !TPoints.getTemp().equals(new BigDecimal("250.0"))).map(t -> t.getTemp()).collect(Collectors.toList());
                    double doubleValue = wholeSum.doubleValue();
                    double wholeAvg = 0;
                    if (collect.size() > 0) {
                        wholeAvg = doubleValue / collect.size();
                    }
                    tTestdata.setAvg(new BigDecimal(wholeAvg == 0 ? 250 : wholeAvg).setScale(2, RoundingMode.HALF_UP));
                    BigDecimal wholeMax = ps.stream().filter(TPoints -> !TPoints.getTemp().equals(new BigDecimal("250.0"))).map(TPoints::getTemp).reduce(BigDecimal.ZERO, BigDecimal::max).setScale(2, RoundingMode.HALF_UP);
                    tTestdata.setMax(new BigDecimal(wholeMax.toString().equals("0") ? "250.0" : wholeMax.toString()));
                    List<Double> wholeMins = Lists.newArrayList();
                    List<BigDecimal> bList = ps.stream().filter(TPoints -> !TPoints.getTemp().equals(new BigDecimal("250.0"))).map(t -> t.getTemp()).collect(Collectors.toList());
                    bList.forEach(bigDecimal -> {
                        wholeMins.add(bigDecimal.doubleValue());
                    });
                    Double wholeMin = wholeMins.size() == 0 ? 250.0 : Collections.min(wholeMins);
                    BigDecimal wMin = new BigDecimal(wholeMin).setScale(2, RoundingMode.HALF_UP);
                    tTestdata.setMin(wMin);
                    tTestdata.setId(testdataId);
                    tTestdata.setOrgId(orgId);
                    tTestdata.setDataSource(dataSource2);
                    tTestdataList.add(tTestdata);
                    if (threshold != null) {
                        //用于判断是否已经报警
                        boolean temp = false;
                        BigDecimal wh = threshold.getThreshold();
                        //-1 小于 0 等于 1 大于 高温报警
                        if (wholeMax.compareTo(wh) == 1 && !wholeMax.toString().equals("250.0") && ilqYq.equals("0")) {
                            String tid = UuidUtils.getCode();
                            String desc = "整仓粮温(" + wholeMax + ")高于阈值(" + wh + ")";
                            TWarningThresholdHistory tt = warningMessage.saveWThreshold(tid, house, threshold, wholeMax, wh, time, desc, dataSource2, "0", "0");
                            tWarningThresholdHistorieList.add(tt);
                            temp = true;
                        }
                        if (thresholdWarning != null && !temp && !wholeMax.toString().equals("250.0") && ilqYq.equals("0")) {
                            //-1 小于 0 等于 1 大于 高温预警
                            BigDecimal ww = thresholdWarning.getThreshold();
                            if (wholeMax.compareTo(ww) == 1 && ilqYq.equals("0")) {
                                String tid = UuidUtils.getCode();
                                String desc = "整仓粮温(" + wholeMax + ")高于阈值(" + ww + ")";
                                TWarningThresholdHistory tt = warningMessage.saveWThreshold(tid, house, thresholdWarning, wholeMax, ww, time, desc, dataSource2, "0", "1");
                                tWarningThresholdHistorieList.add(tt);
                            }
                        }
                    }
                    if (wLowest != null) {
                        //用于判断是否已经报警
                        boolean temp = false;
                        BigDecimal wl = wLowest.getThreshold().setScale(2, RoundingMode.HALF_UP);
                        //-1 小于 0 等于 1 大于 低温报警
                        if (wMin.compareTo(wl) == -1 && !wMin.toString().equals("250.0") && ilqYq.equals("0")) {
                            String tid = UuidUtils.getCode();
                            String desc = "整仓粮温(" + wMin + ")低于阈值(" + wl + ")";
                            TWarningThresholdHistory tt = warningMessage.saveWThreshold(tid, house, wLowest, wMin, wl, time, desc, dataSource2, "0", "0");
                            tWarningThresholdHistorieList.add(tt);
                            temp = true;
                        }
                        if (wLowestWarning != null && !temp && !wMin.toString().equals("250.0") && ilqYq.equals("0")) {
                            //-1 小于 0 等于 1 大于 低温预警
                            BigDecimal ww = wLowestWarning.getThreshold();
                            if (wMin.compareTo(ww) == -1 && ilqYq.equals("0")) {
                                String tid = UuidUtils.getCode();
                                String desc = "整仓粮温(" + wMin + ")低于阈值(" + ww + ")";
                                TWarningThresholdHistory tt = warningMessage.saveWThreshold(tid, house, wLowestWarning, wMin, ww, time, desc, dataSource2, "0", "1");
                                tWarningThresholdHistorieList.add(tt);
                            }
                        }
                    }

                    Map<String, List<TPoints>> layerGroupV = ps.stream().collect(Collectors.groupingBy(t -> t.getZ()));
                    int layerNumber = 0;
                    for (Map.Entry<String, List<TPoints>> entry : layerGroupV.entrySet()) {
                        TTestdataLayer tTestdataLayer = new TTestdataLayer();
                        tTestdataLayer.setLayernumber(++layerNumber);
                        List<TPoints> points = entry.getValue();
                        BigDecimal lsyerSums = points.stream().filter(TPoints -> !TPoints.getTemp().equals(new BigDecimal("250.0"))).map(TPoints::getTemp).reduce(BigDecimal.ZERO, BigDecimal::add);
                        List<BigDecimal> collect1 = points.stream().filter(TPoints -> !TPoints.getTemp().equals(new BigDecimal("250.0"))).map(t -> t.getTemp()).collect(Collectors.toList());
                        double lsyerSum = lsyerSums.doubleValue();
                        tTestdataLayer.setLz(points.get(0).getZ());
                        double lsyerAvg = 0;
                        if (collect1.size() > 0) {
                            lsyerAvg = lsyerSum / collect1.size();
                        }
                        tTestdataLayer.setLavg(new BigDecimal(lsyerAvg == 0 ? 250 : lsyerAvg));
                        BigDecimal lsyerMax = points.stream().filter(TPoints -> !TPoints.getTemp().equals(new BigDecimal("250.0"))).map(TPoints::getTemp).reduce(BigDecimal.ZERO, BigDecimal::max);
                        tTestdataLayer.setLmax(new BigDecimal(lsyerMax.toString().equals("0") ? "250.0" : lsyerMax.toString()));
                        List<Double> lsyerMins = Lists.newArrayList();
                        List<BigDecimal> bigList = points.stream().filter(TPoints -> !TPoints.getTemp().equals(new BigDecimal("250.0"))).map(t -> t.getTemp()).collect(Collectors.toList());
                        bigList.forEach(bigDecimal -> {
                            lsyerMins.add(bigDecimal.doubleValue());
                        });
                        Double wlsyerMin = lsyerMins.size() == 0 ? 250.0 : Collections.min(lsyerMins);
                        BigDecimal lsyerMin = new BigDecimal(wlsyerMin);
                        tTestdataLayer.setLmin(lsyerMin);
                        tTestdataLayer.setLhouse(house);
                        tTestdataLayer.setLtime(time);
                        tTestdataLayer.setId(UuidUtils.getCode());
                        tTestdataLayer.setOrgId(orgId);
                        tTestdataLayer.setDataSource(dataSource2);
                        tTestdataLayer.setLqId(testdataId);
                        tTestdataLayerArrayList.add(tTestdataLayer);

                        Map<Integer, Map<Integer, Map<Integer, List<TPoints>>>> pointsS = points.stream().collect(Collectors.groupingBy(t -> Integer.parseInt(t.getZ()), Collectors.groupingBy(t -> Integer.parseInt(t.getY()), Collectors.groupingBy(t -> Integer.parseInt(t.getX())))));
                        for (Map.Entry<Integer, Map<Integer, Map<Integer, List<TPoints>>>> pS : pointsS.entrySet()) {
                            //每层数据
                            Integer keyL = pS.getKey();
                            Map<Integer, Map<Integer, List<TPoints>>> layerPS = pS.getValue();
                            for (Map.Entry<Integer, Map<Integer, List<TPoints>>> rows : layerPS.entrySet()) {
                                //每一行数据
                                Integer keyR = rows.getKey();
                                Map<Integer, List<TPoints>> value = rows.getValue();
                                for (Map.Entry<Integer, List<TPoints>> orws : value.entrySet()) {
                                    Integer keyC = orws.getKey();
                                    BigDecimal te = orws.getValue().get(0).getTemp().setScale(2, RoundingMode.HALF_UP);
                                    if (threshold != null && ilqYq.equals("0")) {
                                        boolean temp = false;
                                        BigDecimal threshold1 = threshold.getThreshold().setScale(2, RoundingMode.HALF_UP);
                                        //-1 小于 0 等于 1 大于 高温报警
                                        if (te.compareTo(threshold1) == 1 && !te.toString().equals("250.0")) {
                                            // tid id,cfCdoe 仓房编码,threshold 报警实体包括orgID,tthreshold 检测值,wThreshold 预警或报警设置值,date 检测时间,desc 描述信息,mode 0测温，1测虫，2测气,warning 0报警，1预警
                                            String tid = UuidUtils.getCode();
                                            String desc = "第" + keyL + "层,第" + keyR + "行,第" + keyC + "列粮温(" + te + ")高于阈值(" + threshold1 + ")";
                                            TWarningThresholdHistory tt = warningMessage.saveWThreshold(tid, house, threshold, te, threshold1, time, desc, dataSource2, "0", "0");
                                            tWarningThresholdHistorieList.add(tt);
                                            temp = true;
                                        }
                                        if (thresholdWarning != null && !temp && !te.toString().equals("250.0")) {
                                            //-1 小于 0 等于 1 大于 高温预警
                                            BigDecimal ww = thresholdWarning.getThreshold();
                                            if (te.compareTo(ww) == 1 && ilqYq.equals("0")) {
                                                String tid = UuidUtils.getCode();
                                                String desc = "第" + keyL + "层,第" + keyR + "行,第" + keyC + "列粮温(" + te + ")高于阈值(" + ww + ")";
                                                TWarningThresholdHistory tt = warningMessage.saveWThreshold(tid, house, thresholdWarning, te, ww, time, desc, dataSource2, "0", "1");
                                                tWarningThresholdHistorieList.add(tt);
                                            }
                                        }
                                    }
                                    if (wLowest != null && ilqYq.equals("0")) {
                                        boolean temp = false;
                                        BigDecimal wl = wLowest.getThreshold().setScale(2, RoundingMode.HALF_UP);
                                        //-1 小于 0 等于 1 大于 低温报警
                                        if (te.compareTo(wl) == -1 && !te.toString().equals("250.0")) {
                                            String tid = UuidUtils.getCode();
                                            String desc = "第" + keyL + "层,第" + keyR + "行,第" + keyC + "列粮温(" + te + ")低于阈值(" + wl + ")";
                                            TWarningThresholdHistory tt = warningMessage.saveWThreshold(tid, house, wLowest, te, wl, time, desc, dataSource2, "0", "0");
                                            tWarningThresholdHistorieList.add(tt);
                                            temp = true;
                                        }
                                        if (wLowestWarning != null && !temp && !te.toString().equals("250.0")) {
                                            //-1 小于 0 等于 1 大于 低温预警
                                            BigDecimal ww = wLowestWarning.getThreshold();
                                            if (te.compareTo(ww) == -1 && ilqYq.equals("0")) {
                                                String tid = UuidUtils.getCode();
                                                String desc = "第" + keyL + "层,第" + keyR + "行,第" + keyC + "列粮温(" + te + ")低于阈值(" + ww + ")";
                                                TWarningThresholdHistory tt = warningMessage.saveWThreshold(tid, house, wLowestWarning, te, ww, time, desc, dataSource2, "0", "1");
                                                tWarningThresholdHistorieList.add(tt);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                });

                if (tTestdataList.size() > 0) {
                    temperatureRecordService.insertBatch(tTestdataList);
                }
                if (tTestdataLayerArrayList.size() > 0) {
                    tTestdataLayerMapper.insertBatch(tTestdataLayerArrayList);
                }
                if (tWarningThresholdHistorieList.size() > 0) {
                    tWarningThresholdHistoryMapper.insertBatch(tWarningThresholdHistorieList);
                    List<TWarningThresholdHistory> collect = tWarningThresholdHistorieList.stream().filter(TWarningThresholdHistory -> TWarningThresholdHistory.getwWarning().equals("0")).collect(Collectors.toList());
                    boolean alarmDetails = resolutionToSendAlarmService.getAlarmDetails(collect);
                    if (!alarmDetails) {
                        collect.forEach(obj -> {
                            obj.setIsSend("2");
                            tWarningThresholdHistoryService.updateById(obj);
                        });
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info(e.getMessage());
            throw new RuntimeException(TypeEnum.ED.getCode() + "  " + TypeEnum.ED.getDesc());
        }
        return ResponseEntity.ok();
    }
}
