package com.aiotagro.cattletrade.business.service.impl;

import com.aiotagro.cattletrade.business.dto.DeliveryQueryDto;
import com.aiotagro.cattletrade.business.dto.WarningDetailDto;
import com.aiotagro.cattletrade.business.entity.Delivery;
import com.aiotagro.cattletrade.business.entity.DeliveryDevice;
import com.aiotagro.cattletrade.business.entity.IotDeviceData;
import com.aiotagro.cattletrade.business.entity.JbqServerLog;
import com.aiotagro.cattletrade.business.entity.WarningLog;
import com.aiotagro.cattletrade.business.mapper.DeliveryDeviceMapper;
import com.aiotagro.cattletrade.business.mapper.DeliveryMapper;
import com.aiotagro.cattletrade.business.mapper.IotDeviceDataMapper;
import com.aiotagro.cattletrade.business.mapper.JbqServerLogMapper;
import com.aiotagro.cattletrade.business.mapper.WarningLogMapper;
import com.aiotagro.cattletrade.business.service.IWarningLogService;
import com.aiotagro.cattletrade.business.vo.DeliveryLogVo;
import com.aiotagro.cattletrade.constant.WarningStatusAdminEnum;
import com.aiotagro.cattletrade.constant.WarningStatusEnum;
import com.aiotagro.common.core.utils.EnumUtil;
import com.aiotagro.common.core.utils.LngLonUtil;
import com.aiotagro.common.core.utils.SecurityUtil;
import com.aiotagro.common.core.utils.StringUtils;
import com.aiotagro.common.core.utils.uuid.DistinctUtil;
import com.aiotagro.common.core.web.domain.AjaxResult;
import com.aiotagro.common.core.web.domain.PageResultResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 预警记录表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2024-12-26
 */
@Service
@Slf4j
public class WarningLogServiceImpl extends ServiceImpl<WarningLogMapper, WarningLog> implements IWarningLogService {


    @Autowired
    private WarningLogMapper warningLogMapper;
    @Autowired
    private DeliveryMapper deliveryMapper;
    @Autowired
    private DeliveryDeviceMapper deliveryDeviceMapper;
    @Autowired
    private IotDeviceDataMapper iotDeviceDataMapper;
    @Autowired
    private JbqServerLogMapper serverLogMapper;

    /**
     * 预警统计
     *
     * @return
     */
    @Override
    public AjaxResult warningCount() {
        //获取当前登录人信息
        Integer currentUserId = SecurityUtil.getCurrentUserId();
        //返回结果集
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("checkCount", 0);
        resMap.put("rangeCount", 0);
        DeliveryQueryDto deliveryQueryDto = new DeliveryQueryDto();
        deliveryQueryDto.setUserId(currentUserId);
        //查询最新的一条上报数据的预警记录结果
        List<WarningLog> newWarningLog = warningLogMapper.getNewWarningLog(deliveryQueryDto);
        if (CollectionUtils.isNotEmpty(newWarningLog)) {
            //数量盘点预警
            long checkCount = newWarningLog.stream().filter(warningLog -> "2".equals(warningLog.getWarningType())).count();
            long rangeCount = newWarningLog.stream().filter(warningLog -> "3".equals(warningLog.getWarningType())).count();
            resMap.put("checkCount", checkCount);
            resMap.put("rangeCount", rangeCount);
        }
        return AjaxResult.success("查询成功", resMap);
    }

