package com.qaup.collision.common.service;

import com.qaup.collision.common.model.spatial.VehicleLocation;
import com.qaup.collision.common.model.repository.VehicleLocationRepository;
import com.qaup.collision.common.model.MovingObject;
import com.qaup.collision.common.model.MovingObject.MovingObjectType;
import com.qaup.collision.common.adapter.QuapDataAdapter;
import com.qaup.collision.rule.event.RuleViolationEvent;
import com.qaup.collision.rule.model.entity.SpatialRule;
import com.qaup.collision.rule.model.enums.RuleExecutionResult;
import com.qaup.collision.rule.service.LocationRuleQueryService;
import com.qaup.collision.rule.service.RealTimeViolationDetector;
import com.qaup.collision.rule.service.RuleExecutionEngine;
import com.qaup.common.utils.GeoUtils;
import com.qaup.system.domain.SysVehicleInfo;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 车辆位置服务类 - 基于PostGIS的空间数据管理
 * 提供车辆位置的保存、查询、空间分析等功能
 * 集成统一规则引擎，支持实时规则检测和违规事件处理
 * 
 * 新增功能：智能频率控制
 * - 位置变化检测：只有位置真正变化时才触发检测
 * - 定时违规检测：控制检测频率（1秒周期）
 * - 兜底检测机制：即使没有新位置也定期检测
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class VehicleLocationService {

    private final VehicleLocationRepository vehicleLocationRepository;
    private final GeometryFactory geometryFactory = new GeometryFactory();
    
    // 新增QAUP数据适配器
    private final QuapDataAdapter quapDataAdapter;
    
    // 新增规则引擎相关依赖
    private final LocationRuleQueryService locationRuleQueryService;
    private final RuleExecutionEngine ruleExecutionEngine;
    private final RealTimeViolationDetector realTimeViolationDetector;
    
    // === 智能频率控制相关 ===
    
    /**
     * 位置变化检测缓存：记录每个车辆的上次处理位置
     * key: vehicleId, value: 上次处理的位置信息
     */
    private final Map<String, VehicleLocationSnapshot> lastProcessedPositions = new ConcurrentHashMap<>();
    
    /**
     * 违规检测频率控制：记录每个车辆的上次检测时间
     * key: vehicleId, value: 上次检测时间戳（毫秒）
     */
    private final Map<String, Long> lastViolationDetectionTimes = new ConcurrentHashMap<>();
    
    /**
     * 违规检测最小间隔时间（毫秒）- 1秒
     */
    private static final long VIOLATION_DETECTION_INTERVAL_MS = 1000L;
    
    /**
     * 位置变化阈值（米）- 小于此距离认为位置未变化
     */
    private static final double POSITION_CHANGE_THRESHOLD_METERS = 0.5;
    
    /**
     * 速度变化阈值（km/h）- 小于此速度差认为速度未变化
     */
    private static final double SPEED_CHANGE_THRESHOLD_KMH = 0.2;

    /**
     * 位置快照类 - 用于位置变化检测
     */
    private static class VehicleLocationSnapshot {
        public final double longitude;
        public final double latitude;
        public final Double speed;
        public final long timestamp;
        
        public VehicleLocationSnapshot(double longitude, double latitude, Double speed, long timestamp) {
            this.longitude = longitude;
            this.latitude = latitude;
            this.speed = speed;
            this.timestamp = timestamp;
        }
        
        /**
         * 检查位置是否发生了显著变化
         */
        public boolean hasSignificantChange(VehicleLocationSnapshot other) {
            // 计算距离变化
            double distance = calculateDistance(
                this.longitude, this.latitude, 
                other.longitude, other.latitude
            );
            
            // 检查速度变化
            boolean speedChanged = false;
            if (this.speed != null && other.speed != null) {
                speedChanged = Math.abs(this.speed - other.speed) > SPEED_CHANGE_THRESHOLD_KMH;
            } else if (this.speed != other.speed) { // 一个为null一个不为null
                speedChanged = true;
            }
            
            return distance > POSITION_CHANGE_THRESHOLD_METERS || speedChanged;
        }
        
        /**
         * 计算两点之间的距离（米）
         */
        private static double calculateDistance(double lon1, double lat1, double lon2, double lat2) {
            return GeoUtils.calculateDistance(lat1, lon1, lat2, lon2);
        }
    }

    /**
     * 保存车辆位置信息（集成规则检测）
     */
    @Transactional
    public VehicleLocation saveVehicleLocation(VehicleLocation vehicleLocation) {
        try {
            VehicleLocation saved = vehicleLocationRepository.save(vehicleLocation);
            log.debug("保存车辆位置: vehicleId={}, location=({}, {})", 
                     saved.getVehicleId(), 
                     saved.getLocation().getX(), 
                     saved.getLocation().getY());
            
            // 注意：规则检测已移至DataCollectorService的周期性检测中，以实现频率分离
            // performRuleDetection(saved); // 已禁用直接检测
            
            return saved;
        } catch (Exception e) {
            log.error("保存车辆位置失败: vehicleId={}", vehicleLocation.getVehicleId(), e);
            throw new RuntimeException("保存车辆位置失败", e);
        }
    }

    /**
     * 批量保存车辆位置信息（集成智能违规检测）
     */
    @Transactional
    public List<VehicleLocation> saveVehicleLocations(List<VehicleLocation> vehicleLocations) {
        try {
            List<VehicleLocation> saved = vehicleLocationRepository.saveAll(vehicleLocations);
            log.info("批量保存车辆位置: 数量={}", saved.size());
            
            // 智能批量规则检测（只检测有变化或超时的车辆）
            performIntelligentBatchRuleDetection(saved);
            
            return saved;
        } catch (Exception e) {
            log.error("批量保存车辆位置失败: 数量={}", vehicleLocations.size(), e);
            throw new RuntimeException("批量保存车辆位置失败", e);
        }
    }

    /**
     * 创建车辆位置记录（集成QAUP数据适配器）
     */
    public VehicleLocation createVehicleLocation(String licensePlate, Long vehicleId, 
                                                double longitude, double latitude, 
                                                Double altitude, Double heading, Double speed) {
        Point location = geometryFactory.createPoint(new Coordinate(longitude, latitude));
        location.setSRID(4326); // 设置WGS84坐标系

        VehicleLocation vehicleLocation = new VehicleLocation();
        vehicleLocation.setVehicleId(vehicleId); // 使用传入的数字车辆ID
        vehicleLocation.setLocation(location);
        vehicleLocation.setAltitude(altitude);
        vehicleLocation.setHeading(heading);
        vehicleLocation.setSpeed(speed);
        log.debug("在VehicleLocationService.createVehicleLocation方法中，设置速度后，vehicleLocation.speed为: {}", vehicleLocation.getSpeed());
        vehicleLocation.setTimestamp(LocalDateTime.now());
        vehicleLocation.setDataQuality("GOOD"); // 默认数据质量
        
        // 设置运行时属性
        vehicleLocation.setLicensePlate(licensePlate);
        vehicleLocation.setVehicleType(MovingObjectType.UNMANNED_VEHICLE); // 只有无人车数据会持久化

        log.debug("创建车辆位置记录: vehicleId={}, licensePlate={}, location=({}, {})", 
                 vehicleId, licensePlate, longitude, latitude);
        
        return vehicleLocation;
    }

    /**
     * 创建车辆位置记录（通过车牌号自动查找车辆ID）
     */
    public VehicleLocation createVehicleLocationByLicensePlate(String licensePlate, 
                                                              double longitude, double latitude, 
                                                              Double altitude, Double heading, Double speed) {
        // 使用QuapDataAdapter获取车辆基础信息
        try {
            Optional<SysVehicleInfo> vehicleInfoOpt = quapDataAdapter.findVehicleByLicensePlate(licensePlate);
            if (vehicleInfoOpt.isPresent()) {
                SysVehicleInfo vehicleInfo = vehicleInfoOpt.get();
                return createVehicleLocation(licensePlate, vehicleInfo.getVehicleId(), 
                                           longitude, latitude, altitude, heading, speed);
            } else {
                // 车辆信息不存在，记录警告但不阻止位置记录创建
                log.warn("未找到车辆基础信息: licensePlate={}", licensePlate);
                // 返回null或者抛出异常，根据业务需求决定
                return null;
            }
        } catch (Exception e) {
            log.error("通过车牌号查找车辆信息失败: licensePlate={}", licensePlate, e);
            return null;
        }
    }

    /**
     * 根据车辆ID获取最新位置
     */
    public Optional<VehicleLocation> getLatestVehicleLocation(Long vehicleId) {
        try {
            return vehicleLocationRepository.findLatestByVehicleId(vehicleId);
        } catch (Exception e) {
            log.error("获取车辆最新位置失败: vehicleId={}", vehicleId, e);
            return Optional.empty();
        }
    }

    /**
     * 获取车辆的基础信息（使用QAUP数据适配器）
     */
    public Optional<SysVehicleInfo> getVehicleInfo(Long vehicleId) {
        try {
            return quapDataAdapter.findVehicleById(vehicleId);
        } catch (Exception e) {
            log.error("获取车辆基础信息失败: vehicleId={}", vehicleId, e);
            return Optional.empty();
        }
    }

    /**
     * 获取车辆的基础信息（通过车牌号）
     */
    public Optional<SysVehicleInfo> getVehicleInfoByLicensePlate(String licensePlate) {
        try {
            return quapDataAdapter.findVehicleByLicensePlate(licensePlate);
        } catch (Exception e) {
            log.error("获取车辆基础信息失败: licensePlate={}", licensePlate, e);
            return Optional.empty();
        }
    }

    /**
     * 获取车辆位置和基础信息的组合数据
     */
    public Map<String, Object> getVehicleLocationWithInfo(Long vehicleId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取位置信息
            Optional<VehicleLocation> locationOpt = getLatestVehicleLocation(vehicleId);
            if (locationOpt.isPresent()) {
                result.put("location", locationOpt.get());
                
                // 获取基础信息
                Optional<SysVehicleInfo> infoOpt = getVehicleInfo(vehicleId);
                infoOpt.ifPresent(info -> result.put("vehicleInfo", info));
                
                result.put("success", true);
            } else {
                result.put("success", false);
                result.put("message", "未找到车辆位置信息");
            }
        } catch (Exception e) {
            log.error("获取车辆完整信息失败: vehicleId={}", vehicleId, e);
            result.put("success", false);
            result.put("message", "查询失败: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 根据车牌号获取最新位置
     */
    public Optional<VehicleLocation> getLatestVehicleLocationByLicensePlate(String licensePlate) {
        try {
            return vehicleLocationRepository.findLatestByLicensePlate(licensePlate);
        } catch (Exception e) {
            log.error("获取车辆最新位置失败: licensePlate={}", licensePlate, e);
            return Optional.empty();
        }
    }

    /**
     * 根据车辆类型获取活跃车辆
     */
    public List<VehicleLocation> getActiveVehiclesByType(MovingObjectType vehicleType, int minutesBack) {
        LocalDateTime since = LocalDateTime.now().minusMinutes(minutesBack);
        try {
            // 将MovingObject.ObjectType转换为数据库中的类型名称模式
            String typeName = convertMovingObjectTypeToTypeName(vehicleType);
            return vehicleLocationRepository.findActiveByVehicleType(typeName, since);
        } catch (Exception e) {
            log.error("获取活跃车辆失败: vehicleType={}, minutesBack={}", vehicleType, minutesBack, e);
            return List.of();
        }
    }
    
    /**
     * 将MovingObject.ObjectType转换为数据库中的类型名称模式
     */
    private String convertMovingObjectTypeToTypeName(MovingObjectType vehicleType) {
        switch (vehicleType) {
            case UNMANNED_VEHICLE:
                return "%无人车%";
            case SPECIAL_VEHICLE:
                return "%特勤车%";
            case NORMAL_VEHICLE:
                return "%普通车"; // 匹配包含"车"但不包含"无人车"的类型
            case AIRCRAFT:
                return "%飞机%";
            default:
                return "%"; // 匹配所有类型
        }
    }

    /**
     * 空间查询：获取指定半径范围内的车辆
     */
    public List<VehicleLocation> getVehiclesWithinRadius(double longitude, double latitude, 
                                                        double radiusMeters, int minutesBack) {
        Point centerPoint = geometryFactory.createPoint(new Coordinate(longitude, latitude));
        centerPoint.setSRID(4326);
        LocalDateTime since = LocalDateTime.now().minusMinutes(minutesBack);

        try {
            return vehicleLocationRepository.findVehiclesWithinRadius(centerPoint, radiusMeters, since);
        } catch (Exception e) {
            log.error("半径查询失败: center=({}, {}), radius={}m", longitude, latitude, radiusMeters, e);
            return List.of();
        }
    }

    /**
     * 空间查询：获取指定区域内的车辆
     */
    public List<VehicleLocation> getVehiclesInArea(String areaWkt, int minutesBack) {
        LocalDateTime since = LocalDateTime.now().minusMinutes(minutesBack);
        try {
            return vehicleLocationRepository.findVehiclesInArea(areaWkt, since);
        } catch (Exception e) {
            log.error("区域查询失败: areaWkt={}", areaWkt, e);
            return List.of();
        }
    }

    /**
     * 获取车辆轨迹数据
     */
    public List<VehicleLocation> getVehicleTrajectory(Long vehicleId, LocalDateTime startTime, LocalDateTime endTime) {
        try {
            return vehicleLocationRepository.findVehicleTrajectory(vehicleId, startTime, endTime);
        } catch (Exception e) {
            log.error("获取车辆轨迹失败: vehicleId={}, 时间范围=[{}, {}]", vehicleId, startTime, endTime, e);
            return List.of();
        }
    }

    /**
     * 根据车牌号获取车辆轨迹数据
     */
    public List<VehicleLocation> getVehicleTrajectoryByLicensePlate(String licensePlate, LocalDateTime startTime, LocalDateTime endTime) {
        try {
            return vehicleLocationRepository.findVehicleTrajectoryByLicensePlate(licensePlate, startTime, endTime);
        } catch (Exception e) {
            log.error("获取车辆轨迹失败: licensePlate={}, 时间范围=[{}, {}]", licensePlate, startTime, endTime, e);
            return List.of();
        }
    }

    /**
     * 获取指定高度范围内的车辆
     */
    public List<VehicleLocation> getVehiclesByAltitudeRange(double minAltitude, double maxAltitude, int minutesBack) {
        LocalDateTime since = LocalDateTime.now().minusMinutes(minutesBack);
        try {
            return vehicleLocationRepository.findVehiclesByAltitudeRange(minAltitude, maxAltitude, since);
        } catch (Exception e) {
            log.error("高度范围查询失败: 高度范围=[{}, {}]", minAltitude, maxAltitude, e);
            return List.of();
        }
    }

    /**
     * 获取高速移动的车辆
     */
    public List<VehicleLocation> getHighSpeedVehicles(double speedThreshold, int minutesBack) {
        LocalDateTime since = LocalDateTime.now().minusMinutes(minutesBack);
        try {
            return vehicleLocationRepository.findHighSpeedVehicles(speedThreshold, since);
        } catch (Exception e) {
            log.error("高速车辆查询失败: speedThreshold={}", speedThreshold, e);
            return List.of();
        }
    }

    /**
     * 获取最近的N个车辆
     */
    public List<VehicleLocation> getNearestVehicles(double longitude, double latitude, int limit, int minutesBack) {
        Point referencePoint = geometryFactory.createPoint(new Coordinate(longitude, latitude));
        referencePoint.setSRID(4326);
        LocalDateTime since = LocalDateTime.now().minusMinutes(minutesBack);

        try {
            return vehicleLocationRepository.findNearestVehicles(referencePoint, since, limit);
        } catch (Exception e) {
            log.error("最近车辆查询失败: reference=({}, {}), limit={}", longitude, latitude, limit, e);
            return List.of();
        }
    }

    /**
     * 统计指定时间段内的唯一车辆数量
     */
    public long countUniqueVehiclesInTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            return vehicleLocationRepository.countUniqueVehiclesInTimeRange(startTime, endTime);
        } catch (Exception e) {
            log.error("车辆统计失败: 时间范围=[{}, {}]", startTime, endTime, e);
            return 0;
        }
    }

    /**
     * 清理历史数据
     */
    @Transactional
    public int cleanupHistoricalData(LocalDateTime beforeTime) {
        try {
            int deletedCount = vehicleLocationRepository.deleteHistoricalData(beforeTime);
            log.info("清理历史数据完成: 删除记录数={}, 清理时间点={}", deletedCount, beforeTime);
            return deletedCount;
        } catch (Exception e) {
            log.error("清理历史数据失败: beforeTime={}", beforeTime, e);
            throw new RuntimeException("清理历史数据失败", e);
        }
    }

    /**
     * 更新车辆位置 (如果存在则更新，否则创建新记录)（集成规则检测）
     */
    @Transactional
    public VehicleLocation updateOrCreateVehicleLocation(String licensePlate,
                                                        double longitude, double latitude,
                                                        Double altitude, Double heading, Double speed) {
        VehicleLocation vehicleLocation = createVehicleLocationByLicensePlate(licensePlate, 
                                                               longitude, latitude, 
                                                               altitude, heading, speed);
        if (vehicleLocation == null) {
            log.warn("无法创建车辆位置记录，车牌号不存在: {}", licensePlate);
            return null;
        }
        vehicleLocation.setTimestamp(LocalDateTime.now());

        VehicleLocation saved = saveVehicleLocation(vehicleLocation);
        
        // 注意：saveVehicleLocation 已经会触发规则检测，这里不需要重复调用
        
        return saved;
    }

    /**
     * 验证车辆位置数据的有效性
     */
    public boolean isValidVehicleLocation(double longitude, double latitude, Double altitude, Double heading, Double speed) {
        // 经度范围检查
        if (longitude < -180 || longitude > 180) {
            log.warn("无效的经度值: {}", longitude);
            return false;
        }

        // 纬度范围检查
        if (latitude < -90 || latitude > 90) {
            log.warn("无效的纬度值: {}", latitude);
            return false;
        }

        // 高度检查
        if (altitude != null && (altitude < -1000 || altitude > 50000)) {
            log.warn("无效的高度值: {}", altitude);
            return false;
        }

        // 航向检查
        if (heading != null && (heading < 0 || heading >= 360)) {
            log.warn("无效的航向值: {}", heading);
            return false;
        }

        // 速度检查
        if (speed != null && (speed < 0 || speed > 1000)) {
            log.warn("无效的速度值: {}", speed);
            return false;
        }

        return true;
    }

    /**
     * 根据车辆ID删除所有历史位置记录
     */
    @Transactional
    public void deleteVehicleLocations(Long vehicleId) {
        try {
            vehicleLocationRepository.deleteAll(
                vehicleLocationRepository.findVehicleTrajectory(vehicleId, 
                    LocalDateTime.now().minusYears(10), LocalDateTime.now())
            );
            log.info("删除车辆位置记录: vehicleId={}", vehicleId);
        } catch (Exception e) {
            log.error("删除车辆位置记录失败: vehicleId={}", vehicleId, e);
            throw new RuntimeException("删除车辆位置记录失败", e);
        }
    }

    /**
     * 同步规则检测（单个车辆位置）
     */
    private void performRuleDetection(VehicleLocation vehicleLocation) {
        try {
            log.debug("开始实时违规检测: vehicleId={}, location=({}, {})", 
                     vehicleLocation.getVehicleId(),
                     vehicleLocation.getLocation().getX(), 
                     vehicleLocation.getLocation().getY());
            
            // 使用实时违规检测器进行检测
            List<RuleViolationEvent> violations = realTimeViolationDetector.detectViolations(vehicleLocation);
            
            if (!violations.isEmpty()) {
                log.info("检测到违规事件: vehicleId={}, 违规数量={}", 
                        vehicleLocation.getVehicleId(), violations.size());
                
                // 详细记录每个违规事件
                for (RuleViolationEvent violation : violations) {
                    log.warn("违规详情: vehicleId={}, 规则={}, 违规类型={}, 描述={}", 
                           violation.getVehicleId(), violation.getRuleName(), 
                           violation.getViolationType(), violation.getDescription());
                }
            } else {
                log.debug("未检测到违规: vehicleId={}", vehicleLocation.getVehicleId());
            }
            
        } catch (Exception e) {
            log.error("实时违规检测处理失败: vehicleId={}", vehicleLocation.getVehicleId(), e);
            // 规则检测失败不应影响位置保存的主要业务流程
        }
    }

    /**
     * 智能批量规则检测 - 只对需要检测的车辆进行处理
     */
    private void performIntelligentBatchRuleDetection(List<VehicleLocation> vehicleLocations) {
        try {
            List<VehicleLocation> needDetectionVehicles = new ArrayList<>();
            long currentTime = System.currentTimeMillis();
            
            for (VehicleLocation vehicleLocation : vehicleLocations) {
                if (shouldPerformViolationDetection(vehicleLocation, currentTime)) {
                    needDetectionVehicles.add(vehicleLocation);
                    
                    // 更新检测时间记录
                    String vehicleKey = getVehicleKey(vehicleLocation);
                    lastViolationDetectionTimes.put(vehicleKey, currentTime);
                    
                    // 更新位置快照
                    updateLastProcessedPosition(vehicleLocation);
                }
            }
            
            if (needDetectionVehicles.isEmpty()) {
                log.debug("所有车辆位置无显著变化或未到检测时间，跳过违规检测");
                return;
            }
            
            log.info("开始智能违规检测: 总车辆数={}, 需检测车辆数={}", 
                    vehicleLocations.size(), needDetectionVehicles.size());
            
            // 对筛选出的车辆进行违规检测
            List<RuleViolationEvent> allViolations = realTimeViolationDetector.detectBatchViolations(needDetectionVehicles);
            
            if (!allViolations.isEmpty()) {
                log.warn("智能检测发现违规: 总违规数量={}", allViolations.size());
                
                // 按车辆分组显示违规统计
                Map<Long, Long> violationsByVehicle = allViolations.stream()
                    .collect(java.util.stream.Collectors.groupingBy(
                        RuleViolationEvent::getVehicleId,
                        java.util.stream.Collectors.counting()
                    ));
                
                violationsByVehicle.forEach((vehicleId, count) -> 
                    log.warn("车辆违规统计: vehicleId={}, 违规数量={}", vehicleId, count)
                );
            } else {
                log.info("智能检测未发现违规");
            }
            
            log.info("智能违规检测完成: 总车辆数={}, 检测车辆数={}, 发现违规数量={}", 
                    vehicleLocations.size(), needDetectionVehicles.size(), allViolations.size());
            
        } catch (Exception e) {
            log.error("智能批量违规检测处理失败: 车辆数量={}", vehicleLocations.size(), e);
        }
    }
    
    /**
     * 判断是否需要执行违规检测
     */
    private boolean shouldPerformViolationDetection(VehicleLocation vehicleLocation, long currentTime) {
        String vehicleKey = getVehicleKey(vehicleLocation);
        
        // 1. 检查时间间隔 - 如果距离上次检测时间不足1秒，跳过
        Long lastDetectionTime = lastViolationDetectionTimes.get(vehicleKey);
        if (lastDetectionTime != null && (currentTime - lastDetectionTime) < VIOLATION_DETECTION_INTERVAL_MS) {
            log.trace("车辆 {} 距离上次检测时间不足{}ms，跳过检测", vehicleKey, VIOLATION_DETECTION_INTERVAL_MS);
            return false;
        }
        
        // 2. 检查位置变化 - 如果位置和速度都没有显著变化，但超过检测间隔，仍需要检测（兜底机制）
        VehicleLocationSnapshot lastSnapshot = lastProcessedPositions.get(vehicleKey);
        if (lastSnapshot != null) {
            VehicleLocationSnapshot currentSnapshot = createSnapshot(vehicleLocation);
            
            // 如果位置有显著变化，立即检测
            if (lastSnapshot.hasSignificantChange(currentSnapshot)) {
                log.debug("车辆 {} 位置发生显著变化，触发违规检测", vehicleKey);
                return true;
            }
            
            // 如果位置没有变化，但超过了检测间隔（兜底机制）
            if (lastDetectionTime != null && (currentTime - lastDetectionTime) >= VIOLATION_DETECTION_INTERVAL_MS) {
                log.debug("车辆 {} 位置无变化但到达检测周期，执行兜底检测", vehicleKey);
                return true;
            }
            
            log.trace("车辆 {} 位置无显著变化且未到检测周期，跳过检测", vehicleKey);
            return false;
        }
        
        // 3. 首次检测 - 没有历史记录，需要检测
        log.debug("车辆 {} 首次记录，触发违规检测", vehicleKey);
        return true;
    }
    
    /**
     * 获取车辆唯一标识
     */
    private String getVehicleKey(VehicleLocation vehicleLocation) {
        // 使用车辆ID作为唯一标识
        return String.valueOf(vehicleLocation.getVehicleId());
    }
    
    /**
     * 创建位置快照
     */
    private VehicleLocationSnapshot createSnapshot(VehicleLocation vehicleLocation) {
        return new VehicleLocationSnapshot(
            vehicleLocation.getLocation().getX(),
            vehicleLocation.getLocation().getY(),
            vehicleLocation.getSpeed(),
            System.currentTimeMillis()
        );
    }
    
    /**
     * 更新上次处理的位置记录
     */
    private void updateLastProcessedPosition(VehicleLocation vehicleLocation) {
        String vehicleKey = getVehicleKey(vehicleLocation);
        VehicleLocationSnapshot snapshot = createSnapshot(vehicleLocation);
        lastProcessedPositions.put(vehicleKey, snapshot);
    }
    
    /**
     * 清理过期的位置记录（定时任务调用）
     */
    @Scheduled(fixedRate = 300000) // 每5分钟清理一次
    public void cleanupExpiredPositionRecords() {
        long currentTime = System.currentTimeMillis();
        long expireTime = 10 * 60 * 1000L; // 10分钟过期
        
        int removedPositions = lastProcessedPositions.size();
        int removedDetectionTimes = lastViolationDetectionTimes.size();
        
        lastProcessedPositions.entrySet().removeIf(entry -> 
            (currentTime - entry.getValue().timestamp) > expireTime
        );
        
        lastViolationDetectionTimes.entrySet().removeIf(entry -> 
            (currentTime - entry.getValue()) > expireTime
        );
        
        removedPositions -= lastProcessedPositions.size();
        removedDetectionTimes -= lastViolationDetectionTimes.size();
        
        if (removedPositions > 0 || removedDetectionTimes > 0) {
            log.info("清理过期位置记录完成: 清理位置快照={}个, 清理检测时间={}个", 
                    removedPositions, removedDetectionTimes);
        }
    }
    
    /**
     * 获取频率控制统计信息
     */
    public Map<String, Object> getFrequencyControlStats() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("trackedVehicleCount", lastProcessedPositions.size());
        stats.put("violationDetectionInterval", VIOLATION_DETECTION_INTERVAL_MS + "ms");
        stats.put("positionChangeThreshold", POSITION_CHANGE_THRESHOLD_METERS + "m");
        stats.put("speedChangeThreshold", SPEED_CHANGE_THRESHOLD_KMH + "km/h");
        
        // 计算各车辆的上次检测时间
        Map<String, Long> lastDetectionTimes = new HashMap<>();
        long currentTime = System.currentTimeMillis();
        lastViolationDetectionTimes.forEach((vehicleKey, lastTime) -> {
            lastDetectionTimes.put(vehicleKey, currentTime - lastTime);
        });
        stats.put("lastDetectionTimes", lastDetectionTimes);
        
        return stats;
    }

    /**
     * 单个车辆的同步规则检测（内部方法）
     */
    private void triggerRuleDetectionForSingle(VehicleLocation vehicleLocation) {
        try {
            // 获取车辆信息以确定车辆类型
            Optional<SysVehicleInfo> vehicleInfoOpt = quapDataAdapter.findVehicleById(vehicleLocation.getVehicleId());
            if (vehicleInfoOpt.isEmpty()) {
                log.warn("无法获取车辆信息，跳过规则检测: vehicleId={}", vehicleLocation.getVehicleId());
                return;
            }
            
            SysVehicleInfo vehicleInfo = vehicleInfoOpt.get();
            MovingObjectType vehicleType = MovingObjectType.fromTypeCode(vehicleInfo.getTypeCode());
            
            // 查询该位置适用的规则
            List<SpatialRule> applicableRules = locationRuleQueryService.findApplicableRules(
                vehicleLocation.getLocation(), 
                vehicleType, 
                LocalDateTime.now()
            );
            
            if (applicableRules.isEmpty()) {
                return;
            }
            
            // 执行规则检测
            for (SpatialRule rule : applicableRules) {
                try {
                    // 构建车辆状态参数
                    Map<String, Object> vehicleState = buildVehicleStateMap(vehicleLocation, vehicleInfo, vehicleType);
                    
                    // 使用licensePlate作为vehicleIdentifier
                    RuleExecutionResult result = ruleExecutionEngine.executeRule(
                        rule, 
                        vehicleInfo.getLicensePlate(),
                        vehicleType,
                        vehicleLocation.getLocation(), 
                        vehicleState,
                        vehicleLocation.getTimestamp()
                    );
                    
                    if (result.requiresAction()) {
                        log.info("检测发现问题: vehicleId={}, licensePlate={}, ruleId={}, result={}", 
                               vehicleLocation.getVehicleId(), vehicleInfo.getLicensePlate(), 
                               rule.getRuleId(), result);
                    }
                } catch (Exception e) {
                    log.error("规则执行失败: vehicleId={}, licensePlate={}, ruleId={}", 
                             vehicleLocation.getVehicleId(), vehicleInfo.getLicensePlate(), rule.getRuleId(), e);
                }
            }
            
        } catch (Exception e) {
            log.error("单个车辆规则检测失败: vehicleId={}", vehicleLocation.getVehicleId(), e);
        }
    }

    /**
     * 手动触发指定车辆的规则检测（用于调试和手动检查）
     */
    public void manualRuleDetection(Long vehicleId) {
        try {
            Optional<VehicleLocation> latestLocation = getLatestVehicleLocation(vehicleId);
            
            if (latestLocation.isEmpty()) {
                log.warn("未找到车辆位置信息，无法进行规则检测: vehicleId={}", vehicleId);
                return;
            }
            
            log.info("手动触发规则检测: vehicleId={}", vehicleId);
            triggerRuleDetectionForSingle(latestLocation.get());
            
        } catch (Exception e) {
            log.error("手动规则检测失败: vehicleId={}", vehicleId, e);
        }
    }

    /**
     * 查询指定位置的适用规则（提供给外部调用）
     */
    public List<SpatialRule> getApplicableRulesAtLocation(double longitude, double latitude, 
                                                         MovingObjectType vehicleType) {
        try {
            Point location = geometryFactory.createPoint(new Coordinate(longitude, latitude));
            location.setSRID(4326);
            
            return locationRuleQueryService.findApplicableRules(location, vehicleType, LocalDateTime.now());
        } catch (Exception e) {
            log.error("查询位置适用规则失败: location=({}, {}), vehicleType={}", 
                     longitude, latitude, vehicleType, e);
            return List.of();
        }
    }

    /**
     * 构建车辆状态参数Map（用于规则执行）
     */
    private Map<String, Object> buildVehicleStateMap(VehicleLocation vehicleLocation, SysVehicleInfo vehicleInfo, MovingObjectType vehicleType) {
        Map<String, Object> stateMap = new HashMap<>();
        stateMap.put("vehicleId", vehicleLocation.getVehicleId());
        stateMap.put("licensePlate", vehicleLocation.getLicensePlate());
        stateMap.put("longitude", vehicleLocation.getLocation().getX());
        stateMap.put("latitude", vehicleLocation.getLocation().getY());
        stateMap.put("altitude", vehicleLocation.getAltitude());
        stateMap.put("speed", vehicleLocation.getSpeed());
        stateMap.put("heading", vehicleLocation.getHeading());
        stateMap.put("timestamp", vehicleLocation.getTimestamp());
        stateMap.put("vehicleType", vehicleType.name());

        // 移除对 vehicleModel 和 usagePurpose 的引用，因为 SysVehicleInfo 中可能不包含这些字段
        // if (vehicleInfo != null) {
        //     stateMap.put("vehicleModel", vehicleInfo.getVehicleModel());
        //     stateMap.put("usagePurpose", vehicleInfo.getUsagePurpose());
        // }
        return stateMap;
    }

    /**
     * 统计所有无人车数量
     */
    public long countAllUnmannedVehicles() {
        try {
            // 假设VehicleLocationRepository主要存储无人车数据
            return vehicleLocationRepository.count();
        } catch (Exception e) {
            log.error("获取所有无人车数量失败", e);
            return 0;
        }
    }
} 