package com.prolog.rdc.tms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.rdc.tms.dao.mapper.TmsGpsDataE6Mapper;
import com.prolog.rdc.tms.dao.mapper.TmsGpsDataG7Mapper;
import com.prolog.rdc.tms.dao.mapper.TmsGpsDataMapper;
import com.prolog.rdc.tms.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.TmsTemperatureDataE6Mapper;
import com.prolog.rdc.tms.dao.mapper.TmsTemperatureDataG7Mapper;
import com.prolog.rdc.tms.dao.mapper.TmsTemperatureDataMapper;
import com.prolog.rdc.tms.dao.mapper.TmsVehicleAlarmE6Mapper;
import com.prolog.rdc.tms.dao.mapper.TmsVehicleAlarmG7Mapper;
import com.prolog.rdc.tms.dao.mapper.TmsVehicleAlarmMapper;
import com.prolog.rdc.tms.model.constant.RedisConstant;
import com.prolog.rdc.tms.model.dto.e6.EquipInfoDTO;
import com.prolog.rdc.tms.model.dto.g7.CTemperaturePropertiesDTO;
import com.prolog.rdc.tms.model.dto.g7.CurrentGpsLocationDTO;
import com.prolog.rdc.tms.model.dto.g7.CurrentTemperatureDTO;
import com.prolog.rdc.tms.model.entity.TmsGpsDataModel;
import com.prolog.rdc.tms.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.model.entity.TmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillDetailModel;
import com.prolog.rdc.tms.model.entity.gps.TmsGpsDataE6;
import com.prolog.rdc.tms.model.entity.gps.TmsGpsDataG7;
import com.prolog.rdc.tms.model.entity.gps.TmsTemperatureData;
import com.prolog.rdc.tms.model.entity.gps.TmsTemperatureDataE6;
import com.prolog.rdc.tms.model.entity.gps.TmsTemperatureDataG7;
import com.prolog.rdc.tms.model.entity.gps.TmsVehicleAlarm;
import com.prolog.rdc.tms.model.entity.gps.TmsVehicleAlarmE6;
import com.prolog.rdc.tms.model.entity.gps.TmsVehicleAlarmG7;
import com.prolog.rdc.tms.model.vo.PullGpsDataVO;
import com.prolog.rdc.tms.model.vo.e6.EquipInfoVO;
import com.prolog.rdc.tms.model.vo.g7.CurrentTemperatureVO;
import com.prolog.rdc.tms.rmi.feign.InterfaceFeign;
import com.prolog.rdc.tms.service.GpsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author hongbo.pan
 * @date 2023/3/23
 */
@Slf4j
@Service
public class GpsServiceImpl implements GpsService {

    public static final String E6 = "E6";
    public static final String G7 = "G7";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private InterfaceFeign interfaceFeign;

    @Autowired
    private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

    @Autowired
    private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

    @Autowired
    private TmsShipbillDetailMapper tmsShipbillDetailMapper;

    @Autowired
    private TmsGpsDataE6Mapper tmsGpsDataE6Mapper;

    @Autowired
    private TmsGpsDataG7Mapper tmsGpsDataG7Mapper;

    @Autowired
    private TmsGpsDataMapper tmsGpsDataMapper;

    @Autowired
    private TmsTemperatureDataMapper tmsTemperatureDataMapper;

    @Autowired
    private TmsTemperatureDataE6Mapper tmsTemperatureDataE6Mapper;

    @Autowired
    private TmsTemperatureDataG7Mapper tmsTemperatureDataG7Mapper;

    @Autowired
    private TmsVehicleAlarmE6Mapper tmsVehicleAlarmE6Mapper;

    @Autowired
    private TmsVehicleAlarmG7Mapper tmsVehicleAlarmG7Mapper;

    @Autowired
    private TmsVehicleAlarmMapper tmsVehicleAlarmMapper;

    private static Map<String, String> g7AlarmTypeMap = new HashMap<String, String>(){
        {
            put("1", "高温预警");
            put("2", "高温报警");
            put("3", "温度传感器异常报警");
            put("4", "高湿度预警");
            put("5", "高湿度报警");
            put("6", "湿度传感器异常报警");
            put("7", "电量报警");
            put("8", "光感报警");
            put("9", "其他报警");
            put("10", "低温预警");
            put("11", "低温报警");
            put("12", "低湿度预警");
            put("13", "低湿度报警");
            put("14", "设备开机报警");
            put("15", "设备关机报警");
            put("16", "手动开关状态");
            put("17", "温度湿度预警报警总开关状态");
            put("18", "低功耗状态");
            put("19", "任务状态");
            put("20", "重启");
            put("21", "外电断开");
        }
    };