    @Override
    public PageResultResponse<DeliveryLogVo> queryList(DeliveryQueryDto dto) {
        //返回结果集对象
        List<DeliveryLogVo> resList = new ArrayList<>();
        Page<Delivery> result = PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        dto.setUserId(SecurityUtil.getCurrentUserId());//当前登录人
        List<WarningLog> newWarningLog = warningLogMapper.getNewWarningLog(dto);
        if (CollectionUtils.isNotEmpty(newWarningLog)) {
            List<Integer> deliveryIds = newWarningLog.stream().map(WarningLog::getDeliveryId).collect(Collectors.toList());
            //根据运单id查询运单的信息
            List<Delivery> deliveryList = deliveryMapper.selectBatchIds(deliveryIds);
            if (CollectionUtils.isNotEmpty(deliveryList)) {
                Map<Integer, Delivery> deliveryMap = deliveryList.stream().collect(Collectors.toMap(Delivery::getId, delivery -> delivery));
                newWarningLog.forEach(warningLog -> {
                    Delivery delivery = deliveryMap.get(warningLog.getDeliveryId());
                    if (delivery != null) {
                        DeliveryLogVo deliveryLogVo = new DeliveryLogVo();
                        deliveryLogVo.setId(warningLog.getId());
                        deliveryLogVo.setLicensePlate(delivery.getLicensePlate());
                        deliveryLogVo.setDeliveryId(warningLog.getDeliveryId());
                        deliveryLogVo.setDeliveryNumber(delivery.getDeliveryNumber());
                        deliveryLogVo.setStatus(delivery.getStatus());
                        deliveryLogVo.setStatusDesc(2 == delivery.getStatus() ? "已核验" : "待核验");
                        deliveryLogVo.setCarFrontPhoto(delivery.getCarFrontPhoto());
                        deliveryLogVo.setRegisteredJbqCount(delivery.getRegisteredJbqCount());
                        deliveryLogVo.setInventoryJbqCount(warningLog.getInventoryJbqCount());
                        deliveryLogVo.setActualDistance(warningLog.getActualDistance());
                        deliveryLogVo.setExpectedDistance(warningLog.getExpectedDistance());
                        String warningType = warningLog.getWarningType();
                        deliveryLogVo.setWarningType(warningType);
                        if (StringUtils.isNotEmpty(warningType)) {
                            deliveryLogVo.setWarningTypeDesc(EnumUtil.getEnumConstant(WarningStatusAdminEnum.class , Integer.parseInt(warningType)).getDescription());
                        }
                        deliveryLogVo.setWarningTime(warningLog.getWarningTime());
                        resList.add(deliveryLogVo);
                    }
                });
            }
        }
        return new PageResultResponse(result.getTotal(), resList);
    }

