package com.qaup.collision.dataprocessing.service;

import com.qaup.collision.common.model.MovingObject;
import com.qaup.collision.common.model.MovingObject.MovingObjectType;
import com.qaup.collision.common.model.UnmannedVehicle;
import com.qaup.collision.common.model.spatial.VehicleLocation;
import com.qaup.collision.common.adapter.QuapDataAdapter;
import com.qaup.collision.datacollector.service.VehicleDataPersistenceService;
import com.qaup.collision.websocket.event.PositionUpdateEvent;
import com.qaup.collision.websocket.message.PositionUpdatePayload;
import com.qaup.collision.pathconflict.service.PathConflictDetectionService;
import com.qaup.system.domain.SysVehicleInfo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.PrecisionModel;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 数据处理服务
 * 
 * 职责：
 * 1. 从DataCollectorService的缓存中获取位置数据
 * 2. 计算速度和方向
 * 3. 发送WebSocket消息
 * 4. 执行违规检测和路径冲突检测
 * 5. 保存数据到数据库
 * 
 * 运行频率：1000ms（与detection.interval同步）
 */
@Slf4j
@Service
public class DataProcessingService {
    
    @Value("${data.collector.disabled:false}")
    private boolean collectorDisabled;
    
    @Autowired
    private SpeedCalculationService speedCalculationService;
    
    @Autowired
    private PathConflictDetectionService pathConflictDetectionService;
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    @Autowired
    private VehicleDataPersistenceService vehicleDataPersistenceService;
    
    @Autowired
    private QuapDataAdapter quapDataAdapter;
    
    @Autowired
    private com.qaup.collision.rule.service.RuleExecutionEngine ruleExecutionEngine;
    
    private final GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
    
    // 从DataCollectorService获取缓存的引用
    private Map<String, MovingObject> activeMovingObjectsCache;
    
    /**
     * 设置活跃对象缓存的引用（由DataCollectorService调用）
     */
    public void setActiveMovingObjectsCache(Map<String, MovingObject> cache) {
        this.activeMovingObjectsCache = cache;
    }
    
    /**
     * 周期性数据处理任务
     * 
     * 处理步骤：
     * 1. 从缓存获取最新位置数据
     * 2. 计算速度和方向
     * 3. 发送WebSocket位置更新消息
     * 4. 执行路径冲突检测
     * 5. 执行违规检测
     * 6. 保存无人车数据到数据库
     */
    @Scheduled(fixedRateString = "${data.collector.detection.interval:1000}")
    @Transactional
    public void performPeriodicDataProcessing() {
        if (collectorDisabled) {
            return;
        }
        
        if (activeMovingObjectsCache == null || activeMovingObjectsCache.isEmpty()) {
            log.debug("活跃对象缓存为空，跳过数据处理");
            return;
        }
        
        log.info("开始周期性数据处理，活跃对象数量: {}", activeMovingObjectsCache.size());
        
        // 获取所有活跃对象的快照
        List<MovingObject> currentActiveObjects = new ArrayList<>(activeMovingObjectsCache.values());
        
        // 第一步：计算速度和方向
        calculateSpeedAndDirectionForAllObjects(currentActiveObjects);
        
        // 第二步：发送WebSocket位置更新消息
        sendPositionUpdatesForActiveObjects(currentActiveObjects);
        
        // 第三步：执行路径冲突检测
        pathConflictDetectionService.detectPathConflicts(currentActiveObjects);
        
        // 第四步：执行违规检测
        performViolationDetection(currentActiveObjects);
        
        // 第五步：保存无人车数据到数据库
        saveUnmannedVehicleDataPeriodically(currentActiveObjects);
        
        log.info("周期性数据处理完成");
    }
    
