package com.yeejoin.equipmanage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeejoin.equipmanage.common.entity.SupervisionVideo;
import com.yeejoin.equipmanage.common.entity.vo.AlamVideoVO;
import com.yeejoin.equipmanage.common.enums.PressurePumpRelateEnum;
import com.yeejoin.equipmanage.common.utils.DateUtils;
import com.yeejoin.equipmanage.common.vo.IotDataVO;
import com.yeejoin.equipmanage.common.vo.PressurePumpCountVo;
import com.yeejoin.equipmanage.mapper.FireFightingSystemMapper;
import com.yeejoin.equipmanage.mapper.SupervisionVideoMapper;
import com.yeejoin.equipmanage.service.IEquipmentSpecificSerivce;
import com.yeejoin.equipmanage.service.IPressurePumpService;
import com.yeejoin.equipmanage.service.ISupervisionVideoService;
import com.yeejoin.equipmanage.service.IVideoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


@Slf4j
@Service
//@EnableAsync
public class SupervisionVideoServiceImpl extends ServiceImpl<SupervisionVideoMapper, SupervisionVideo> implements ISupervisionVideoService {

    @Autowired
    SupervisionVideoMapper supervisionVideoMapper;
    @Value("${window.vedioFormat.video}")
    String vedioFormat;
    @Autowired
    private IVideoService videoService;
    @Autowired
    private IPressurePumpService pressurePumpService;

    @Autowired
    private IEquipmentSpecificSerivce equipmentSpecificSerivce;

    @Autowired
    private FireFightingSystemMapper fireFightingSystemMapper;

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

    @Override
    public List<AlamVideoVO> queryVideoList(String bizOrgCode) {
        List<AlamVideoVO> list = supervisionVideoMapper.getVideoByCompany(bizOrgCode);
        if (0 < list.size()) {
            list.forEach(action -> {
                action.setVedioFormat(action.getVideoType());
                action.setUrl(videoService.getVideoUrl(action.getName(), action.getPresetPosition(), action.getUrl(), action.getCode()));
            });
        }
        return list;
    }


    @Override
    public boolean replaceVideo(Map<String, String> map, String bizOrgCode) {
        supervisionVideoMapper.delete(new QueryWrapper<SupervisionVideo>().eq("biz_org_code", bizOrgCode));
        List<SupervisionVideo> list = new ArrayList<>();
        String ids = map.get("ids");
        if (StringUtils.isNotEmpty(ids)) {
            for (String s : ids.split(",")) {
                SupervisionVideo supervisionVideo = new SupervisionVideo();
                supervisionVideo.setCameraId(s);
                supervisionVideo.setBizOrgCode(bizOrgCode);
                supervisionVideo.setId(Long.valueOf(String.valueOf(UUID.randomUUID().getLeastSignificantBits()).replace("-", "")));
                list.add(supervisionVideo);
            }
        }
        return saveBatch(list);
    }

    @Override
    public List<String> queryVideoAllId(String bizOrgCode) {
        return supervisionVideoMapper.queryVideoAllId(bizOrgCode);
    }