    @Override
    public void pullGpsData(PullGpsDataVO vo) {
        log.info("开始拉取gps任务={}", JSON.toJSONString(vo));
//        redisTemplate.opsForSet().add(RedisConstant.PULL_GPS_DEVICE_E6_KEY, "HR220308105798");
//        redisTemplate.opsForSet().add(RedisConstant.PULL_GPS_DEVICE_G7_KEY, "71017854");
//        redisTemplate.opsForSet().add(RedisConstant.PULL_GPS_DEVICE_G7_KEY, "90037836");
        if (redisTemplate.hasKey(RedisConstant.PULL_GPS_DEVICE_E6_KEY)) {
            Set<String> e6Set = redisTemplate.opsForSet().members(RedisConstant.PULL_GPS_DEVICE_E6_KEY);
            log.info("redis key={},data={}", RedisConstant.PULL_GPS_DEVICE_E6_KEY, JSON.toJSONString(e6Set));
            if (CollectionUtil.isNotEmpty(e6Set)) {
                saveE6Data(vo, e6Set.stream().collect(Collectors.joining(",")));
            }
        }

        if (redisTemplate.hasKey(RedisConstant.PULL_GPS_DEVICE_G7_KEY)) {
            Set<String> g7Set = redisTemplate.opsForSet().members(RedisConstant.PULL_GPS_DEVICE_G7_KEY);
            log.info("redis key={},data={}", RedisConstant.PULL_GPS_DEVICE_G7_KEY, JSON.toJSONString(g7Set));
            if (CollectionUtil.isNotEmpty(g7Set)) {
                saveG7Data(vo, g7Set.stream().collect(Collectors.joining(",")));
            }
        }
        log.info("结束拉取gps任务");
    }


    /**
     * saveE6Data
     * @param vo
     * @param deviceCode
     */
    private void saveE6Data(PullGpsDataVO vo, String deviceCode) {
        EquipInfoVO equipInfoVO = new EquipInfoVO();
        equipInfoVO.setEquipCode(deviceCode);
        RestMessage<List<EquipInfoDTO>> equipInfoResult = null;
        try {
            equipInfoResult = interfaceFeign.getEquipInfoReal(equipInfoVO);
        } catch (Exception e) {
            log.error("易流设备定位报错，deviceCode={}", deviceCode, e);
        } finally {
            log.info("saveE6Data request={},response={}", JSON.toJSONString(equipInfoVO), JSON.toJSONString(equipInfoResult));
        }
        if (equipInfoResult.isSuccess()) {
            if (CollectionUtil.isNotEmpty(equipInfoResult.getData())) {
                equipInfoResult.getData().forEach(equipInfoDTO -> {
                    TmsLoadingBillHeaderModel lastLoadingBill = lastLoadingBill(equipInfoDTO.getEquipCode());
                    if (ObjectUtil.isNotNull(lastLoadingBill)) {
                        List<TmsShipbillDetailModel> tmsShipbillDetailModelList = getShipBillDetail(lastLoadingBill.getLoadingBillId());
                        saveTmsGpsDataE6(equipInfoDTO, vo, lastLoadingBill);
                        saveTmsTemperatureDataE6(equipInfoDTO, vo, lastLoadingBill, tmsShipbillDetailModelList);
                        saveTmsVehicleAlarmE6(equipInfoDTO, vo, lastLoadingBill, tmsShipbillDetailModelList);
                    }
                });
            }
        }
    }

    /**
     * saveTmsGpsDataE6
     * @param equipInfoDTO
     * @param vo
     * @param lastLoadingBill
     * @return
     */
    private void saveTmsGpsDataE6(EquipInfoDTO equipInfoDTO, PullGpsDataVO vo, TmsLoadingBillHeaderModel lastLoadingBill) {
        TmsGpsDataE6 tmsGpsDataE6 = new TmsGpsDataE6();
        tmsGpsDataE6.setId(UUID.randomUUID().toString());
        tmsGpsDataE6.setVehicle(lastLoadingBill.getVehiclePlateNumber());
        tmsGpsDataE6.setGpsTime(equipInfoDTO.getGpsTime());
        tmsGpsDataE6.setLon(equipInfoDTO.getLon());
        tmsGpsDataE6.setLat(equipInfoDTO.getLat());
        tmsGpsDataE6.setSpeed(equipInfoDTO.getSpeed());
        tmsGpsDataE6.setDirection(equipInfoDTO.getDirection());
        tmsGpsDataE6.setEquipCode(equipInfoDTO.getEquipCode());
        tmsGpsDataE6.setCreatetime(DateUtil.date());
        tmsGpsDataE6Mapper.save(tmsGpsDataE6);

        TmsGpsDataModel gpsDataModel = new TmsGpsDataModel();
        gpsDataModel.setId(UUID.randomUUID().toString());
        gpsDataModel.setDeviceCode(lastLoadingBill.getVehicleDeviceCode());
        gpsDataModel.setDeviceName(lastLoadingBill.getVehicleDeviceName());
        gpsDataModel.setVehiclePlateNumber(lastLoadingBill.getVehiclePlateNumber());
        gpsDataModel.setDriverName(lastLoadingBill.getDriverName());
        gpsDataModel.setDriverPhoneNumber(lastLoadingBill.getDriverPhoneNumber());
        gpsDataModel.setLongitude(equipInfoDTO.getLon());
        gpsDataModel.setLatitude(equipInfoDTO.getLat());
        gpsDataModel.setGpsDate(equipInfoDTO.getGpsTime());
        gpsDataModel.setCurrentVelocity(equipInfoDTO.getSpeed());
        gpsDataModel.setVehicleDirection(equipInfoDTO.getDirection());
        gpsDataModel.setEnterpriseId(vo.getEnterpriseId());
        gpsDataModel.setCreatetime(DateUtil.date());
        gpsDataModel.setUpdatetime(DateUtil.date());
        gpsDataModel.setSourceType(E6);
        gpsDataModel.setSourceId(tmsGpsDataE6.getId());
        tmsGpsDataMapper.save(gpsDataModel);
    }