    /**
     * 为所有缓存对象计算速度和方向
     */
    private void calculateSpeedAndDirectionForAllObjects(List<MovingObject> activeObjects) {
        if (activeObjects.isEmpty()) {
            return;
        }
        
        long currentTime = System.currentTimeMillis();
        log.debug("开始为 {} 个对象计算速度和方向", activeObjects.size());
        
        for (MovingObject movingObject : activeObjects) {
            try {
                // 计算实时速度
                Double calculatedSpeed = speedCalculationService.calculateRealtimeSpeed(
                    movingObject.getObjectId(),
                    movingObject.getCurrentPosition().getY(), // latitude
                    movingObject.getCurrentPosition().getX(), // longitude  
                    currentTime
                );
                
                // 计算实时方向
                Double calculatedDirection = speedCalculationService.calculateRealtimeDirection(
                    movingObject.getObjectId(),
                    movingObject.getCurrentPosition().getY(), // latitude
                    movingObject.getCurrentPosition().getX(), // longitude
                    currentTime
                );
                
                // 处理速度值 - 如果计算返回null，使用合理默认值
                Double finalSpeed = calculatedSpeed;
                if (finalSpeed == null) {
                    switch (movingObject.getObjectType()) {
                        case AIRCRAFT:
                            finalSpeed = 40.0; // 航空器默认速度
                            break;
                        case SPECIAL_VEHICLE:
                        case NORMAL_VEHICLE:
                            finalSpeed = 25.0; // 机场车辆默认速度
                            break;
                        case UNMANNED_VEHICLE:
                            finalSpeed = 20.0; // 无人车默认速度
                            break;
                        default:
                            finalSpeed = 0.0;
                    }
                    log.debug("对象 {} 速度计算返回null，使用默认值: {} km/h", 
                             movingObject.getObjectId(), finalSpeed);
                }
                
                // 处理方向值 - 如果计算返回null，使用合理默认值  
                Double finalDirection = calculatedDirection;
                if (finalDirection == null) {
                    finalDirection = 0.0; // 默认朝北
                    log.debug("对象 {} 方向计算返回null，使用默认值: 0.0度", 
                             movingObject.getObjectId());
                }
                
                // 更新MovingObject的速度和方向
                movingObject.setCurrentSpeed(finalSpeed);
                movingObject.setCurrentHeading(finalDirection);
                
                // 更新缓存中的对象
                activeMovingObjectsCache.put(movingObject.getObjectId(), movingObject);
                
                log.debug("对象 {} 计算完成: 速度={} km/h, 方向={}度", 
                         movingObject.getObjectId(), finalSpeed, finalDirection);
                         
            } catch (Exception e) {
                log.error("计算对象 {} 的速度和方向时发生异常", movingObject.getObjectId(), e);
            }
        }
        
        log.debug("所有对象的速度和方向计算完成");
    }
    
    /**
     * 发送WebSocket位置更新消息
     */
    private void sendPositionUpdatesForActiveObjects(List<MovingObject> activeObjects) {
        if (activeObjects.isEmpty()) {
            log.debug("没有活跃对象，跳过位置更新消息发送");
            return;
        }
        
        long currentTime = System.currentTimeMillis();
        log.debug("发送位置更新消息，对象数量: {}", activeObjects.size());
        
        for (MovingObject movingObject : activeObjects) {
            try {
                // 创建位置更新消息负载
                PositionUpdatePayload.Position positionPayload = PositionUpdatePayload.Position.builder()
                        .latitude(movingObject.getCurrentPosition().getY())
                        .longitude(movingObject.getCurrentPosition().getX())
                        .build();
                
                // 处理速度值 - 如果为null，使用合理的默认值而不是0
                Double finalSpeed = movingObject.getCurrentSpeed();
                if (finalSpeed == null) {
                    // 根据对象类型使用合理的默认速度
                    switch (movingObject.getObjectType()) {
                        case AIRCRAFT:
                            finalSpeed = 40.0; // 航空器默认速度
                            break;
                        case SPECIAL_VEHICLE:
                        case NORMAL_VEHICLE:
                            finalSpeed = 25.0; // 机场车辆默认速度
                            break;
                        case UNMANNED_VEHICLE:
                            finalSpeed = 20.0; // 无人车默认速度
                            break;
                        default:
                            finalSpeed = 0.0;
                    }
                }
                
                // 处理方向值 - 如果为null，使用合理的默认值而不是0
                Double finalHeading = movingObject.getCurrentHeading();
                if (finalHeading == null) {
                    finalHeading = 0.0; // 默认朝北
                }
                
                PositionUpdatePayload payload = PositionUpdatePayload.builder()
                        .objectId(movingObject.getObjectId())
                        .objectType(movingObject.getObjectType().name())
                        .position(positionPayload)
                        .heading(finalHeading)
                        .speed(new BigDecimal(finalSpeed).setScale(2, RoundingMode.HALF_UP).doubleValue())
                        .timestamp(currentTime)
                        .build();
                
                // 发布WebSocket事件
                eventPublisher.publishEvent(new PositionUpdateEvent(payload));
                
                log.debug("发送位置更新: {} ({}), 位置: ({}, {}), 速度: {}", 
                         movingObject.getObjectId(), 
                         movingObject.getObjectType(),
                         movingObject.getCurrentPosition().getX(),
                         movingObject.getCurrentPosition().getY(),
                         movingObject.getCurrentSpeed());
                         
            } catch (Exception e) {
                log.error("发送位置更新消息失败: objectId={}", movingObject.getObjectId(), e);
            }
        }
        
        log.info("位置更新消息发送完成，发送数量: {}", activeObjects.size());
    }
    