    @Override
    public Page<Map<String, Object>> queryPumpInfo(Page page, String bizOrgCode) {
        //  从 json 配置文件获取配置信息
        List<Map> infoList = pressurePumpService.getNameKeyInfoList(PressurePumpRelateEnum.PRESSURE_PUMP.getValue());
        Page<Map<String, Object>> pressurePumpInfo = new Page<>();
        if (!CollectionUtils.isEmpty(infoList)) {
            Map map = infoList.get(0);
            String equipmentCode = map.get("equipmentCode").toString();
            String top = map.get("top").toString();
            String countRedisKey = map.get("countRedisKey").toString();
            long countExpire = Long.parseLong(map.get("countExpire").toString());
            Date dateNow = DateUtils.getDateNow();
            String nowStrLong = DateUtils.getNowStrLong();
            //  获取稳压泵数据，redis没有，从iot取
            List<Map<String, Object>> pumpInfoList = equipmentSpecificSerivce.getFirePumpInfoEQ(equipmentCode, bizOrgCode);
            Map<String, List<IotDataVO>> dataMap = pressurePumpService.getDataList(pumpInfoList, PressurePumpRelateEnum.PRESSURE_PUMP.getValue(), equipmentCode, top, pressurePumpStart, bizOrgCode, null);
            List<IotDataVO> dataListFilterTrue = dataMap.get("dataListFilterTrue");
            List<IotDataVO> dataListFilterFalse = dataMap.get("dataListFilterFalse");
            Long interval = 0L;
            //全部稳压泵半小时、一小时、两小时、四小时启动次数
            int halfHourStartNum = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.HALF_HOUR.getValue()), dataListFilterTrue, dateNow);
            int oneHourStartNum = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.ONE_HOUR.getValue()), dataListFilterTrue, dateNow);
            int twoHourStartNum = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.TWO_HOUR.getValue()), dataListFilterTrue, dateNow);
            int fourHourStartNum = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.FOUR_HOUR.getValue()), dataListFilterTrue, dateNow);
            //  近3天启动平均值，四合五入
            AtomicInteger dayAvgFrequency = new AtomicInteger();
            try {
                Date startDate = com.yeejoin.amos.boot.biz.common.utils.DateUtils.dateAddDays(dateNow, Integer.parseInt(PressurePumpRelateEnum.DAY_AVG.getValue()));
                String startTime = String.join(" ", com.yeejoin.amos.boot.biz.common.utils.DateUtils.dateFormat(startDate, com.yeejoin.amos.boot.biz.common.utils.DateUtils.DATE_PATTERN), "00:00:00");
                String endTime = String.join(" ", com.yeejoin.amos.boot.biz.common.utils.DateUtils.dateFormat(dateNow, com.yeejoin.amos.boot.biz.common.utils.DateUtils.DATE_PATTERN), "00:00:00");
                Map<String, List<PressurePumpCountVo>> dayAvgDataMap = pressurePumpService.getDateRangeCountList(pumpInfoList, startTime,endTime, PressurePumpRelateEnum.PRESSURE_PUMP.getValue(), countRedisKey, equipmentCode, pressurePumpStart, countExpire, bizOrgCode);
                if (!CollectionUtils.isEmpty(dayAvgDataMap)) {
                    for (List<PressurePumpCountVo> voList : dayAvgDataMap.values()) {
                        if (!CollectionUtils.isEmpty(voList)) {
                            voList.forEach(x -> dayAvgFrequency.addAndGet(x.getValue()));
                        }
                    }
                }
            } catch (ParseException e) {
                log.error("近3天平均启动次数获取失败-->dayAvgFrequency：{}", e.getMessage());
            }
            DecimalFormat df = new DecimalFormat("0.0");
            int dayAvgCount = dayAvgFrequency.get();
            String dayAvgStartNum = dayAvgCount == 0 ? "0" : df.format(dayAvgCount / (double) Math.abs(Integer.parseInt(PressurePumpRelateEnum.DAY_AVG.getValue())));
            pressurePumpInfo = fireFightingSystemMapper.getPressurePumpInfo(page, bizOrgCode, null);
            String prefix = null;
            for (Map<String, Object> item : pressurePumpInfo.getRecords()) {
                String suffix = null;
                String iotCode = item.get("iot_code").toString();
                if (iotCode.length() > 8) {
                    prefix = iotCode.substring(0, 8);
                    suffix = iotCode.substring(8);
                } else {
                    throw new BadRequest("装备物联编码错误，请确认！");
                }
                Date mounthDate = null;
                try {
                    mounthDate = DateUtils.getCurrentMonthStartTime(new Date());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                String startDateStr = DateUtils.convertDateToString(mounthDate, DateUtils.DATE_TIME_PATTERN);
                //稳压泵本月累计启动统计
                List<Map<String, String>> mounthEntity =
                        pressurePumpService.getIotCommonListData(startDateStr, nowStrLong, prefix, suffix, (PressurePumpRelateEnum.IOT_INDEX_VALUE_TRUE.getValue()), pressurePumpStart);
                item.put("monthStartNum", ObjectUtils.isEmpty(mounthEntity) ? 0 : mounthEntity.size());
                item.put("halfHourStartNum", halfHourStartNum);
                item.put("oneHourStartNum", oneHourStartNum);
                item.put("twoHourStartNum", twoHourStartNum);
                item.put("fourHourStartNum", fourHourStartNum);
                item.put("dayAvgStartNum", dayAvgStartNum);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                long nowDateTime = new Date().getTime();//当前时间戳
                boolean time = true;
                //获取最近的一个触发物联指标的时间
                Map<String, String> stateMap = fireFightingSystemMapper.queryPressureNowSignalBySpecificId((Long) item.get("id"));
                Long update_date = 0L;
                if (!ObjectUtils.isEmpty(stateMap)) {
                    try {
                        //如果当前指标为启动，并且指标值为true,计算启动时长
                        if(PressurePumpRelateEnum.START.getDesc().contains(stateMap.get("equipment_index_name")) && PressurePumpRelateEnum.IOT_INDEX_VALUE_TRUE.getValue().contains(stateMap.get("value"))){
                            update_date = sdf.parse(stateMap.get("update_date")).getTime();
                            long res = nowDateTime - update_date;
                            long diffMinute = res / 1000 / 60;
                            if (diffMinute > Long.valueOf(PressurePumpRelateEnum.START_FIVE.getValue())) {
                                time = false;
                            }
                        }
                        if(PressurePumpRelateEnum.IOT_INDEX_VALUE_FALSE.getValue().contains(stateMap.get("value"))){
                            if(PressurePumpRelateEnum.START.getDesc().contains(stateMap.get("equipment_index_name"))){
                                item.put("equipment_index_name", PressurePumpRelateEnum.STOP.getDesc());
                            } else {
                                item.put("equipment_index_name", PressurePumpRelateEnum.RESET.getDesc());
                            }
                        } else {
                            item.put("equipment_index_name", stateMap.get("equipment_index_name"));
                        }
                        item.put("update_time", stateMap.get("update_date"));
                    } catch (ParseException e) {
                        throw new BadRequest("稳压泵最新指标时间转换失败！");
                    }
                } else {
                    item.put("equipment_index_name", "无信号");
                    item.put("update_time", false);
                }
                //稳压泵当前状态   无告警并且启动时长小于5分钟为正常
                item.put("stateDesc", Integer.parseInt(String.valueOf(item.get("isAlarm"))) == 0 && time ? PressurePumpRelateEnum.PIPE_PRESSURE_NORMAL_STATUS.getValue() : PressurePumpRelateEnum.PIPE_PRESSURE_ABNORMAL_STATUS.getValue());
            }

            // 获取redis稳压泵缓存数据，默认JSON配置最近4小时
            List<IotDataVO> DataList = pressurePumpService.getDataToRedis(PressurePumpRelateEnum.PRESSURE_PUMP.getValue(), pressurePumpStart, null, bizOrgCode);
            if(CollectionUtils.isEmpty(DataList)){
                //从influxdb中获取最近一次启停间隔
                List<Map<String, String>> iotDataList = pressurePumpService.getIotTopSingleField(top, prefix, null, null, pressurePumpStart);
                iotDataList.forEach(e -> {
                    try {
                        IotDataVO iotDataVO = (IotDataVO) pressurePumpService.mapToObject(e, IotDataVO.class, pressurePumpStart);
                        DataList.add(iotDataVO);
                    } catch (Exception el) {
                        throw new RuntimeException();
                    }
                });
            }
            interval =pressurePumpService.getAllPressurePumpStartStopInterval(DataList, dataListFilterTrue, dataListFilterFalse, nowStrLong);
            double finalDiffMinute = (double) interval;
            pressurePumpInfo.getRecords().stream(
            ).map(item -> {
                item.put("startAndStopInterval", finalDiffMinute);
                if (finalDiffMinute <= Long.valueOf(PressurePumpRelateEnum.START_FIVE.getValue())) {
                    item.put("generalState", PressurePumpRelateEnum.PIPE_PRESSURE_ABNORMAL_STATUS.getValue());
                } else {
                    item.put("generalState", PressurePumpRelateEnum.PIPE_PRESSURE_NORMAL_STATUS.getValue());
                }
                item.put("nameKey", pressurePumpStart);
                return item;
            }).collect(Collectors.toList());
            List<Map<String, Object>> records = pressurePumpInfo.getRecords();
            records.sort((t1, t2) -> t1.get("stateDesc").toString().compareTo(t2.get("stateDesc").toString()));
            pressurePumpInfo.setRecords(records);
        }
        return pressurePumpInfo;
    }

    @Override
    public List<Map<String, Object>> selectPressureDetails(String bizOrgCode) {
        List<Map<String, Object>> pressurePumpInfo = fireFightingSystemMapper.selectAllPressurePumpInfo(bizOrgCode);
        pressurePumpInfo.stream().map(item -> {
            String prefix = null;
            String suffix = null;
            String iotCode = item.get("iot_code").toString();
            if (iotCode.length() > 8) {
                prefix = iotCode.substring(0, 8);
                suffix = iotCode.substring(8);
            } else {
                throw new BadRequest("装备物联编码错误，请确认！");
            }
            //通过iot最近一次的启动和停止时间
            List<Map<String, String>> trueData = pressurePumpService.getIotTopSingleField(PressurePumpRelateEnum.ONE_TIME.getValue(), prefix, suffix, PressurePumpRelateEnum.IOT_INDEX_VALUE_TRUE.getValue(), pressurePumpStart);
            List<Map<String, String>> falseData = pressurePumpService.getIotTopSingleField(PressurePumpRelateEnum.ONE_TIME.getValue(), prefix, suffix, PressurePumpRelateEnum.IOT_INDEX_VALUE_FALSE.getValue(), pressurePumpStart);
            if(!ObjectUtils.isEmpty(trueData)){
                item.put("startTime", trueData.get(0).get("createdTime"));
            } else {
                item.put("startTime", "");
            }
            if(!ObjectUtils.isEmpty(falseData)){
                item.put("stopTime", falseData.get(0).get("createdTime"));
            } else {
                item.put("stopTime", "");
            }
            return item;
        }).collect(Collectors.toList());
        return pressurePumpInfo;
    }

}