    /**
     * saveTmsTemperatureDataE6
     * @param equipInfoDTO
     * @param vo
     * @param lastLoadingBill
     * @param tmsShipbillDetailModelList
     * @return
     */
    private void saveTmsTemperatureDataE6(EquipInfoDTO equipInfoDTO, PullGpsDataVO vo, TmsLoadingBillHeaderModel lastLoadingBill, List<TmsShipbillDetailModel> tmsShipbillDetailModelList) {
        TmsTemperatureDataE6 tmsTemperatureDataE6 = new TmsTemperatureDataE6();
        tmsTemperatureDataE6.setId(UUID.randomUUID().toString());
        tmsTemperatureDataE6.setVehicle(lastLoadingBill.getVehiclePlateNumber());
        tmsTemperatureDataE6.setGpsTime(equipInfoDTO.getGpsTime());
        tmsTemperatureDataE6.setLat(equipInfoDTO.getLat());
        tmsTemperatureDataE6.setLon(equipInfoDTO.getLon());
        tmsTemperatureDataE6.setTemperature(equipInfoDTO.getT1());
        tmsTemperatureDataE6.setTemperature2(equipInfoDTO.getT2());
        tmsTemperatureDataE6.setTemperature3(equipInfoDTO.getT3());
        tmsTemperatureDataE6.setTemperature4(equipInfoDTO.getT4());
        tmsTemperatureDataE6.setCreatetime(DateUtil.date());
        tmsTemperatureDataE6Mapper.save(tmsTemperatureDataE6);

        TmsTemperatureData tmsTemperatureData = new TmsTemperatureData();
        tmsTemperatureData.setId(UUID.randomUUID().toString());
        tmsTemperatureData.setVehiclePlateNumber(lastLoadingBill.getVehiclePlateNumber());
        tmsTemperatureData.setDeviceCode(lastLoadingBill.getVehicleDeviceCode());
        tmsTemperatureData.setTemperature(equipInfoDTO.getT1());
        tmsTemperatureData.setLongitude(equipInfoDTO.getLon());
        tmsTemperatureData.setLatitude(equipInfoDTO.getLat());
        tmsTemperatureData.setTime(equipInfoDTO.getGpsTime());
        tmsTemperatureData.setEnterpriseId(vo.getEnterpriseId());
        tmsTemperatureData.setCreatetime(DateUtil.date());
        tmsTemperatureData.setUpdatetime(DateUtil.date());
        tmsTemperatureData.setSourceType(E6);
        tmsTemperatureData.setSourceId(tmsTemperatureDataE6.getId());
        tmsTemperatureData.setLoadingBillId(lastLoadingBill.getLoadingBillId());
        tmsTemperatureData.setShipbillId(getShipBillId(tmsShipbillDetailModelList));
        tmsTemperatureDataMapper.save(tmsTemperatureData);
    }