    /**
     * 执行违规检测
     */
    private void performViolationDetection(List<MovingObject> activeObjects) {
        // 将MovingObject列表转换为VehicleLocation列表进行批量检测
        List<VehicleLocation> detectionVehicleLocations = activeObjects.stream()
                .map(this::createTemporaryVehicleLocationForDetection)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 执行统一的违规检测 (包括超速、区域访问、电子围栏等) - 使用规则执行引擎统一处理
        if (!detectionVehicleLocations.isEmpty()) {
            log.debug("执行统一违规检测，车辆数量: {}", detectionVehicleLocations.size());
            for (VehicleLocation vehicleLocation : detectionVehicleLocations) {
                try {
                    // 只处理无人车
                    if (vehicleLocation.getVehicleType() == MovingObjectType.UNMANNED_VEHICLE) {
                        // 构建车辆状态参数
                        Map<String, Object> vehicleState = new HashMap<>();
                        vehicleState.put("speed", vehicleLocation.getSpeed());
                        vehicleState.put("altitude", vehicleLocation.getAltitude());
                        vehicleState.put("heading", vehicleLocation.getHeading());
                        
                        // 统一调用规则执行引擎进行所有类型的违规检测（速度、区域访问、电子围栏等）
                        ruleExecutionEngine.detectAllViolations(
                            String.valueOf(vehicleLocation.getVehicleId()),
                            vehicleLocation.getVehicleType(),
                            vehicleLocation.getLocation(),
                            vehicleState,
                            vehicleLocation.getTimestamp()
                        );
                    }
                } catch (Exception e) {
                    log.error("车辆 {} 违规检测失败: {}", vehicleLocation.getVehicleId(), e.getMessage());
                }
            }
        } else {
            log.debug("没有可用于违规检测的车辆位置数据");
        }
    }
    
    /**
     * 周期性保存无人车位置数据到数据库
     */
    private void saveUnmannedVehicleDataPeriodically(List<MovingObject> activeObjects) {
        if (activeObjects.isEmpty()) {
            log.debug("没有活跃对象，跳过数据保存");
            return;
        }
        
        // 过滤出无人车对象
        List<MovingObject> unmannedVehicles = activeObjects.stream()
                .filter(obj -> obj.getObjectType() == MovingObjectType.UNMANNED_VEHICLE)
                .collect(Collectors.toList());
        
        if (unmannedVehicles.isEmpty()) {
            log.debug("没有无人车数据，跳过数据保存");
            return;
        }
        
        log.debug("开始周期性保存无人车位置数据，数量: {}", unmannedVehicles.size());
        
        // 将MovingObject转换为VehicleLocation并保存
        List<VehicleLocation> vehicleLocations = new ArrayList<>();
        for (MovingObject unmannedVehicle : unmannedVehicles) {
            try {
                // 创建一个临时的UnmannedVehicle对象用于转换
                UnmannedVehicle tempUnmannedVehicle = UnmannedVehicle.builder()
                    .objectId(unmannedVehicle.getObjectId())
                    .objectName(unmannedVehicle.getObjectName())
                    .currentPosition(unmannedVehicle.getCurrentPosition())
                    .currentSpeed(unmannedVehicle.getCurrentSpeed())
                    .currentHeading(unmannedVehicle.getCurrentHeading())
                    .altitude(unmannedVehicle.getAltitude())
                    .objectType(MovingObjectType.UNMANNED_VEHICLE)
                    .build();
                
                // 转换无人车数据为VehicleLocation
                VehicleLocation vehicleLocation = convertToVehicleLocation(tempUnmannedVehicle);
                
                if (vehicleLocation != null) {
                    vehicleLocations.add(vehicleLocation);
                }
            } catch (Exception e) {
                log.error("转换无人车数据失败: objectId={}", unmannedVehicle.getObjectId(), e);
            }
        }
        
        // 批量保存到数据库
        if (!vehicleLocations.isEmpty()) {
            try {
                vehicleDataPersistenceService.batchSaveUnmannedVehicleLocations(vehicleLocations);
                log.info("周期性保存无人车位置数据完成，保存数量: {}", vehicleLocations.size());
            } catch (Exception e) {
                log.error("批量保存无人车位置数据失败: 数量={}", vehicleLocations.size(), e);
            }
        } else {
            log.debug("没有有效的无人车位置数据可保存");
        }
    }
    
