package com.yeejoin.equipmanage.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecificAlarmLog;
import com.yeejoin.equipmanage.common.enums.IndexStatusEnum;
import com.yeejoin.equipmanage.common.enums.PressurePumpAnalysisEnum;
import com.yeejoin.equipmanage.common.enums.PressurePumpRelateEnum;
import com.yeejoin.equipmanage.common.utils.StringUtil;
import com.yeejoin.equipmanage.common.utils.UnitTransformUtil;
import com.yeejoin.equipmanage.common.vo.IotDataVO;
import com.yeejoin.equipmanage.fegin.IotFeign;
import com.yeejoin.equipmanage.mapper.EmergencyMapper;
import com.yeejoin.equipmanage.service.IEmergencyService;
import com.yeejoin.equipmanage.service.IEquipmentSpecificAlarmLogService;
import com.yeejoin.equipmanage.service.IEquipmentSpecificSerivce;
import com.yeejoin.equipmanage.service.IPressurePumpService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 四横八纵应急模块接口服务类
 */
@Service
@Slf4j
public class EmergencyServiceImpl implements IEmergencyService {


    @Autowired
    private EmergencyMapper emergencyMapper;

    @Autowired
    private IEquipmentSpecificSerivce equipmentSpecificSerivce;

    @Autowired
    private IEquipmentSpecificAlarmLogService equipmentSpecificAlarmLogService;

    @Autowired
    private SupervisionVideoServiceImpl supervisionVideoService;

    @Autowired
    private IotFeign iotFeign;

    @Autowired
    private IPressurePumpService pressurePumpService;

    @Value("${equipment.pressurepump.start}")
    private String pressurePumpStart;

    @Value("${equipment.pressurepump.pipepressure}")
    private String pressurePumpPipePressure;

    @Override
    public List<Map<String, Object>> getSystemState(String bizOrgCode) {
        List<Map<String, Object>> list = emergencyMapper.getSystemState(bizOrgCode);
        if (0 < list.size()) {
            list.forEach(x -> {
                List<Map<String, Object>> list1 = new ArrayList();
                Map<String, Object> map = new HashMap<>();
                map.put("name", x.get("status"));
                if ("正常".equals(String.valueOf(x.get("status")))) {
                    map.put("level", "success");
                } else {
                    map.put("level", "warning");
                }
                list1.add(map);
                x.put("status", list1);
            });
        }
        return list;
    }

    @Override
    public List<Map<String, Object>> getCAFSWaterTankInfo() {
        List<Map<String, Object>> list = emergencyMapper.getCAFSWaterTankInfo();
        if (0 < list.size()) {
            for (Map<String, Object> m : list) {
                Map<String, Object> transResult = UnitTransformUtil.transformValues(String.valueOf(m.get("value")),
                        String.valueOf(m.get("unit")), String.valueOf(m.get("minLevel")), String.valueOf(m.get("maxLevel")));
                m.put("value", transResult.get("nowValue"));
                if (StringUtil.isNotEmpty(IndexStatusEnum.getEnumByKey(String.valueOf(transResult.get("status"))))) {
                    m.put("statusDesc", IndexStatusEnum.getEnumByKey(String.valueOf(transResult.get("status"))).getDescribe1());
                } else {
                    m.put("statusDesc", "--");
                }
                m.put("sxyl", transResult.get("abs"));
            }
        }
        return Optional.ofNullable(list).orElse(Lists.newArrayList());
    }

    @Override
    public Map<String, Object> emergencyMaterials() {
        return emergencyMapper.selectEmergencyMaterials();
    }

    @Override
    public Page<Map<String, Object>> emergencyMaterialsDetails(Page<Map<String, Object>> page, String bizOrgCode) {
        return emergencyMapper.selectEmergencyMaterialsDetails(page, bizOrgCode);
    }

    @Override
    public Page<Map<String, Object>> selectFireMonitor(Page<Map<String, Object>> page, String bizOrgCode, String code) {
        return emergencyMapper.selectFireMonitor(page, bizOrgCode, code);
    }