    /**
     * saveTmsVehicleAlarmE6
     * @param equipInfoDTO
     * @param vo
     * @param lastLoadingBill
     * @param tmsShipbillDetailModelList
     * @return
     */
    private void saveTmsVehicleAlarmE6(EquipInfoDTO equipInfoDTO, PullGpsDataVO vo, TmsLoadingBillHeaderModel lastLoadingBill, List<TmsShipbillDetailModel> tmsShipbillDetailModelList) {
        if (NumberUtil.isLess(equipInfoDTO.getVoltage(), BigDecimal.valueOf(20))) {
            saveTmsVehicleAlarmE6(equipInfoDTO, vo, lastLoadingBill, tmsShipbillDetailModelList, "E6-电量过低", "电量数值低于20，当前电量=" + equipInfoDTO.getVoltage());
        }
        if (!"正常".equals(equipInfoDTO.getPowerStatus())) {
            saveTmsVehicleAlarmE6(equipInfoDTO, vo, lastLoadingBill, tmsShipbillDetailModelList, "E6-电源状态非正常", "电源状态非正常，当前电源状态=" + equipInfoDTO.getPowerStatus());
        }
        if (CollectionUtil.isNotEmpty(tmsShipbillDetailModelList)) {
            Optional<BigDecimal> lowerLimit = tmsShipbillDetailModelList.stream().map(TmsShipbillDetailModel::getTemperatureCtlLowerLimit).filter(ObjectUtil::isNotNull).max(BigDecimal::compareTo);
            if (lowerLimit.isPresent() && NumberUtil.isLess(equipInfoDTO.getT1(), lowerLimit.get())) {
                saveTmsVehicleAlarmE6(equipInfoDTO, vo, lastLoadingBill, tmsShipbillDetailModelList, "E6-低温报警", "低温报警，当前温度=" + equipInfoDTO.getT1() + "，最低温度=" + lowerLimit.get());
            }
            Optional<BigDecimal> upperLimit = tmsShipbillDetailModelList.stream().map(TmsShipbillDetailModel::getTemperatureCtlUpperLimit).filter(ObjectUtil::isNotNull).min(BigDecimal::compareTo);
            if (upperLimit.isPresent() && NumberUtil.isGreater(equipInfoDTO.getT1(), upperLimit.get())) {
                saveTmsVehicleAlarmE6(equipInfoDTO, vo, lastLoadingBill, tmsShipbillDetailModelList, "E6-高温报警", "高温报警，当前温度=" + equipInfoDTO.getT1() + "，最高温度=" + upperLimit.get());
            }
        }
    }

    /**
     * saveTmsVehicleAlarmE6
     * @param equipInfoDTO
     * @param vo
     * @param lastLoadingBill
     * @param tmsShipbillDetailModelList
     * @param alarmType
     * @param alarmContent
     * @return
     */
    private void saveTmsVehicleAlarmE6(EquipInfoDTO equipInfoDTO, PullGpsDataVO vo, TmsLoadingBillHeaderModel lastLoadingBill, List<TmsShipbillDetailModel> tmsShipbillDetailModelList, String alarmType, String alarmContent) {
        TmsVehicleAlarmE6 tmsVehicleAlarmE6 = new TmsVehicleAlarmE6();
        tmsVehicleAlarmE6.setId(UUID.randomUUID().toString());
        tmsVehicleAlarmE6.setVehicle(lastLoadingBill.getVehiclePlateNumber());
        tmsVehicleAlarmE6.setAlarmType(alarmType);
        tmsVehicleAlarmE6.setBTime(DateUtil.date());
        tmsVehicleAlarmE6.setETime(DateUtil.date());
        tmsVehicleAlarmE6.setAlarmContent(alarmContent);
        tmsVehicleAlarmE6.setBLat(equipInfoDTO.getLat());
        tmsVehicleAlarmE6.setBLon(equipInfoDTO.getLon());
        tmsVehicleAlarmE6.setELat(equipInfoDTO.getLat());
        tmsVehicleAlarmE6.setELon(equipInfoDTO.getLon());
        tmsVehicleAlarmE6.setCreatetime(DateUtil.date());
        tmsVehicleAlarmE6Mapper.save(tmsVehicleAlarmE6);

        TmsVehicleAlarm tmsVehicleAlarm = new TmsVehicleAlarm();
        tmsVehicleAlarm.setId(UUID.randomUUID().toString());
        tmsVehicleAlarm.setVehiclePlateNumber(lastLoadingBill.getVehiclePlateNumber());
        tmsVehicleAlarm.setDeviceCode(lastLoadingBill.getVehicleDeviceCode());
        tmsVehicleAlarm.setAlarmType(tmsVehicleAlarmE6.getAlarmType());
        tmsVehicleAlarm.setStartTime(tmsVehicleAlarmE6.getBTime());
        tmsVehicleAlarm.setEndTime(tmsVehicleAlarmE6.getETime());
        tmsVehicleAlarm.setAlarmContent(tmsVehicleAlarmE6.getAlarmContent());
        tmsVehicleAlarm.setStartLat(tmsVehicleAlarmE6.getBLat());
        tmsVehicleAlarm.setStartLon(tmsVehicleAlarmE6.getBLon());
        tmsVehicleAlarm.setEndLat(tmsVehicleAlarmE6.getELat());
        tmsVehicleAlarm.setEndLon(tmsVehicleAlarmE6.getELon());
        tmsVehicleAlarm.setEnterpriseId(vo.getEnterpriseId());
        tmsVehicleAlarm.setCreatetime(DateUtil.date());
        tmsVehicleAlarm.setUpdatetime(DateUtil.date());
        tmsVehicleAlarm.setSourceType(E6);
        tmsVehicleAlarm.setSourceId(tmsVehicleAlarmE6.getId());
        tmsVehicleAlarm.setLoadingBillId(lastLoadingBill.getLoadingBillId());
        tmsVehicleAlarm.setShipbillId(getShipBillId(tmsShipbillDetailModelList));
        tmsVehicleAlarmMapper.save(tmsVehicleAlarm);
    }