    @Override
    public AjaxResult warningDetail(Integer id) {
        log.info("[预警详情查询] 预警ID: {}", id);
        
        WarningDetailDto warningDetailDto = new WarningDetailDto();
        //预警记录信息
        WarningLog warningLog = warningLogMapper.selectById(id);
        if (warningLog == null) {
            return AjaxResult.error("预警记录不存在");
        }
        
        BeanUtils.copyProperties(warningLog, warningDetailDto);
        String warningType = warningLog.getWarningType();
        if (StringUtils.isNotEmpty(warningType)) {
            warningDetailDto.setWarningReason(EnumUtil.getEnumConstant(WarningStatusEnum.class , Integer.parseInt(warningType)).getDescription());
        }
        
        //获取当前记录的运单信息
        Integer originalDeliveryId = warningLog.getDeliveryId();
        Delivery delivery = deliveryMapper.selectById(originalDeliveryId);
        
        // ✅ 容错处理：如果通过 delivery_id 查不到运单，尝试用预警记录的 id 作为 delivery_id 查询
        // 这种情况可能是因为数据不一致，预警记录的 id 可能就是运单的 id
        Integer correctDeliveryId = originalDeliveryId;
        if (delivery == null && originalDeliveryId != null && !originalDeliveryId.equals(warningLog.getId())) {
            log.warn("[预警详情] 通过 delivery_id={} 查询不到运单，尝试使用预警记录 id={} 作为 delivery_id 查询", 
                originalDeliveryId, warningLog.getId());
            delivery = deliveryMapper.selectById(warningLog.getId());
            if (delivery != null) {
                log.info("[预警详情] ✅ 容错成功：使用预警记录 id={} 找到了运单，运单号: {}", 
                    warningLog.getId(), delivery.getDeliveryNumber());
                // 使用预警记录的 id 作为正确的 deliveryId
                correctDeliveryId = warningLog.getId();
            }
        }
        
        if (delivery != null) {
            BeanUtils.copyProperties(delivery, warningDetailDto);
        }
        warningDetailDto.setWarningTime(warningLog.getWarningTime());
        warningDetailDto.setWarningType(warningType);
        warningDetailDto.setInventoryJbqCount(warningLog.getInventoryJbqCount());
        
        // ✅ 设置运单ID（用于前端查询设备列表和日志）
        // 使用修正后的 deliveryId（如果容错成功，这里会是预警记录的 id）
        warningDetailDto.setDeliveryId(correctDeliveryId);
        log.info("[预警详情] 设置运单ID: {} (原始 delivery_id: {})", correctDeliveryId, originalDeliveryId);
        
        //获取当前运单关联的设备信息
        List<DeliveryDevice> deliveryDevices = new ArrayList<>();
        if (delivery != null) {
            deliveryDevices = deliveryDeviceMapper.selectList(
                new LambdaQueryWrapper<DeliveryDevice>().eq(DeliveryDevice::getDeliveryId, delivery.getId())
            );
        } else {
            log.warn("[预警详情] 运单不存在，deliveryId: {} (原始: {})", correctDeliveryId, originalDeliveryId);
        }
        
        String mainDeviceId = null;
        if (CollectionUtils.isNotEmpty(deliveryDevices)) {
            List<String> serverCollect = deliveryDevices.stream()
                .filter(deliveryDevice -> deliveryDevice.getDeviceType() == 1)
                .map(DeliveryDevice::getDeviceId)
                .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(serverCollect)) {
                mainDeviceId = serverCollect.get(0);
                warningDetailDto.setServerDeviceSn(mainDeviceId);
            }
            List<String> jbqDeviceCollect = deliveryDevices.stream()
                .filter(deliveryDevice -> deliveryDevice.getDeviceType() == 2)
                .map(DeliveryDevice::getDeviceId)
                .collect(Collectors.toList());
            warningDetailDto.setJbqDeviceSn(jbqDeviceCollect);
        } else {
            // ✅ 如果 delivery_device 表为空，尝试从 iot_device_data 表查询（兼容旧数据）
            if (delivery != null) {
                log.info("[预警详情] delivery_device 表无数据，尝试从 iot_device_data 表查询设备");
                List<IotDeviceData> iotDevices = iotDeviceDataMapper.selectList(
                    new LambdaQueryWrapper<IotDeviceData>().eq(IotDeviceData::getDeliveryId, delivery.getId())
                );
                
                if (CollectionUtils.isNotEmpty(iotDevices)) {
                    log.info("[预警详情] 从 iot_device_data 查询到 {} 个设备", iotDevices.size());
                    
                    // 查找主机设备（类型1或4）
                    List<String> serverCollect = iotDevices.stream()
                        .filter(device -> device.getDeviceType() != null && 
                                         (device.getDeviceType() == 1 || device.getDeviceType() == 4))
                        .map(IotDeviceData::getDeviceId)
                        .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(serverCollect)) {
                        mainDeviceId = serverCollect.get(0);
                        warningDetailDto.setServerDeviceSn(mainDeviceId);
                        log.info("[预警详情] 找到主机设备: {}", mainDeviceId);
                    }
                    
                    // 查找耳标设备（类型2）
                    List<String> jbqDeviceCollect = iotDevices.stream()
                        .filter(device -> device.getDeviceType() != null && device.getDeviceType() == 2)
                        .map(IotDeviceData::getDeviceId)
                        .collect(Collectors.toList());
                    warningDetailDto.setJbqDeviceSn(jbqDeviceCollect);
                } else {
                    log.warn("[预警详情] iot_device_data 表也无设备数据");
                }
            } else {
                log.warn("[预警详情] 运单不存在，无法查询设备信息");
            }
        }
        
        // ✅ 设置预警位置信息（优先使用预警记录中保存的经纬度）
        // 预警类型：4-设备停留预警，5-高温预警，6-低温预警，7-位置偏离预警
        
        // 1. 优先使用预警记录中已保存的经纬度（新版本预警会保存）
        if (StringUtils.isNotEmpty(warningLog.getLatitude()) && 
            StringUtils.isNotEmpty(warningLog.getLongitude())) {
            warningDetailDto.setLatitude(warningLog.getLatitude());
            warningDetailDto.setLongitude(warningLog.getLongitude());
            log.info("[预警详情] 使用预警记录中的位置 - 经度: {}, 纬度: {}", 
                warningLog.getLongitude(), warningLog.getLatitude());
        } 
        // 2. 如果预警记录中没有经纬度，尝试从设备日志查询（兼容旧版本预警）
        else if (mainDeviceId != null && warningLog.getWarningTime() != null) {
            try {
                log.info("[预警详情] 预警记录中无位置信息，尝试从设备日志查询");
                
                // 查询预警时间前后5分钟内最接近的设备日志
                Date warningTime = warningLog.getWarningTime();
                LocalDateTime warningDateTime = warningTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                LocalDateTime startTime = warningDateTime.minusMinutes(5);
                LocalDateTime endTime = warningDateTime.plusMinutes(5);
                
                List<JbqServerLog> logs = serverLogMapper.selectList(
                    new LambdaQueryWrapper<JbqServerLog>()
                        .eq(JbqServerLog::getDeviceId, mainDeviceId)
                        .ge(JbqServerLog::getCreateTime, startTime)
                        .le(JbqServerLog::getCreateTime, endTime)
                        .orderByAsc(JbqServerLog::getCreateTime)
                );
                
                if (CollectionUtils.isNotEmpty(logs)) {
                    // 找到最接近预警时间的日志
                    JbqServerLog closestLog = logs.get(0);
                    long minDiff = Math.abs(closestLog.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()
                        .toEpochSecond(java.time.ZoneOffset.UTC) - warningDateTime.toEpochSecond(java.time.ZoneOffset.UTC));
                    
                    for (JbqServerLog serverLog : logs) {
                        LocalDateTime logTime = serverLog.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                        long diff = Math.abs(logTime.toEpochSecond(java.time.ZoneOffset.UTC) - 
                                           warningDateTime.toEpochSecond(java.time.ZoneOffset.UTC));
                        if (diff < minDiff) {
                            minDiff = diff;
                            closestLog = serverLog;
                        }
                    }
                    
                    // 设置预警位置信息
                    if (StringUtils.isNotEmpty(closestLog.getLatitude()) && 
                        StringUtils.isNotEmpty(closestLog.getLongitude())) {
                        warningDetailDto.setLatitude(closestLog.getLatitude());
                        warningDetailDto.setLongitude(closestLog.getLongitude());
                        warningDetailDto.setDeviceTemp(closestLog.getDeviceTemp());
                        
                        log.info("[预警详情] 从设备日志找到位置 - 经度: {}, 纬度: {}, 温度: {}", 
                            closestLog.getLongitude(), closestLog.getLatitude(), closestLog.getDeviceTemp());
                    } else {
                        log.warn("[预警详情] 设备日志中无有效位置信息");
                    }
                } else {
                    log.warn("[预警详情] 未找到预警时刻前后的设备日志");
                }
            } catch (Exception e) {
                log.warn("[预警详情] 查询预警时刻设备位置失败: {}", e.getMessage());
            }
        } else {
            log.warn("[预警详情] 无法获取位置信息 - mainDeviceId: {}, warningTime: {}", 
                mainDeviceId, warningLog.getWarningTime());
        }
        
        log.info("[预警详情] 查询完成 - 预警类型: {}, 运单号: {}", warningType, delivery != null ? delivery.getDeliveryNumber() : "");
        
        return AjaxResult.success(warningDetailDto);
    }

    @Override
    public AjaxResult savaWarn(String deviceId) {
        // 查询主机关联的最新运单
        List<DeliveryDevice> list = deliveryDeviceMapper.selectList(new LambdaQueryWrapper<DeliveryDevice>().eq(DeliveryDevice::getDeviceId, deviceId)
                .orderByDesc(DeliveryDevice::getId));
        // 主机未绑定运单 无需操作
        if (CollectionUtils.isEmpty(list)) {
            return AjaxResult.success();
        }
        Delivery delivery = deliveryMapper.selectById(list.get(0).getDeliveryId());
        // 运单已核验 无需操作
        if (delivery.getStatus() == 2) {
            return AjaxResult.success();
        }

        // 查询运单创建后的主机上报日志
        List<JbqServerLog> logs = serverLogMapper.selectList(new LambdaQueryWrapper<JbqServerLog>().eq(JbqServerLog::getDeviceId, deviceId)
                .ge(JbqServerLog::getCreateTime, delivery.getCreateTime()).orderByDesc(JbqServerLog::getCreateTime));
        LocalDateTime endTime = logs.get(0).getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime createTime;
        Double endLat = Double.parseDouble(logs.get(0).getLatitude());
        Double endLon = Double.parseDouble(logs.get(0).getLongitude());
        // 转换成高德经纬度
        double[] gcjDouble = LngLonUtil.gps84_To_Gcj02(endLat, endLon);
        endLat = gcjDouble[0];
        endLon = gcjDouble[1];
        Double startLat;
        Double startLon;
        if (logs.size() == 1) {
            // 第一次上报 计算上报时间到运单创建时间的时间段
            createTime = delivery.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            // 腾讯地图经纬度无需转换
            startLat = Double.parseDouble(delivery.getStartLat());
            startLon = Double.parseDouble(delivery.getStartLon());
        } else {
            // 多次上报 计算上报时间到上一次上报时间的时间段
            createTime = logs.get(1).getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            startLat = Double.parseDouble(logs.get(1).getLatitude());
            startLon = Double.parseDouble(logs.get(1).getLongitude());
            // 转换成高德经纬度
            double[] gcjDouble1 = LngLonUtil.gps84_To_Gcj02(startLat, startLon);
            startLat = gcjDouble1[0];
            startLon = gcjDouble1[1];
        }

        // 计算时间差，单位为小时
        double hoursBetween = Duration.between(createTime, endTime).toMinutes() / 60.0;
        // 确定当前上报时间是在白天还是晚上
        boolean isDayTime = !endTime.toLocalTime().isBefore(LocalTime.of(8, 0)) &&
                !endTime.toLocalTime().isAfter(LocalTime.of(20, 0));
        // 计算基准距离
        double baseDistance = isDayTime ? (80 * hoursBetween * 0.9) : (80 * hoursBetween * 0.8);
        // 四舍五入 保留3位小数
        baseDistance = BigDecimal.valueOf(baseDistance).setScale(3, RoundingMode.HALF_UP).doubleValue();
        // 计算本次上报点 和上次上报点之间的经纬度导航实际距离 km
        try {
            double distance = DistinctUtil.calculateDistance(startLat, startLon, endLat, endLon);
            // 小于基准距离 发起预警
            WarningLog log = new WarningLog();
            log.setWarningTime(new Date());
            if (distance < baseDistance) {
                log.setWarningType("3");
            } else {
                log.setWarningType("1");
            }
            log.setDeliveryId(delivery.getId());
            log.setActualDistance(String.valueOf(distance));
            log.setExpectedDistance(String.valueOf(baseDistance));
            save(log);
        } catch (Exception e) {
            log.error("请求高德api计算距离失败：", e);
            return AjaxResult.error("请求高德api计算距离失败");
        }
        return AjaxResult.success();
    }

    /**
     * 获取设备温度历史数据（用于温度预警详情）
     * 
     * @param deviceId 设备ID
     * @param startTime 开始时间（可选）
     * @param endTime 结束时间（可选）
     * @return 温度历史记录
     */
    @Override
    public AjaxResult getDeviceTemperatureHistory(String deviceId, String startTime, String endTime) {
        try {
            log.info("[温度历史查询] 设备ID: {}, 开始时间: {}, 结束时间: {}", deviceId, startTime, endTime);
            
            if (StringUtils.isEmpty(deviceId)) {
                return AjaxResult.error("设备ID不能为空");
            }
            
            // 构建查询条件
            LambdaQueryWrapper<JbqServerLog> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JbqServerLog::getDeviceId, deviceId);
            
            // 如果提供了时间范围，添加时间过滤
            if (StringUtils.isNotEmpty(startTime)) {
                queryWrapper.ge(JbqServerLog::getCreateTime, startTime);
            }
            if (StringUtils.isNotEmpty(endTime)) {
                queryWrapper.le(JbqServerLog::getCreateTime, endTime);
            }
            
            // 按时间倒序排列，最多返回最近100条记录
            queryWrapper.orderByDesc(JbqServerLog::getCreateTime)
                       .last("LIMIT 100");
            
            List<JbqServerLog> logs = serverLogMapper.selectList(queryWrapper);
            
            // 构建返回结果
            List<Map<String, Object>> temperatureHistory = new ArrayList<>();
            for (JbqServerLog serverLog : logs) {
                Map<String, Object> record = new HashMap<>();
                record.put("time", serverLog.getCreateTime());
                record.put("deviceId", serverLog.getDeviceId());
                
                // 获取温度值（deviceTemp 是字符串）
                String tempStr = serverLog.getDeviceTemp();
                Double temp = null;
                if (StringUtils.isNotEmpty(tempStr)) {
                    try {
                        temp = Double.parseDouble(tempStr);
                        record.put("temperature", temp);
                    } catch (NumberFormatException e) {
                        record.put("temperature", tempStr);
                    }
                }
                
                // 判断温度是否正常（5°C - 35°C 为正常范围）
                if (temp != null) {
                    if (temp >= 35) {
                        record.put("status", "高温预警");
                    } else if (temp <= 5) {
                        record.put("status", "低温预警");
                    } else {
                        record.put("status", "正常");
                    }
                } else {
                    record.put("status", "未知");
                }
                
                temperatureHistory.add(record);
            }
            
            log.info("[温度历史查询] 查询到 {} 条记录", temperatureHistory.size());
            
            Map<String, Object> result = new HashMap<>();
            result.put("deviceId", deviceId);
            result.put("total", temperatureHistory.size());
            result.put("records", temperatureHistory);
            
            return AjaxResult.success("查询成功", result);
            
        } catch (Exception e) {
            log.error("[温度历史查询] 查询失败", e);
            return AjaxResult.error("查询温度历史数据失败：" + e.getMessage());
        }
    }

    /**
     * 获取预警位置的设备轨迹数据（用于停留预警、位置偏离预警详情）
     * 
     * @param deliveryId 运单ID
     * @param warningTime 预警时间
     * @return 设备轨迹记录
     */
    @Override
    public AjaxResult getDeviceTrackAroundWarning(Integer deliveryId, String warningTime) {
        try {
            log.info("[设备轨迹查询] 运单ID: {}, 预警时间: {}", deliveryId, warningTime);
            
            if (deliveryId == null) {
                return AjaxResult.error("运单ID不能为空");
            }
            
            // 查询运单信息
            Delivery delivery = deliveryMapper.selectById(deliveryId);
            if (delivery == null) {
                return AjaxResult.error("运单不存在");
            }
            
            // 查询运单绑定的主机设备
            LambdaQueryWrapper<DeliveryDevice> deviceWrapper = new LambdaQueryWrapper<>();
            deviceWrapper.eq(DeliveryDevice::getDeliveryId, deliveryId)
                        .eq(DeliveryDevice::getDeviceType, 1) // 1-主机
                        .last("LIMIT 1");
            DeliveryDevice deliveryDevice = deliveryDeviceMapper.selectOne(deviceWrapper);
            
            if (deliveryDevice == null) {
                return AjaxResult.error("该运单未绑定主机设备");
            }
            
            String deviceId = deliveryDevice.getDeviceId();
            
            // 构建查询条件：查询预警时间前后2小时的设备轨迹
            LambdaQueryWrapper<JbqServerLog> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JbqServerLog::getDeviceId, deviceId);
            
            // 如果提供了预警时间，查询前后2小时的数据
            if (StringUtils.isNotEmpty(warningTime)) {
                try {
                    // 假设 warningTime 格式为 "yyyy-MM-dd HH:mm:ss"
                    LocalDateTime warningDateTime = LocalDateTime.parse(warningTime.replace(" ", "T"));
                    LocalDateTime startTime = warningDateTime.minusHours(2);
                    LocalDateTime endTime = warningDateTime.plusHours(2);
                    
                    queryWrapper.ge(JbqServerLog::getCreateTime, startTime)
                               .le(JbqServerLog::getCreateTime, endTime);
                } catch (Exception e) {
                    log.warn("[设备轨迹查询] 预警时间格式解析失败: {}", warningTime);
                }
            }
            
            // 按时间排序
            queryWrapper.orderByAsc(JbqServerLog::getCreateTime);
            
            List<JbqServerLog> logs = serverLogMapper.selectList(queryWrapper);
            
            // 构建返回结果
            List<Map<String, Object>> trackPoints = new ArrayList<>();
            for (JbqServerLog serverLog : logs) {
                if (StringUtils.isNotEmpty(serverLog.getLatitude()) && 
                    StringUtils.isNotEmpty(serverLog.getLongitude())) {
                    
                    Map<String, Object> point = new HashMap<>();
                    point.put("time", serverLog.getCreateTime());
                    point.put("latitude", serverLog.getLatitude());
                    point.put("longitude", serverLog.getLongitude());
                    point.put("temperature", serverLog.getDeviceTemp()); // 使用 deviceTemp 而不是 temperature
                    point.put("deviceId", serverLog.getDeviceId());
                    
                    trackPoints.add(point);
                }
            }
            
            log.info("[设备轨迹查询] 查询到 {} 个轨迹点", trackPoints.size());
            
            Map<String, Object> result = new HashMap<>();
            result.put("deviceId", deviceId);
            result.put("deliveryId", deliveryId);
            result.put("deliveryNumber", delivery.getDeliveryNumber());
            result.put("total", trackPoints.size());
            result.put("trackPoints", trackPoints);
            
            return AjaxResult.success("查询成功", result);
            
        } catch (Exception e) {
            log.error("[设备轨迹查询] 查询失败", e);
            return AjaxResult.error("查询设备轨迹数据失败：" + e.getMessage());
        }
    }

}
