package com.ningdatech.carapi.radar.task;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.ningdatech.carapi.radar.helper.RadarDataHelper;
import com.ningdatech.carapi.radar.model.entity.RadarData;
import com.ningdatech.carapi.radar.model.entity.RadarOriginalData;
import com.ningdatech.carapi.radar.model.vo.RadarDataVO;
import com.ningdatech.carapi.radar.service.IRadarDataService;
import com.ningdatech.carapi.radar.service.IRadarOriginalDataService;
import com.ningdatech.carapi.road.model.entity.TrafficFlow;
import com.ningdatech.carapi.road.service.impl.ITrafficFlowServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.carapi.gps.manage.GpsDataPullManage;

import cn.hutool.core.date.StopWatch;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author CMM
 * 雷达实时数据更新定时任务
 * @since 2024/10/12 10:39
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class RadarRealTimeDataUpdateTask {

    @Value("${task.switch.is-open}")
    private boolean flag;

    private final IRadarOriginalDataService radarOriginalDataService;
    private final RadarDataHelper radarDataHelper;
    private final IRadarDataService radarDataService;
    private final ITrafficFlowServiceImpl trafficFlowService;

    // 定时更新雷达实时数据 每1分钟一次
    @Scheduled(cron = "0 */1 * * * ?")

    public void doTask() {
        if (!flag){
            log.info("雷达实时数据更新定时任务未开启!");
            return;
        }
        log.info("=========== 雷达实时数据更新 ======== 任务开始");
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 从表中分别获取三个盒子的最新的目标轨迹数据和交通流量数据
        List<RadarOriginalData> dataList = radarOriginalDataService.list();
        log.info("=========== 雷达实时数据更新 ======== 获取数据条数:{}",dataList.size());
        // 按照盒子ip分组
        Map<String, List<RadarOriginalData>> dataMap = dataList.stream().collect(Collectors.groupingBy(RadarOriginalData::getArmIp));
        List<RadarOriginalData> finalDataList = Lists.newArrayList();
        for (Map.Entry<String, List<RadarOriginalData>> entry : dataMap.entrySet()) {
            // 针对每个盒子分别解析数据
            String armIp = entry.getKey();
            List<RadarOriginalData> datas = entry.getValue();
            log.info("=========== 雷达实时数据更新 ======== 盒子ip:{},数据条数:{}",armIp, datas.size());
            // 盒子有对应的原始数据
            if (CollUtil.isNotEmpty(datas)) {
                // 根据数据类型进行分组
                Map<String, List<RadarOriginalData>> dataTypeMap = datas.stream().filter(d -> Objects.nonNull(d.getDataType())).collect(Collectors.groupingBy(RadarOriginalData::getDataType));
                // 获取每个数据类型（目标轨迹数据或者交通流量数据）的数据中最新的一条数据
                for (Map.Entry<String, List<RadarOriginalData>> dataTypeEntry : dataTypeMap.entrySet()) {
                    String dataType = dataTypeEntry.getKey();
                    List<RadarOriginalData> dataTypeDatas = dataTypeEntry.getValue();
                    if (Objects.nonNull(dataTypeDatas) && CollUtil.isNotEmpty(dataTypeDatas)) {
                        log.info("=========== 雷达实时数据更新 ======== 数据类型:{},数据量:{}",dataType,dataTypeDatas.size());
                        // 解析所有原始数据
                        for (RadarOriginalData radarOriginalData : dataTypeDatas) {
                            if (Objects.nonNull(radarOriginalData)) {
                                RadarOriginalData data = new RadarOriginalData();
                                data.setId(radarOriginalData.getId());
                                data.setData(radarOriginalData.getData());
                                data.setArmIp(armIp);
                                data.setDataType(dataType);
                                finalDataList.add(data);
                            }
                        }
                    }
                }
            }
        }
        // 处理数据
        List<RadarData> objects = Lists.newArrayList();
        for (RadarOriginalData radarOriginalData : finalDataList) {
            String armIp = radarOriginalData.getArmIp();
            String dataType = radarOriginalData.getDataType();
            String data = radarOriginalData.getData();
            List<RadarDataVO> radarDataList = radarDataHelper.getRadarDataList(data);
            if (CollUtil.isNotEmpty(radarDataList)) {
                // 获取radarDataList中数据类型为dataType的数据
                List<RadarDataVO> dataTypeDataList = radarDataList.stream().filter(radarDataVO -> radarDataVO.getDataType().equals(dataType)).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(dataTypeDataList)) {
                    for (RadarDataVO radarDataVO : dataTypeDataList) {
                        RadarData radarData = new RadarData();
                        radarData.setArmIp(armIp);
                        Map<String, String> deviceIdRadarIpMap = new HashMap<>();
                        deviceIdRadarIpMap.put("21626092", "192.168.6.43");
                        deviceIdRadarIpMap.put("21626098", "192.168.6.40");
                        deviceIdRadarIpMap.put("21626114", "192.168.6.45");
                        deviceIdRadarIpMap.put("21626163", "192.168.6.47");
                        deviceIdRadarIpMap.put("21626197", "192.168.10.63");
                        deviceIdRadarIpMap.put("21626107", "192.168.10.60");
                        String radarIp = deviceIdRadarIpMap.getOrDefault(radarDataVO.getDeviceId(), null);
                        radarData.setRadarIp(radarIp);
                        String voDataType = radarDataVO.getDataType();
                        if ("1".equals(voDataType)) {
                            radarData.setDataType(1);
                        } else if ("3".equals(voDataType)) {
                            radarData.setDataType(2);
                        }
                        radarData.setCreateOn(LocalDateTime.now());
                        radarData.setUpdateOn(LocalDateTime.now());

                        radarData.setTargetLane(radarDataVO.getTargetLane());

                        Map<String, Integer> carTypeMap = new HashMap<>();
                        carTypeMap.put("00", 4);
                        carTypeMap.put("01", 1);
                        carTypeMap.put("02", 2);
                        carTypeMap.put("03", 3);

                        Integer type = carTypeMap.getOrDefault(radarDataVO.getCarType(), 4);
                        radarData.setCarType(type);
                        radarData.setTargetSpeed(radarDataVO.getTargetSpeed());
                        radarData.setTargetLongitude(radarDataVO.getTargetLongitude());
                        radarData.setTargetLatitude(radarDataVO.getTargetLatitude());

                        radarData.setRealTimeTrafficFlow(radarDataVO.getRealTimeTrafficFlow());
                        radarData.setAverageCarSpeed(radarDataVO.getAverageCarSpeed());
                        radarData.setMaxQueueLength(radarDataVO.getMaxQueueLength());
                        radarData.setCreateOn(LocalDateTime.now());
                        radarData.setUpdateOn(LocalDateTime.now());
                        objects.add(radarData);
                    }
                }
            }
        }

        // 将dataList从表中删除
        if (CollUtil.isNotEmpty(dataList)) {
            // 删除此次查询的数据
            List<Long> removeIdList = dataList.stream().map(RadarOriginalData::getId).collect(Collectors.toList());
            radarOriginalDataService.removeBatchByIds(removeIdList);
            log.info("=========== 雷达实时数据更新 ======== 删除数据条数:{}", removeIdList.size());
        }

        // 插入数据
        if (CollUtil.isNotEmpty(objects)) {
            // 先删除旧数据
            List<Long> idList = radarDataService.list(Wrappers.lambdaQuery(RadarData.class).select(RadarData::getId)).stream().map(RadarData::getId).collect(Collectors.toList());
            radarDataService.removeBatchByIds(idList);
            log.info("=========== 雷达实时数据更新 ======== 删除旧数据条数:{}",idList.size());
            radarDataService.saveBatch(objects);
            log.info("=========== 雷达实时数据更新 ======== 插入数据条数:{}",objects.size());
        }
        List<RadarData> hsyw = radarDataService.list(Wrappers.lambdaQuery(RadarData.class)
                .eq(RadarData::getDataType, "2")
                .eq(RadarData::getRadarIp,"192.168.6.40"));
        Integer sum1 = hsyw.stream().mapToInt(p -> {
            return Integer.parseInt(p.getRealTimeTrafficFlow());
        }).sum();
        saveTrafficFlow(1,sum1);

        List<RadarData> hsdy = radarDataService.list(Wrappers.lambdaQuery(RadarData.class)
                .eq(RadarData::getDataType, "2")
                .eq(RadarData::getRadarIp,"192.168.6.47"));
        Integer sum2 = hsdy.stream().mapToInt(p -> {
            return Integer.parseInt(p.getRealTimeTrafficFlow());
        }).sum();
        saveTrafficFlow(2,sum2);

        List<RadarData> hlyw = radarDataService.list(Wrappers.lambdaQuery(RadarData.class)
                .eq(RadarData::getDataType, "2")
                .eq(RadarData::getRadarIp,"192.168.10.60"));
        Integer sum3 = hlyw.stream().mapToInt(p -> {
            return Integer.parseInt(p.getRealTimeTrafficFlow());
        }).sum();
        saveTrafficFlow(3,sum3);

        stopWatch.stop();
        log.info("=========== 雷达实时数据更新 ======== 任务结束 {}s",stopWatch.getTotalTimeSeconds());
    }

    private void saveTrafficFlow(Integer region,Integer sum){
        TrafficFlow trafficFlow = trafficFlowService.getOne(Wrappers.lambdaQuery(TrafficFlow.class)
                .eq(TrafficFlow::getRegion, region)
                .orderByDesc(TrafficFlow::getCreateOn)
                .last("limit 1"));
        LocalDateTime createOn = trafficFlow.getCreateOn();

        if (Objects.nonNull(trafficFlow.getCreateOn())){

            if (LocalDateTime.now().getHour()==trafficFlow.getCreateOn().getHour()) {
                trafficFlow.setTrafficFlow(String.valueOf(Integer.valueOf(trafficFlow.getTrafficFlow()) + Integer.valueOf(sum)));
                trafficFlowService.updateById(trafficFlow);
            }else {
                TrafficFlow newTrafficFlow = new TrafficFlow();
                newTrafficFlow.setTrafficFlow(sum.toString());
                newTrafficFlow.setCreateOn(LocalDateTime.now());
                newTrafficFlow.setRegion(region);
                trafficFlowService.save(newTrafficFlow);
            }
        }
        if (Objects.isNull(trafficFlow)){
            TrafficFlow newTrafficFlow = new TrafficFlow();
            newTrafficFlow.setTrafficFlow(sum.toString());
            newTrafficFlow.setCreateOn(LocalDateTime.now());
            newTrafficFlow.setRegion(region);
            trafficFlowService.save(newTrafficFlow);
        }
    }

}