    /**
     * saveG7Data
     * @param vo
     * @param deviceCode
     */
    private void saveG7Data(PullGpsDataVO vo, String deviceCode) {
        CurrentTemperatureVO currentTemperatureVO = new CurrentTemperatureVO();
        currentTemperatureVO.setGpsnos(deviceCode);
        RestMessage<List<CurrentTemperatureDTO>> currentTemperatureInfo = null;
        RestMessage<List<CurrentGpsLocationDTO>> currentGpsLocationInfo = null;
        try {
            currentGpsLocationInfo = interfaceFeign.simpleCurrentsByGpsnos(currentTemperatureVO);
        } catch (Exception e) {
            log.error("G7设备定位报错，deviceCode={}", deviceCode, e);
        } finally {
            log.info("saveG7Data simpleCurrentsByGpsnos request={},response={}", JSON.toJSONString(currentTemperatureVO), JSON.toJSONString(currentGpsLocationInfo));
        }
        try {
            currentTemperatureInfo = interfaceFeign.currentTemperatureExecute(currentTemperatureVO);
        } catch (Exception e) {
            log.error("G7设备温度报错，deviceCode={}", deviceCode, e);
        } finally {
            log.info("saveG7Data currentTemperatureExecute request={},response={}", JSON.toJSONString(currentTemperatureVO), JSON.toJSONString(currentTemperatureInfo));
        }
        if (currentGpsLocationInfo.isSuccess()) {
            if (CollectionUtil.isNotEmpty(currentGpsLocationInfo.getData())) {
                currentGpsLocationInfo.getData().forEach(currentGpsLocationDTO -> {
                    TmsLoadingBillHeaderModel lastLoadingBill = lastLoadingBill(currentGpsLocationDTO.getGpsno());
                    if (ObjectUtil.isNotNull(lastLoadingBill)) {
                        saveTmsGpsDataG7(currentGpsLocationDTO, vo, lastLoadingBill);
                    }
                });
            }
        }
        if (currentTemperatureInfo.isSuccess()) {
            if (CollectionUtil.isNotEmpty(currentTemperatureInfo.getData())) {
                currentTemperatureInfo.getData().forEach(currentTemperatureDTO -> {
                    TmsLoadingBillHeaderModel lastLoadingBill = lastLoadingBill(currentTemperatureDTO.getGpsno());
                    if (ObjectUtil.isNotNull(lastLoadingBill)) {
                        List<TmsShipbillDetailModel> tmsShipbillDetailModelList = getShipBillDetail(lastLoadingBill.getLoadingBillId());
                        saveTmsTemperatureDataG7(currentTemperatureDTO, vo, lastLoadingBill, tmsShipbillDetailModelList);
                        saveTmsVehicleAlarmG7(currentTemperatureDTO, vo, lastLoadingBill, tmsShipbillDetailModelList);
                    }
                });
            }
        }
    }

    /**
     * saveTmsGpsDataG7
     * @param currentGpsLocationDTO
     * @param vo
     * @param lastLoadingBill
     * @return
     */
    private void saveTmsGpsDataG7(CurrentGpsLocationDTO currentGpsLocationDTO, PullGpsDataVO vo, TmsLoadingBillHeaderModel lastLoadingBill) {
        TmsGpsDataG7 tmsGpsDataG7 = new TmsGpsDataG7();
        tmsGpsDataG7.setId(UUID.randomUUID().toString());
        tmsGpsDataG7.setVehiclePlateNumber(lastLoadingBill.getVehiclePlateNumber());
        tmsGpsDataG7.setLongitude(currentGpsLocationDTO.getLng());
        tmsGpsDataG7.setLatitude(currentGpsLocationDTO.getLat());
        tmsGpsDataG7.setSpeed(currentGpsLocationDTO.getSpeed());
        tmsGpsDataG7.setCourse(currentGpsLocationDTO.getCourse());
        tmsGpsDataG7.setTime(DateUtil.parseDateTime(currentGpsLocationDTO.getGps_time()));
        tmsGpsDataG7.setCreatetime(DateUtil.date());
        tmsGpsDataG7Mapper.save(tmsGpsDataG7);

        TmsGpsDataModel gpsDataModel = new TmsGpsDataModel();
        gpsDataModel.setId(UUID.randomUUID().toString());
        gpsDataModel.setDeviceCode(lastLoadingBill.getVehicleDeviceCode());
        gpsDataModel.setDeviceName(lastLoadingBill.getVehicleDeviceName());
        gpsDataModel.setVehiclePlateNumber(lastLoadingBill.getVehiclePlateNumber());
        gpsDataModel.setDriverName(lastLoadingBill.getDriverName());
        gpsDataModel.setDriverPhoneNumber(lastLoadingBill.getDriverPhoneNumber());
        gpsDataModel.setLongitude(currentGpsLocationDTO.getLng());
        gpsDataModel.setLatitude(currentGpsLocationDTO.getLat());
        gpsDataModel.setGpsDate(tmsGpsDataG7.getTime());
        gpsDataModel.setCurrentVelocity(tmsGpsDataG7.getSpeed());
        gpsDataModel.setVehicleDirection(tmsGpsDataG7.getCourse());
        gpsDataModel.setEnterpriseId(vo.getEnterpriseId());
        gpsDataModel.setCreatetime(DateUtil.date());
        gpsDataModel.setUpdatetime(DateUtil.date());
        gpsDataModel.setSourceType(G7);
        gpsDataModel.setSourceId(tmsGpsDataG7.getId());
        tmsGpsDataMapper.save(gpsDataModel);
    }