    /**
     * 将 UnmannedVehicle 转换为 VehicleLocation 实体用于持久化
     */
    private VehicleLocation convertToVehicleLocation(UnmannedVehicle vehicle) {
        if (vehicle == null || vehicle.getObjectId() == null || vehicle.getObjectId().trim().isEmpty()) {
            log.warn("无法转换无人车位置数据：对象或其 ID 为空或无效。对象: {}", vehicle);
            return null;
        }
        try {
            // 根据无人车的 objectId (车牌号/外部ID) 查询其在 sys_vehicle_info 表中的 Long 类型 vehicleId
            Optional<SysVehicleInfo> vehicleInfoOptional = quapDataAdapter.findVehicleByLicensePlate(vehicle.getObjectId());

            if (vehicleInfoOptional.isEmpty()) {
                log.warn("未找到无人车 {} 对应的系统车辆信息，跳过持久化。这可能意味着该无人车未在系统中注册。", vehicle.getObjectId());
                return null;
            }

            SysVehicleInfo sysVehicleInfo = vehicleInfoOptional.get();

            return VehicleLocation.builder()
                    .vehicleId(sysVehicleInfo.getVehicleId()) // 使用从 sys_vehicle_info 获取的 Long 类型 vehicleId
                    .location(geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(vehicle.getCurrentPosition().getX(), vehicle.getCurrentPosition().getY())))
                    .altitude(vehicle.getAltitude())
                    .speed(vehicle.getCurrentSpeed() != null ? vehicle.getCurrentSpeed() : 0.0)
                    .heading(vehicle.getCurrentHeading())
                    .timestamp(java.time.LocalDateTime.ofEpochSecond(System.currentTimeMillis() / 1000, 0, java.time.ZoneOffset.UTC))
                    .licensePlate(sysVehicleInfo.getLicensePlate()) // 设置运行时属性 licensePlate
                    .vehicleType(MovingObjectType.UNMANNED_VEHICLE) // 从无人车接口获取的数据，直接设置为无人车类型
                    .build();
        } catch (Exception e) {
            log.error("转换无人车位置数据时发生未知错误: objectId={}", vehicle.getObjectId(), e);
            return null;
        }
    }
    
    /**
     * 创建临时VehicleLocation用于违规检测（航空器和机场车辆）
     * 对于不持久化的MovingObject，生成一个临时的VehicleLocation用于RealTimeViolationDetector
     */
    private VehicleLocation createTemporaryVehicleLocationForDetection(MovingObject movingObject) {
        if (movingObject == null || movingObject.getObjectId() == null || movingObject.getObjectId().trim().isEmpty()) {
            return null;
        }

        try {
            Long vehicleIdForDetection;
            String licensePlateForDetection;
            MovingObjectType objectTypeForDetection = MovingObjectType.valueOf(movingObject.getObjectType().name());

            if (MovingObjectType.UNMANNED_VEHICLE.equals(movingObject.getObjectType())) {
                // 对于无人车，其objectId就是车牌号，可以从sys_vehicle_info中查到vehicleId
                Optional<SysVehicleInfo> vehicleInfoOptional = quapDataAdapter.findVehicleByLicensePlate(movingObject.getObjectId());
                if (vehicleInfoOptional.isEmpty()) {
                    log.warn("未找到无人车 {} 对应的系统车辆信息，跳过违规检测。这可能意味着该无人车未在系统中注册。", movingObject.getObjectId());
                    return null;
                }
                SysVehicleInfo sysVehicleInfo = vehicleInfoOptional.get();
                vehicleIdForDetection = sysVehicleInfo.getVehicleId();
                licensePlateForDetection = sysVehicleInfo.getLicensePlate();
            } else {
                // 对于航空器和机场车辆（包括特勤车），其objectId是flightNo或vehicleNo，
                // 生成一个临时的、一致的Long类型ID，用于内部检测和日志记录
                vehicleIdForDetection = (long) movingObject.getObjectId().hashCode(); // 使用hashCode生成一个伪ID
                licensePlateForDetection = movingObject.getObjectId(); // 用objectId作为车牌号
            }

            Point currentPosition = movingObject.getCurrentPosition();
            if (currentPosition == null) {
                log.warn("对象 {} 位置信息缺失，跳过违规检测。", movingObject.getObjectId());
                return null;
            }

            log.debug("在createTemporaryVehicleLocationForDetection方法中，准备创建VehicleLocation，MovingObject的速度为: {}", movingObject.getCurrentSpeed());

            return VehicleLocation.builder()
                    .vehicleId(vehicleIdForDetection)
                    .location(geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(currentPosition.getX(), currentPosition.getY())))
                    .altitude(movingObject.getAltitude() != null ? movingObject.getAltitude() : 0.0)
                    .speed(movingObject.getCurrentSpeed() != null ? movingObject.getCurrentSpeed() : 0.0)
                    .heading(movingObject.getCurrentHeading() != null ? movingObject.getCurrentHeading() : 0.0)
                    .timestamp(java.time.LocalDateTime.ofEpochSecond(System.currentTimeMillis() / 1000, 0, java.time.ZoneOffset.UTC)) // 使用当前时间作为检测时间戳
                    .licensePlate(licensePlateForDetection)
                    .vehicleType(objectTypeForDetection)
                    .build();
        } catch (Exception e) {
            log.error("创建临时VehicleLocation用于违规检测失败: objectId={}", movingObject.getObjectId(), e);
            return null;
        }
    }
}