    @Override
    public Page<Map<String, Object>> selectFoamTank(Page<Map<String, Object>> page) {
        Page<Map<String, Object>> page1 = emergencyMapper.selectFoamTank(page);
        List<Map<String, Object>> res = page1.getRecords();
        if (0 < res.size()) {
            for (Map<String, Object> m : res) {
                Map<String, Object> transResult = UnitTransformUtil.transformValues(String.valueOf(m.get("nowLevel")),
                        String.valueOf(m.get("unit")), String.valueOf(m.get("minLevel")), String.valueOf(m.get("maxLevel")));
                m.put("nowLevel", transResult.get("nowValue"));
                if (StringUtil.isNotEmpty(IndexStatusEnum.getEnumByKey(String.valueOf(transResult.get("status"))))) {
                    m.put("status", IndexStatusEnum.getEnumByKey(String.valueOf(transResult.get("status"))).getDescribe1());
                } else {
                    m.put("status", "--");
                }
                m.put("abs", transResult.get("abs"));
            }
        }
        return page1;
    }

    @Override
    public Page<Map<String, Object>> selectOilDrainage(Page<Map<String, Object>> page, String bizOrgCode, String code) {
        return emergencyMapper.selectOilDrainage(page, bizOrgCode, code);
    }

    @Override
    public Page<Map<String, Object>> selectPressureFlow(Page<Map<String, Object>> page, String bizOrgCode) {
        return emergencyMapper.selectPressureFlow(page, bizOrgCode);
    }

    @Override
    public List<Map<String, Object>> selectAlarmAnalysis(String startDate, String endDate, String dataType, String date, String systemType) {
        List<String> strings = emergencyMapper.selectSystemCodes(systemType);
        if (!CollectionUtils.isEmpty(strings)) {
            return emergencyMapper.selectAlarmAnalysis(startDate, endDate, dataType, date, strings);
        }
        return null;

    }

    @Override
    public List<Map<String, Object>> selectAlarmAnalysisCount(String systemType, String startDate, String endDate) {
        List<String> strings = emergencyMapper.selectSystemCodes(systemType);
        if (!CollectionUtils.isEmpty(strings)) {
            return emergencyMapper.selectAlarmAnalysisCount(startDate, endDate, strings);
        }
        return null;

    }

    @Override
    public Map<String, Object> systemAndCar() {
        return emergencyMapper.getSystemAndCarCount();
    }

    @Override
    public List<Map<String, Object>> selectFireCannonAlarmAnalysisPie(String startDate, String endDate, String systemType) {
        List<String> strings = emergencyMapper.selectSystemCodes(systemType);
        if (!CollectionUtils.isEmpty(strings)) {
            return emergencyMapper.selectFireCannonAlarmAnalysisPie(startDate, endDate, strings);
        }
        return null;
    }

    @Override
    public List<Map<String, Object>> waterSystemAlarmAnalysisPie(String startDate, String endDate, String systemType) {
        List<String> strings = emergencyMapper.selectSystemCodes(systemType);
        if (!CollectionUtils.isEmpty(strings)) {
            return emergencyMapper.waterSystemAlarmAnalysisPie(startDate, endDate, strings);
        }
        return null;
    }

    @Override
    public List<Map<String, Object>> waterSystemAlarmAnalysis(String startDate, String endDate, String dataType, String date, String systemType) {
        List<String> strings = emergencyMapper.selectSystemCodes(systemType);
        if (!CollectionUtils.isEmpty(strings)) {
            return emergencyMapper.waterSystemAlarmAnalysis(startDate, endDate, dataType, date, strings);
        }
        return null;

    }

    @Override
    public List<Map<String, Object>> fireCannonSystemAlarmAnalysis(String startDate, String endDate, String dataType, String date, String systemType) {
        List<String> strings = emergencyMapper.selectSystemCodes(systemType);
        if (!CollectionUtils.isEmpty(strings)) {
            return emergencyMapper.fireCannonSystemAlarmAnalysis(startDate, endDate, dataType, date, strings);
        }
        return null;

    }


    @Override
    public List<Map<String, Object>> getEquipExpiryStatistics(Integer expiryDayNum) {
        List<Map<String, Object>> equipExpiryStatistics = emergencyMapper.getEquipExpiryStatistics(expiryDayNum);
        equipExpiryStatistics.forEach(item -> {
            item.put("value", Integer.parseInt(item.get("value").toString()));
        });
        return equipExpiryStatistics;
    }

    @Override
    public List<Map<String, String>> getEquipExpiryList(Integer expiryDayNum) {

        return emergencyMapper.getEquipExpiryList(expiryDayNum);
    }