    /**
     * saveTmsTemperatureDataG7
     * @param currentTemperatureDTO
     * @param vo
     * @param lastLoadingBill
     * @param tmsShipbillDetailModelList
     */
    private void saveTmsTemperatureDataG7(CurrentTemperatureDTO currentTemperatureDTO, PullGpsDataVO vo, TmsLoadingBillHeaderModel lastLoadingBill, List<TmsShipbillDetailModel> tmsShipbillDetailModelList) {
        TmsTemperatureDataG7 tmsTemperatureDataG7 = new TmsTemperatureDataG7();
        tmsTemperatureDataG7.setId(UUID.randomUUID().toString());
        tmsTemperatureDataG7.setTruckId(currentTemperatureDTO.getTruckid());
        tmsTemperatureDataG7.setOrgCode(currentTemperatureDTO.getOrgcode());
        tmsTemperatureDataG7.setCarNum(currentTemperatureDTO.getCarnum());
        tmsTemperatureDataG7.setGpsNo(currentTemperatureDTO.getGpsno());
        if (ObjectUtil.isNotNull(currentTemperatureDTO.getProbeInfo())) {
            if ("2".equals(currentTemperatureDTO.getColdchaintype())) {
                tmsTemperatureDataG7.setTemperature(NumberUtil.toBigDecimal(currentTemperatureDTO.getProbeInfo().getT0Temperature()));
                tmsTemperatureDataG7.setHumidity(NumberUtil.toBigDecimal(currentTemperatureDTO.getProbeInfo().getT0Humidity()));
            } else {
                tmsTemperatureDataG7.setTemperature(NumberUtil.toBigDecimal(currentTemperatureDTO.getProbeInfo().getT1Temperature()));
            }
        }
        tmsTemperatureDataG7.setLongitude(currentTemperatureDTO.getLng());
        tmsTemperatureDataG7.setLatitude(currentTemperatureDTO.getLat());
        tmsTemperatureDataG7.setColdChainType(NumberUtil.toBigDecimal(currentTemperatureDTO.getColdchaintype()));
        tmsTemperatureDataG7.setTime(DateUtil.parseDateTime(currentTemperatureDTO.getTime()));
        tmsTemperatureDataG7.setCreatetime(DateUtil.date());
        tmsTemperatureDataG7Mapper.save(tmsTemperatureDataG7);

        TmsTemperatureData tmsTemperatureData = new TmsTemperatureData();
        tmsTemperatureData.setId(UUID.randomUUID().toString());
        tmsTemperatureData.setVehiclePlateNumber(lastLoadingBill.getVehiclePlateNumber());
        tmsTemperatureData.setDeviceCode(lastLoadingBill.getVehicleDeviceCode());
        tmsTemperatureData.setTemperature(tmsTemperatureDataG7.getTemperature());
        tmsTemperatureData.setLongitude(tmsTemperatureDataG7.getLongitude());
        tmsTemperatureData.setLatitude(tmsTemperatureDataG7.getLatitude());
        tmsTemperatureData.setTime(tmsTemperatureDataG7.getTime());
        tmsTemperatureData.setEnterpriseId(vo.getEnterpriseId());
        tmsTemperatureData.setCreatetime(DateUtil.date());
        tmsTemperatureData.setUpdatetime(DateUtil.date());
        tmsTemperatureData.setSourceType(G7);
        tmsTemperatureData.setSourceId(tmsTemperatureDataG7.getId());
        tmsTemperatureData.setLoadingBillId(lastLoadingBill.getLoadingBillId());
        tmsTemperatureData.setShipbillId(getShipBillId(tmsShipbillDetailModelList));
        tmsTemperatureDataMapper.save(tmsTemperatureData);
    }

