package com.ningdatech.carapi.radar.manage;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.socket.SocketUtil;
import com.ningdatech.carapi.radar.helper.RadarDataHelper;
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.BeanUtils;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.carapi.radar.constant.RadarCarTypeEnum;
import com.ningdatech.carapi.radar.constant.RadarDataTypeEnum;
import com.ningdatech.carapi.radar.model.entity.RadarData;
import com.ningdatech.carapi.radar.model.vo.RadarObjectDataVO;
import com.ningdatech.carapi.radar.model.vo.RadarTrafficFlowDataVO;
import com.ningdatech.carapi.radar.service.IRadarDataService;
import com.ningdatech.carapi.road.model.req.RoadMonitorReq;

import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 车辆位置信息
 *
 * @author CMM
 * @since 2023/11/17 09:35
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RadarManage {

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

    public String getRadarDataAsClient() {
        // 盒子ip地址：192.168.6.42 --> 192.168.6.40（黄山隧道义乌来向雷达）、192.168.6.43（黄山隧道义乌去向雷达）
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        // 默认结果
        String result = "接收失败!";
        String ip = "192.168.6.42";
        // String ip = "192.168.2.249";
        try (Socket socket = SocketUtil.connect(ip, 13000)) {
            log.info("Client connected to server on port: {}", 13000);
            InputStream inputStream = socket.getInputStream();
            if (Objects.nonNull(inputStream)) {
                // 读取输入流中的1024个字节
                byte[] buffer = new byte[1024];
                if (inputStream.available() > 0) {
                    int len = inputStream.read(buffer);
                    // 处理读取到的数据
                    byte[] data = Arrays.copyOf(buffer, len);
                    log.info("Received: {}", Arrays.toString(data));
                    log.info("Connect Successfully!");
                }else {
                    return "流数据为空!";
                }
            }else{
                return result;
            }
            // 从接入数据 开始 持续接收1分钟的数据 接收完成后 关闭连接
            // 设置1分钟后关闭连接
            executor.schedule(() -> {
                try {
                    socket.close();
                } catch (IOException e) {
                    log.error("Error closing client socket: ", e);
                }
            }, 1, TimeUnit.MINUTES);

            // 开启保活选项
            socket.setKeepAlive(true);
            byte[] buffer = new byte[1024];
            int bytesRead;
            // 循环读取数据，直到Socket被关闭
            while (!socket.isClosed() && (bytesRead = inputStream.read(buffer)) != -1) {
                // 处理读取到的数据
                String dataString = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
                log.info("Received: {}", dataString);
                radarDataHelper.processRadarData(dataString);
            }
            // 如果循环正常结束，则修改结果
            result = "接收成功!";
        } catch (IOException e) {
            return e.getMessage();
        }finally {
            // 关闭ScheduledExecutorService
            executor.shutdown();
            try {
                if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
            }
        }
        // 返回最终结果
        return result;
    }

    public String getRadarDataAsServer() {
        // 盒子ip地址：192.168.6.42 --> 192.168.6.40（黄山隧道义乌来向雷达）、192.168.6.43（黄山隧道义乌去向雷达）
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        // 默认结果
        String result = "接收失败!";
        String ip = "192.168.6.42";
        //String ip = "192.168.2.249";
        try (ServerSocket serverSocket = new ServerSocket()) {
            // 设置超时时间
            serverSocket.setSoTimeout(60000);
            InetSocketAddress address = new InetSocketAddress(ip, 13000);
            //InetSocketAddress address = new InetSocketAddress("192.168.2.254", 13000);
            serverSocket.bind(address);

            // 等待客户端连接
            System.out.println("等待客户端连接...");
            Socket socket = serverSocket.accept();
            System.out.println("客户端已连接！");

            // 读取客户端推送的数据
            InputStream inputStream = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                // 处理接收到的数据
                String data = new String(buffer, 0, len);
                System.out.println("接收到数据：" + data);
            }
            result = "接收成功!";
        } catch (Exception e) {
            log.error("Error closing server socket: ", e);
        }
        // 返回最终结果
        return result;
    }


    public RadarTrafficFlowDataVO radarTrafficFlowData(RoadMonitorReq req) {
        RadarTrafficFlowDataVO vo = new RadarTrafficFlowDataVO();
        String region = req.getRegion();
        // 雷达区域-ip对应关系
        Map<String, String> radarRegionIpMap = getRadarRegionIpMap();
        // 判断查询的是哪个设备的数据
        String radarIp = radarRegionIpMap.getOrDefault(region, null);
        if (StringUtils.isBlank(radarIp)){
            throw new BizException("查询区域数据不存在!");
        }
        // 从雷达数据信息表中获取查询区域最新的一条流量数据
        RadarData radarData = radarDataService.getOne(Wrappers.lambdaQuery(RadarData.class)
                .eq(RadarData::getRadarIp, radarIp)
                .eq(RadarData::getDataType, RadarDataTypeEnum.TRAFFIC_DATA.getCode())
                .orderByDesc(RadarData::getUpdateOn)
                .last("limit 1"));
        if (Objects.nonNull(radarData)) {
            BeanUtils.copyProperties(radarData, vo);
        }
        String region1 = null;
        if (req.getRegion().equals("1")||req.getRegion().equals("2")){
            region1="1";
        }else if (req.getRegion().equals("3")||req.getRegion().equals("4")){
            region1="2";
        }else if (req.getRegion().equals("5")||req.getRegion().equals("6")){
            region1="3";
        }
        TrafficFlow trafficFlow = trafficFlowService.getOne(Wrappers.lambdaQuery(TrafficFlow.class)
                .eq(TrafficFlow::getRegion, region1)
                .orderByDesc(TrafficFlow::getCreateOn)
                .last("limit 1"));
        if (Objects.nonNull(trafficFlow)){
            vo.setRealTimeTrafficFlow(trafficFlow.getTrafficFlow());
        }
        return vo;
    }

    private static Map<String, String> getRadarRegionIpMap() {
        Map<String, String> radarRegionIpMap = new HashMap<>();
        // 黄山隧道东阳去向
        radarRegionIpMap.put("1", "192.168.6.45");
        // 黄山隧道东阳来向
        radarRegionIpMap.put("2", "192.168.6.47");
        // 黄山隧道义乌去向
        radarRegionIpMap.put("3", "192.168.6.43");
        // 黄山隧道义乌来向
        radarRegionIpMap.put("4", "192.168.6.40");
        // 何里隧道兰溪方向
        radarRegionIpMap.put("5", "192.168.10.63");
        // 何里隧道义乌方向
        radarRegionIpMap.put("6", "192.168.10.60");
        return radarRegionIpMap;
    }

    public List<RadarObjectDataVO> radarObjectData(RoadMonitorReq req) {
        String region = req.getRegion();
        // 雷达区域-ip对应关系
        Map<String, String> radarRegionIpMap = getRadarRegionIpMap();
        // 判断查询的是哪个设备的数据
        String radarIp = radarRegionIpMap.getOrDefault(region, null);
        if (StringUtils.isBlank(radarIp)){
            throw new BizException("查询区域数据不存在!");
        }
        // 从雷达数据信息表中获取查询区域最近1分钟的目标数据
        LocalDateTime startTime = LocalDateTime.now().minusMinutes(1);
        List<RadarData> radarDataList = radarDataService.list(Wrappers.lambdaQuery(RadarData.class)
                .eq(RadarData::getRadarIp, radarIp)
                .eq(RadarData::getDataType, RadarDataTypeEnum.OBJECT_DATA.getCode())
                .ge(RadarData::getUpdateOn, startTime)
                .orderByDesc(RadarData::getUpdateOn));
        // 如果查询不到数据，则返回雷达数据表中最新的100条目标轨迹数据
        if (CollUtil.isEmpty(radarDataList)){
            radarDataList = radarDataService.list(Wrappers.lambdaQuery(RadarData.class)
                    .eq(RadarData::getRadarIp, radarIp)
                    .eq(RadarData::getDataType, RadarDataTypeEnum.OBJECT_DATA.getCode())
                    .orderByDesc(RadarData::getUpdateOn)
                    .last("limit 100"));
        }
        return radarDataList.stream().map(d -> {
            RadarObjectDataVO vo = new RadarObjectDataVO();
            // 转换为中文
            String targetLane = d.getTargetLane();
            // 如果是以1开头 表示上行（靠近雷达） 拼接上行 + 所属车道编号
            if (StringUtils.startsWith(targetLane, "1")){
                vo.setTargetLane("上行" + targetLane);
            }
            // 如果是以3开头 表示下行（远离雷达） 拼接下行 + 所属车道编号
            else if (StringUtils.startsWith(targetLane, "3")){
                vo.setTargetLane("下行" + targetLane);
            }else {
                vo.setTargetLane("未知车道");
            }
            vo.setCarType(RadarCarTypeEnum.getDescByCode(d.getCarType()));
            vo.setTargetSpeed(d.getTargetSpeed());
            vo.setTargetLatitude(d.getTargetLatitude());
            vo.setTargetLongitude(d.getTargetLongitude());
            vo.setUpdateOn(d.getUpdateOn());
            return vo;
        }).collect(Collectors.toList());
    }

    public RadarTrafficFlowDataVO workbenchRadarTrafficFlowData(RoadMonitorReq req) {
        RadarTrafficFlowDataVO vo = new RadarTrafficFlowDataVO();
        // 雷达区域-ip对应关系
        List<RadarData> radarDataList = getRadarDataList();
        if (CollUtil.isEmpty(radarDataList)){
            vo.setRealTimeTrafficFlow("0");
            return vo;
        }
        // 计算实时流量的和
        List<String> list = radarDataList.stream().map(RadarData::getRealTimeTrafficFlow).collect(Collectors.toList());
        List<BigDecimal> decimals = list.stream().map(BigDecimal::new).collect(Collectors.toList());

        BigDecimal total = decimals.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        vo.setRealTimeTrafficFlow(String.valueOf(total));
        return vo;
    }

    private List<RadarData> getRadarDataList() {
        Map<String, String> radarRegionIpMap = getRadarRegionIpMap();
        List<String> radarIpList = new ArrayList<>(radarRegionIpMap.values());

        // 从雷达数据信息表中获取每个区域最新的一条流量数据
        List<RadarData> radarDataList = Lists.newArrayList();
        radarIpList.forEach(radarIp -> {
            RadarData radarData = radarDataService.getOne(Wrappers.lambdaQuery(RadarData.class)
                    .eq(RadarData::getRadarIp, radarIp)
                    .eq(RadarData::getDataType, RadarDataTypeEnum.TRAFFIC_DATA.getCode())
                    .orderByDesc(RadarData::getUpdateOn)
                    .last("limit 1"));
            if (Objects.nonNull(radarData)) {
                radarDataList.add(radarData);
            }
        });
        return radarDataList;
    }
}
