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.amos.boot.biz.common.utils.CommonUtils;
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.mapper.FireFightingSystemMapper;
import com.yeejoin.equipmanage.mapper.SupervisionVideoMapper;
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.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
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 FireFightingSystemMapper fireFightingSystemMapper;

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

    @Override
    public List<AlamVideoVO> queryVideoList(String bizOrgCode) {
        List<AlamVideoVO> list = supervisionVideoMapper.getVideoByCompany(bizOrgCode);
        list.forEach(action -> {
            action.setVedioFormat(vedioFormat);
            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) {
        Date dateNow = DateUtils.getDateNow();
        String nowStrLong = DateUtils.getNowStrLong();
        Long interval = 0L;
        //全部稳压泵半小时、一小时、两小时、四小时启动次数
        int halfHourStartNum = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.HALF_HOUR.getValue()), dateNow);
        int oneHourStartNum = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.ONE_HOUR.getValue()), dateNow);
        int twoHourStartNum = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.TWO_HOUR.getValue()), dateNow);
        int fourHourStartNum = pressurePumpService.getAllPressurePumpStartFrequency(Double.parseDouble(PressurePumpRelateEnum.FOUR_HOUR.getValue()), dateNow);
        Page<Map<String, Object>> 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);
            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_FALSE.getValue().contains(stateMap.get("equipment_index_name"))){
                        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;
                        }
                    }
                    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());
        }

        List<Map> infoList = pressurePumpService.getNameKeyInfoList(PressurePumpRelateEnum.PRESSURE_PUMP.getValue());
        if (!CollectionUtils.isEmpty(infoList)) {
            // 获取redis稳压泵缓存数据，默认JSON配置最近4小时
            List<IotDataVO> DataList = pressurePumpService.getDataToRedis(PressurePumpRelateEnum.PRESSURE_PUMP.getValue(), pressurePumpStart, null);
            if(CollectionUtils.isEmpty(DataList)){
                //从influxdb中获取最近一次启停间隔
                String top = infoList.get(0).get("top").toString();
                List<Map<String, String>> iotDataList = pressurePumpService.getIotTopSingleField(top, prefix, null, null, pressurePumpStart);
                iotDataList.stream().forEach(e -> {
                    try {
                        IotDataVO iotDataVO = (IotDataVO) mapToObject(e, IotDataVO.class);
                        DataList.add(iotDataVO);
                    } catch (Exception el) {
                        throw new RuntimeException();
                    }
                });

            }
            interval =pressurePumpService.getAllPressurePumpStartStopInterval(DataList, 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;
    }

    /**
     * map 转化为对象
     * @param map 需要转化的参数
     * @param aClass 要转化成的对象
     * @return 转化成功的对象
     * @throws IllegalAccessException 非法访问异常
     * @throws InstantiationException 实例化异常
     */
    public Object mapToObject(Map<String,String> map,Class<?> aClass) throws IllegalAccessException, InstantiationException {
        if(null == map || map.size()<=0){
            return null;
        }
        Object o = aClass.newInstance();
        Field[] declaredFields = o.getClass().getDeclaredFields();
        for (Field field :declaredFields) {
            int modifiers = field.getModifiers();
            if(Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)){
                continue;
            }
            // （此处如果不设置 无法获取对象的私有属性）
            field.setAccessible(true);
            if("key".equals(field.getName())){
                field.set(o,pressurePumpStart);
            } else if("value".equals(field.getName())){
                field.set(o,map.get(pressurePumpStart));
            } else {
                field.set(o,map.get(field.getName()));
            }

        }
        return o;
    }
}