    /**
     * saveTmsVehicleAlarmG7
     * @param currentTemperatureDTO
     * @param vo
     * @param lastLoadingBill
     * @param tmsShipbillDetailModelList
     * @return
     */
    private void saveTmsVehicleAlarmG7(CurrentTemperatureDTO currentTemperatureDTO, PullGpsDataVO vo, TmsLoadingBillHeaderModel lastLoadingBill, List<TmsShipbillDetailModel> tmsShipbillDetailModelList) {
        if (ObjectUtil.isNotNull(currentTemperatureDTO.getProbeInfo()) && StrUtil.isNotBlank(currentTemperatureDTO.getProbeInfo().getT0AlarmTypes())) {
            List<String> alarmTypeList = JSON.parseArray(currentTemperatureDTO.getProbeInfo().getT0AlarmTypes(), String.class);
            String alarmContent = alarmTypeList.stream().map(s -> g7AlarmTypeMap.get(s)).filter(StrUtil::isNotBlank).collect(Collectors.joining(","));
            if (StrUtil.isNotBlank(alarmContent)) {
                saveTmsVehicleAlarmG7(currentTemperatureDTO, vo, lastLoadingBill, tmsShipbillDetailModelList, "G7-" + alarmContent, alarmContent);
            }
        }
        if (StrUtil.isNotBlank(currentTemperatureDTO.getProperties()) && "2".equals(currentTemperatureDTO.getColdchaintype())) {
            CTemperaturePropertiesDTO cTemperaturePropertiesDTO = JSON.parseObject(currentTemperatureDTO.getProperties(), CTemperaturePropertiesDTO.class);
            if (NumberUtil.isLess(cTemperaturePropertiesDTO.getBatteryPower(), BigDecimal.valueOf(20))) {
                saveTmsVehicleAlarmG7(currentTemperatureDTO, vo, lastLoadingBill, tmsShipbillDetailModelList, "G7-电量过低", "电量数值低于20，当前电量=" + cTemperaturePropertiesDTO.getBatteryPower());
            }
        }
        if (CollectionUtil.isNotEmpty(tmsShipbillDetailModelList)) {
            BigDecimal temperature = NumberUtil.toBigDecimal(currentTemperatureDTO.getProbeInfo().getT0Temperature());
            if ("1".equals(currentTemperatureDTO.getColdchaintype())) {
                temperature = NumberUtil.toBigDecimal(currentTemperatureDTO.getProbeInfo().getT1Temperature());
            }
            Optional<BigDecimal> lowerLimit = tmsShipbillDetailModelList.stream().map(TmsShipbillDetailModel::getTemperatureCtlLowerLimit).filter(ObjectUtil::isNotNull).max(BigDecimal::compareTo);
            if (lowerLimit.isPresent() && NumberUtil.isLess(temperature, lowerLimit.get())) {
                saveTmsVehicleAlarmG7(currentTemperatureDTO, vo, lastLoadingBill, tmsShipbillDetailModelList, "G7-低温报警", "低温报警，当前温度=" + temperature + "，最低温度=" + lowerLimit.get());
            }
            Optional<BigDecimal> upperLimit = tmsShipbillDetailModelList.stream().map(TmsShipbillDetailModel::getTemperatureCtlUpperLimit).filter(ObjectUtil::isNotNull).min(BigDecimal::compareTo);
            if (upperLimit.isPresent() && NumberUtil.isGreater(temperature, upperLimit.get())) {
                saveTmsVehicleAlarmG7(currentTemperatureDTO, vo, lastLoadingBill, tmsShipbillDetailModelList, "G7-高温报警", "高温报警，当前温度=" + temperature + "，最高温度=" + upperLimit.get());
            }
        }
    }