    @Override
    public Map<String, Integer> getStockEquipStatistics() {
        return emergencyMapper.getStockEquipStatistics();
    }

    @Override
    public List<Map<String, Object>> getPressurePumpDiagnosticAnalysis(String bizOrgCode) {
        //  从 json 配置文件获取配置信息
        List<Map> infoList = pressurePumpService.getNameKeyInfoList(PressurePumpRelateEnum.PRESSURE_PUMP.getValue());
        if (!CollectionUtils.isEmpty(infoList)) {
            Map map = infoList.get(0);
            String equipmentCode = map.get("equipmentCode").toString();
            String faultNameKey = map.get("faultNameKey").toString();
            //  1. 判断稳压泵整体是否故障
            List<EquipmentSpecificAlarmLog> alarmLogList = equipmentSpecificAlarmLogService.getAlarmLogInfoList(equipmentCode, faultNameKey, PressurePumpRelateEnum.IOT_INDEX_VALUE_TRUE.getValue(), PressurePumpRelateEnum.UN_CLEAN_TIME.getValue(), bizOrgCode);
            PressurePumpAnalysisEnum.PRESSURE_PUMP_FAULT.setValue(CollectionUtils.isEmpty(alarmLogList) ? PressurePumpRelateEnum.NOT_FAULT.getValue() : PressurePumpRelateEnum.FAULT.getValue());
            //  获取redis稳压泵缓存数据，默认JSON配置最近4小时
            List<IotDataVO> DataList = pressurePumpService.getDataToRedis(PressurePumpRelateEnum.PRESSURE_PUMP.getValue(), pressurePumpStart, null);
            List<IotDataVO> DataPipeList = pressurePumpService.getDataToRedis(PressurePumpRelateEnum.PRESSURE_PUMP.getValue(), pressurePumpPipePressure, null);
            String top = map.get("top").toString();
            //  通过 equipmentCode 获取装备
            List<Map<String, Object>> pumpInfoList = equipmentSpecificSerivce.getFirePumpInfoEQ(equipmentCode, bizOrgCode);
            if (!ObjectUtils.isEmpty(pumpInfoList)) {
                String iotCode = pumpInfoList.get(0).get("iotCode").toString();
                if (iotCode.length() > 8) {
                    String prefix = iotCode.substring(0, 8);
                    //获取iot的数据
                    if(ObjectUtils.isEmpty(DataList)){
                        DataList = getIotData(top, prefix, pressurePumpStart);
                    }
                    if(ObjectUtils.isEmpty(DataPipeList)){
                        DataPipeList = getIotData(top, prefix, pressurePumpPipePressure);
                    }
                } else {
                    throw new BadRequest("装备物联编码错误，请确认！");
                }
            }

            String nowStrLong = DateUtils.getDateNowString();
            //  2. 最近一次启停间隔
            long interval = pressurePumpService.getAllPressurePumpStartStopInterval(DataList, nowStrLong);
            //  3. 最近一次启动时长
            long duration = pressurePumpService.getAllPressurePumpStartStopDuration(DataList, nowStrLong);
            //  6. 管网压力状态
            double pressureDiff = pressurePumpService.getAllPressurePumpPipePressureDiff(DataList, DataPipeList, PressurePumpRelateEnum.PRESSURE_PUMP_START_BEFORE_MINUTE.getValue());

            Date dateNow = DateUtils.getDateNow();
            //  2. 最近一次启停间隔
            PressurePumpAnalysisEnum.PRESSURE_PUMP_INTERVAL.setValue(interval);
            //  3. 最近一次启动时长
            PressurePumpAnalysisEnum.PRESSURE_PUMP_DURATION.setValue(duration);
            //  4. 半小时启动
            int halfFrequency = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.HALF_HOUR.getValue()), dateNow);
            PressurePumpAnalysisEnum.PRESSURE_PUMP_HALF.setValue(halfFrequency);
            //  5. 2小时启动
            int twoFrequency = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.TWO_HOUR.getValue()), dateNow);
            PressurePumpAnalysisEnum.PRESSURE_PUMP_TWO.setValue(twoFrequency);
            //  6. 管网压力状态
            PressurePumpAnalysisEnum.PRESSURE_PUMP_PIPE.setValue(pressureDiff > Double.parseDouble(PressurePumpRelateEnum.PIPE_PRESSURE_DIFF.getValue()) ? PressurePumpRelateEnum.PIPE_PRESSURE_ABNORMAL_STATUS.getValue() : PressurePumpRelateEnum.PIPE_PRESSURE_NORMAL_STATUS.getValue());
        }
        return PressurePumpAnalysisEnum.getList();
    }

    private List<IotDataVO> getIotData(String top, String prefix, String indexKey) {
        List<IotDataVO> DataList = new ArrayList<>();
        List<Map<String, String>> iotDataList = pressurePumpService.getIotTopSingleField(top, prefix, null, null, indexKey);
        //将iot的List<Map<String, String>>转化为List<IotDataVO>类型
        iotDataList.stream().forEach(e -> {
            try {
                IotDataVO iotDataVO = (IotDataVO) supervisionVideoService.mapToObject(e, IotDataVO.class);
                DataList.add(iotDataVO);
            } catch (Exception el) {
                throw new BadRequest("IOT数据类型转换失败");
            }
        });
        return DataList;
    }

    @Override
    public Map<String, Object> getPressurePumpStatusChart(String startTime, String endTime, String bizOrgCode) {
        Map<String, Object> map = new LinkedHashMap<>();
        try {
            //  从 json 配置文件获取配置信息
            List<Map> infoList = pressurePumpService.getNameKeyInfoList(PressurePumpRelateEnum.PRESSURE_PUMP.getValue());
            if (!CollectionUtils.isEmpty(infoList)) {
                Map infoMap = infoList.get(0);
                String equipmentCode = infoMap.get("equipmentCode").toString();
                //  获取稳压泵
                List<Map<String, Object>> list = equipmentSpecificSerivce.getListByEquipmentCode(equipmentCode, bizOrgCode);
                //  获取各稳压泵数据，及时间戳
                if (!CollectionUtils.isEmpty(list)) {
                    //  获取查询时间范围内的时间戳
                    List<String> timeHourList = DateUtils.getTimeStrListByStartAndEnd(startTime, endTime, DateUtils.MONTH_DAY_HOUR_MINUTE_PATTERN);
                    Set<String> timeSet = new LinkedHashSet<>();
                    List<Map<String, Object>> yData = new ArrayList<>();
                    LinkedHashMap<String, List<Map<String, String>>> dataListMap = new LinkedHashMap<>();
                    for (Map<String, Object> x : list) {
                        Object iotCode = x.get("iotCode");
                        if (iotCode != null) {
                            //  判断开始时间，是否在redis缓存有效期之内，是，redis获取数据，否则，iot获取数据
                            int expire = Integer.parseInt(infoMap.get("expire").toString()) * -1;
                            Date dateNow = DateUtils.getDateNow();
                            Date beforeDate = DateUtils.dateAddSeconds(dateNow, expire);
                            Date startDate = DateUtils.convertStrToDate(startTime, DateUtils.DATE_TIME_PATTERN);
                            Date endDate = DateUtils.convertStrToDate(endTime, DateUtils.DATE_TIME_PATTERN);
                            if (DateUtils.dateCompare(startDate, beforeDate) >= 0) {
                                //  获取redis稳压泵缓存数据，默认JSON配置最近4小时
                                List<IotDataVO> redisDataList = pressurePumpService.getDataToRedisByDateBetween(PressurePumpRelateEnum.PRESSURE_PUMP.getValue(), pressurePumpStart, iotCode.toString(), startDate, endDate);
                                if (!CollectionUtils.isEmpty(redisDataList)) {
                                    List<Map<String, String>> dataList = new ArrayList<>();
                                    redisDataList.forEach(y -> {
                                        timeSet.add(y.getCreatedTime());
                                        Map<String, String> xMap = new HashMap<>();
                                        xMap.put(pressurePumpStart, y.getValue().toString());
                                        xMap.put(PressurePumpRelateEnum.CREATED_TIME.getValue(), y.getCreatedTime());
                                        dataList.add(xMap);
                                    });
                                    dataListMap.put(iotCode.toString(), dataList);
                                }
                            } else if (iotCode.toString().length() > 8) {
                                //  iot获取数据
                                String prefix = iotCode.toString().substring(0, 8);
                                String suffix = iotCode.toString().substring(8);
                                List<Map<String, String>> dataList = pressurePumpService.getIotCommonListData(startTime, endTime, prefix, suffix, null, pressurePumpStart);
                                dataList.forEach(z -> timeSet.add(z.get(PressurePumpRelateEnum.CREATED_TIME.getValue())));
                                dataListMap.put(iotCode.toString(), dataList);
                            }
                        }
                    }
                    //  数据时间排序
                    List<String> sortTimeList = new ArrayList<>(timeSet);
                    Collections.sort(sortTimeList);
                    //  数据时间截取，MM-dd HH:mm
                    //                List<String> sortTimeCollectList = sortTimeList.stream().map(x -> DateUtils.dateFormat(DateUtils.convertStrToDate(x, DateUtils.DATE_TIME_PATTERN),DateUtils.MONTH_DAY_HOUR_MINUTE_PATTERN)).collect(Collectors.toList());
                    List<String> sortTimeCollectList = sortTimeList.stream().map(x -> x.substring(5, x.length() - 3)).collect(Collectors.toList());
                    //  数据时间截取，MM-dd HH
                    List<String> sortTimeTmpCollectList = sortTimeList.stream().map(x -> x.substring(5, x.length() - 6)).collect(Collectors.toList());
                    //  组装x时间轴数据
                    List<String> timeList = new ArrayList<>();
                    timeHourList.forEach(t -> {
                        String strTime = t.substring(0, t.length() - 3);
                        if (sortTimeCollectList.contains(t)) {
                            timeList.add(t);
                        } else if (!sortTimeTmpCollectList.contains(strTime)) {
                            timeList.add(strTime + ":00");
                            sortTimeTmpCollectList.add(strTime);
                        }
                    });
                    //  遍历稳压泵，dataListMap获取各稳压泵数据，没有数据的进行补0
                    list.forEach(x -> {
                        Map<String, Object> yMap = new HashMap<>();
                        List<Integer> yList = new ArrayList<>();
                        String name = x.get("name").toString();
                        yMap.put("name", name);
                        Object iotCode = x.get("iotCode");
                        if (x.get("iotCode") != null) {
                            List<Map<String, String>> dataList = dataListMap.get(iotCode.toString());
                            if (!CollectionUtils.isEmpty(dataList)) {
                                Collections.reverse(dataList);
                                Map<String, List<Map<String, String>>> dataMap = dataList.stream().filter(y -> y.containsKey(PressurePumpRelateEnum.CREATED_TIME.getValue())).collect(Collectors.groupingBy(e -> e.get("createdTime").substring(5, 16)));
                                List<Map<String, String>> yDataList = null;
                                for (String t : timeList) {
                                    List<Map<String, String>> data = dataMap.get(t);
                                    if (!CollectionUtils.isEmpty(data)) {
                                        yDataList = data.stream().filter(o -> PressurePumpRelateEnum.IOT_INDEX_VALUE_TRUE.getValue().equalsIgnoreCase(o.get(pressurePumpStart))).collect(Collectors.toList());
                                        String flag = data.get(data.size() - 1).get(pressurePumpStart);
                                        yList.add(!CollectionUtils.isEmpty(yDataList) ? Integer.parseInt(PressurePumpRelateEnum.START.getValue()) : PressurePumpRelateEnum.IOT_INDEX_VALUE_TRUE.getValue().equalsIgnoreCase(flag) ? Integer.parseInt(PressurePumpRelateEnum.START.getValue()) : Integer.parseInt(PressurePumpRelateEnum.STOP.getValue()));
                                    } else {
                                        yList.add(Integer.parseInt(PressurePumpRelateEnum.STOP.getValue()));
                                    }
                                }
                            } else {
                                timeList.forEach(t -> {
                                    yList.add(Integer.parseInt(PressurePumpRelateEnum.STOP.getValue()));
                                });
                            }
                            yMap.put("data", yList);
                            yData.add(yMap);
                        }
                    });
                    map.put("xData", timeList);
                    map.put("yData", yData);
                }
            }
        } catch (Exception e) {
            log.error("getPressurePumpStatusChart-->获取稳压泵启停状态图失败：{}", e.getMessage());
        }
        return map;
    }


    @Override
    public Page<Map<String, Object>> alarmList(Page<Map<String, Object>> page, String bizOrgCode, List<String> types, List<String> emergencyLevels, String name, Integer cleanStatus, Integer handleStatus) {
        return emergencyMapper.alarmList(page, bizOrgCode, types, emergencyLevels, name, cleanStatus, handleStatus);
    }
}