    /**
     * saveTmsVehicleAlarmG7
     * @param currentTemperatureDTO
     * @param vo
     * @param lastLoadingBill
     * @param alarmType
     * @param alarmContent
     * @return
     */
    private void saveTmsVehicleAlarmG7(CurrentTemperatureDTO currentTemperatureDTO, PullGpsDataVO vo, TmsLoadingBillHeaderModel lastLoadingBill, List<TmsShipbillDetailModel> tmsShipbillDetailModelList, String alarmType, String alarmContent) {
        TmsVehicleAlarmG7 tmsVehicleAlarmG7 = new TmsVehicleAlarmG7();
        tmsVehicleAlarmG7.setId(UUID.randomUUID().toString());
        tmsVehicleAlarmG7.setVehiclePlateNumber(currentTemperatureDTO.getCarnum());
        tmsVehicleAlarmG7.setDeviceCode(currentTemperatureDTO.getGpsno());
        if ("2".equals(currentTemperatureDTO.getColdchaintype())) {
            tmsVehicleAlarmG7.setTemperature(NumberUtil.toBigDecimal(currentTemperatureDTO.getProbeInfo().getT0Temperature()));
        } else {
            tmsVehicleAlarmG7.setTemperature(NumberUtil.toBigDecimal(currentTemperatureDTO.getProbeInfo().getT1Temperature()));
        }
        tmsVehicleAlarmG7.setStartTime(DateUtil.date());
        tmsVehicleAlarmG7.setEndTime(DateUtil.date());
        tmsVehicleAlarmG7.setProbeName(alarmContent);
        tmsVehicleAlarmG7.setStartLat(currentTemperatureDTO.getLat());
        tmsVehicleAlarmG7.setStartLng(currentTemperatureDTO.getLng());
        tmsVehicleAlarmG7.setEndLat(currentTemperatureDTO.getLat());
        tmsVehicleAlarmG7.setEndLng(currentTemperatureDTO.getLng());
        tmsVehicleAlarmG7.setCreatetime(DateUtil.date());
        tmsVehicleAlarmG7Mapper.save(tmsVehicleAlarmG7);

        TmsVehicleAlarm tmsVehicleAlarm = new TmsVehicleAlarm();
        tmsVehicleAlarm.setId(UUID.randomUUID().toString());
        tmsVehicleAlarm.setVehiclePlateNumber(lastLoadingBill.getVehiclePlateNumber());
        tmsVehicleAlarm.setDeviceCode(lastLoadingBill.getVehicleDeviceCode());
        tmsVehicleAlarm.setAlarmType(alarmType);
        tmsVehicleAlarm.setStartTime(tmsVehicleAlarmG7.getStartTime());
        tmsVehicleAlarm.setEndTime(tmsVehicleAlarmG7.getEndTime());
        tmsVehicleAlarm.setAlarmContent(alarmContent);
        tmsVehicleAlarm.setStartLat(tmsVehicleAlarmG7.getStartLat());
        tmsVehicleAlarm.setStartLon(tmsVehicleAlarmG7.getStartLng());
        tmsVehicleAlarm.setEndLat(tmsVehicleAlarmG7.getEndLat());
        tmsVehicleAlarm.setEndLon(tmsVehicleAlarmG7.getEndLng());
        tmsVehicleAlarm.setEnterpriseId(vo.getEnterpriseId());
        tmsVehicleAlarm.setCreatetime(DateUtil.date());
        tmsVehicleAlarm.setUpdatetime(DateUtil.date());
        tmsVehicleAlarm.setSourceType(G7);
        tmsVehicleAlarm.setSourceId(tmsVehicleAlarmG7.getId());
        tmsVehicleAlarm.setLoadingBillId(lastLoadingBill.getLoadingBillId());
        tmsVehicleAlarm.setShipbillId(getShipBillId(tmsShipbillDetailModelList));
        tmsVehicleAlarmMapper.save(tmsVehicleAlarm);
    }

    /**
     * 获取在途有设备的派车单
     * @param deviceCode
     * @return
     */
    private List<TmsLoadingBillHeaderModel> getLoadingBill(String deviceCode) {
        Criteria crt = Criteria.forClass(TmsLoadingBillHeaderModel.class);
        Restriction r3 = Restrictions.eq(TmsLoadingBillHeaderModel::getVehicleDeviceCode, deviceCode);
        Restriction r4 = Restrictions.in(TmsLoadingBillHeaderModel::getStatus, Lists.newArrayList("113","120","143"));
        Restriction r5 = Restrictions.eq(TmsLoadingBillHeaderModel::getCarrierType, "2");
        crt.setRestriction(Restrictions.and(r3, r4, r5));
        crt.orderDescBy(TmsLoadingBillHeaderModel::getCreatetime);
        return tmsLoadingBillHeaderMapper.findByCriteria(crt);
    }

    /**
     * 查询派车单
     * @param deviceCode
     * @return
     */
    private TmsLoadingBillHeaderModel lastLoadingBill(String deviceCode) {
        List<TmsLoadingBillHeaderModel> loadingBillHeaderModelList = getLoadingBill(deviceCode);
        if (CollectionUtil.isNotEmpty(loadingBillHeaderModelList)) {
            return loadingBillHeaderModelList.get(0);
        }
        return null;
    }

    /**
     * getShipBillDetail
     * @param loadingBillId
     * @return
     */
    private List<TmsShipbillDetailModel> getShipBillDetail(String loadingBillId) {
        List<TmsShipbillDetailModel> tmsShipbillDetailModelList = Lists.newArrayList();
        Criteria crt = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, loadingBillId);
        crt.setRestriction(r1);
        List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(crt);
        if (CollectionUtil.isNotEmpty(tmsLoadingBillDetailModelList)) {
            crt = Criteria.forClass(TmsShipbillDetailModel.class);
            r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, tmsLoadingBillDetailModelList.stream().map(
                    TmsLoadingBillDetailModel::getShipbillId).distinct().collect(Collectors.toList()));
            crt.setRestriction(r1);
            tmsShipbillDetailModelList = tmsShipbillDetailMapper.findByCriteria(crt);
        }
        return tmsShipbillDetailModelList;
    }

    /**
     * getShipBillId
     * @param tmsShipbillDetailModelList
     * @return
     */
    private String getShipBillId(List<TmsShipbillDetailModel> tmsShipbillDetailModelList) {
        if (CollectionUtil.isNotEmpty(tmsShipbillDetailModelList)) {
            return tmsShipbillDetailModelList.stream().map(TmsShipbillDetailModel::getShipbillId).filter(StrUtil::isNotBlank).distinct().collect(Collectors.joining(","));
        }
        return StrUtil.EMPTY;
    }
}
