package com.ltgk.video.controller;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ltgk.common.annotation.Anonymous;
import com.ltgk.common.annotation.Log;
import com.ltgk.common.annotation.RepeatSubmit;
import com.ltgk.common.core.controller.BaseController;
import com.ltgk.common.core.domain.AjaxResult;
import com.ltgk.common.core.domain.entity.SysUser;
import com.ltgk.common.core.page.TableDataInfo;
import com.ltgk.common.enums.BusinessType;
import com.ltgk.common.utils.CameraDegreesUtil;
import com.ltgk.common.utils.SecurityUtils;
import com.ltgk.common.utils.StringUtils;
import com.ltgk.common.utils.bean.BeanUtils;
import com.ltgk.common.utils.poi.ExcelUtil;
import com.ltgk.common.utils.sql.MybatisUtil;
import com.ltgk.video.domain.dto.DsArtemisDTO;
import com.ltgk.video.domain.dto.VideoServoDTO;
import com.ltgk.video.domain.entity.DsVideo;
import com.ltgk.video.domain.entity.DsVideoLog;
import com.ltgk.video.domain.entity.UavWeather;
import com.ltgk.video.domain.vo.DsDynamicLkdVO;
import com.ltgk.video.domain.vo.DsVideoExcelVO;
import com.ltgk.video.domain.vo.GetVideoStatusLogVo;
import com.ltgk.video.domain.vo.VideoCountVO;
import com.ltgk.video.service.DsVideoLogService;
import com.ltgk.video.service.IDsVideoService;
import com.ltgk.video.service.IUavWeatherService;
import com.ltgk.video.service.impl.ArtemisPostService;
import com.ltgk.video.service.impl.DsCameraService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.compress.utils.Lists;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 视频监控管理表 前端控制器
 * </p>
 *
 * @author zhouyaoyao
 * @since 2025-01-19
 */
@Api(tags = "视频监控设备信息")
@RestController
@RequestMapping("/fishingPort/dsVideo")
public class DsVideoController extends BaseController {

    @Resource
    IDsVideoService dsVideoService;
    @Resource
    RedisTemplate redisTemplate;
    @Resource
    DsCameraService dsCameraService;
    @Resource
    IUavWeatherService uavWeatherService;
    @Resource
    private DsVideoLogService dsVideoLogService;

    @ApiOperation(value = "查询列表数据")
    @PostMapping("/getList")
    @Log(title = "视频监控设备信息", businessType = BusinessType.QUERY)
    public Object getList(@RequestBody DsVideo dsVideo) {
        QueryWrapper<DsVideo> queryWrapper = MybatisUtil.notNullField(dsVideo);
        List<DsVideo> list = dsVideoService.list(queryWrapper);
        return success(list);
    }

    /**
     * 视频监控层级列表
     *
     * @param dsVideo:
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2025/3/11
     */
    @ApiOperation(value = "视频监控层级列表")
    @PostMapping("/findVideoLevelList")
    @Log(title = "视频监控设备信息", businessType = BusinessType.QUERY)
    public AjaxResult findVideoLevelList(@RequestBody DsVideo dsVideo) {
        LambdaQueryWrapper<DsVideo> wrapper = new LambdaQueryWrapper<>(dsVideo);
        List<DsVideo> dsVideoList = dsVideoService.list(wrapper);
        return success(dsVideoList.stream()
                .collect(Collectors.groupingBy(DsVideo::getBelongUnit)));
    }


    @ApiOperation(value = "分页查询")
    @PostMapping("/page")
    @Log(title = "视频监控设备信息", businessType = BusinessType.PAGE_QUERY)
    public Object page(@RequestBody DsVideo dsVideo) {
        QueryWrapper<DsVideo> queryWrapper = MybatisUtil.notNullField(dsVideo);
        startPage(dsVideo.getPageNum(), dsVideo.getPageSize());
        List<DsVideo> list = dsVideoService.list(queryWrapper);
        return getDataTable(list);
    }

    @ApiOperation(value = "详情查询")
    @PostMapping("/detail")
    @Log(title = "视频监控设备信息", businessType = BusinessType.QUERY)
    public Object page(@RequestParam("id") Long id) {
        if (Objects.isNull(id)) {
            return AjaxResult.error("id不能为空");
        }
        DsVideo dsVideo = dsVideoService.getById(id);
        return success(dsVideo);
    }

    @RepeatSubmit(message = "请勿重复提交")
    @ApiOperation(value = "添加")
    @PostMapping("/save")
    @Log(title = "视频监控设备信息", businessType = BusinessType.INSERT)
    public Object save(@RequestBody DsVideo dsVideo) {
        String userName = SecurityUtils.getLoginUser().getUser().getNickName();
        dsVideo.setCreateBy(userName)
                .setCreateAt(new Date())
                .setUpdateBy(userName)
                .setUpdateAt(new Date());
        AjaxResult result = toAjax(dsVideoService.save(dsVideo));
        updateYunVideoList();
        return result;
    }

    @ApiOperation(value = "编辑")
    @PostMapping("/update")
    @Log(title = "视频监控设备信息", businessType = BusinessType.UPDATE)
    public Object update(@RequestBody DsVideo dsVideo) {
        String userName = SecurityUtils.getLoginUser().getUser().getNickName();
        dsVideo.setUpdateBy(userName)
                .setUpdateAt(new Date());
        AjaxResult result = toAjax(dsVideoService.updateById(dsVideo));
        updateYunVideoList();
        return result;
    }

    @ApiOperation(value = "删除")
    @PostMapping("/delete")
    @Log(title = "视频监控设备信息", businessType = BusinessType.DELETE)
    public Object delete(@RequestBody DsVideo dsVideo) {
        AjaxResult result = toAjax(dsVideoService.removeById(dsVideo.getId()));
        updateYunVideoList();
        return result;
    }

    @Log(title = "视频监控设备信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ApiOperation(value = "导出数据")
    public void export(HttpServletResponse response, DsVideo dsVideo) {
        QueryWrapper<DsVideo> queryWrapper = MybatisUtil.notNullField(dsVideo);
        List<DsVideo> dataList = dsVideoService.list(queryWrapper);

        List<DsVideoExcelVO> dsVideoExcelVOS = dataList.stream()
                .map(item -> {
                    DsVideoExcelVO excelItem = new DsVideoExcelVO();
                    BeanUtils.copyProperties(item, excelItem);
                    return excelItem;
                })
                .collect(Collectors.toList());

        ExcelUtil<DsVideoExcelVO> util = new ExcelUtil<>(DsVideoExcelVO.class);
        util.exportExcel(response, dsVideoExcelVOS, "视频监控设备信息数据");
    }

    @Log(title = "视频监控设备信息", businessType = BusinessType.EXPORT)
    @PostMapping("/importTemplate")
    @ApiOperation(value = "导入模板导出")
    public void importTemplate(HttpServletResponse response) {

        List<DsVideoExcelVO> dsVideoExcelVOS = Lists.newArrayList();

        ExcelUtil<DsVideoExcelVO> util = new ExcelUtil<>(DsVideoExcelVO.class);
        util.exportExcel(response, dsVideoExcelVOS, "视频监控设备信息数据");
    }

    @RepeatSubmit(message = "请勿重复提交")
    @Log(title = "视频监控设备信息导入", businessType = BusinessType.IMPORT)
    @ApiOperation("视频监控设备信息导入")
    @PostMapping("/importData")
    public AjaxResult importData(@RequestBody MultipartFile file) throws Exception {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 校验是否为 Excel 格式
        ExcelUtil.checkExcelFile(file);
        ExcelUtil<DsVideoExcelVO> util = new ExcelUtil<>(DsVideoExcelVO.class);
        List<DsVideoExcelVO> dsVideoExcelVOS = util.importExcel(file.getInputStream());
        if (CollectionUtils.isEmpty(dsVideoExcelVOS) || dsVideoExcelVOS.stream().allMatch(Objects::isNull)) {
            return AjaxResult.error("导入数据为空或模板格式有误！");
        }

        List<DsVideo> dsVideos = dsVideoExcelVOS.stream().map(m -> {
            DsVideo dsVideo = new DsVideo();
            BeanUtils.copyProperties(m, dsVideo);
            dsVideo.setCreateBy(user.getNickName())
                    .setCreateAt(new Date())
                    .setUpdateBy(user.getNickName())
                    .setUpdateAt(new Date());
            return dsVideo;
        }).collect(Collectors.toList());
        boolean flag = dsVideoService.saveBatchByName(dsVideos);

        AjaxResult result = toAjax(flag);
        updateYunVideoList();
        return result;
    }

    @Log(title = "通过海康综合安防平台查询视频监控设备的预览视频流链接", businessType = BusinessType.QUERY)
    @ApiOperation("通过海康综合安防平台查询视频监控设备的预览视频流链接")
    @PostMapping("/getPreviewUrlByArtemis")
    public AjaxResult getPreviewUrlByArtemis(@RequestBody DsArtemisDTO dsArtemisDTO) {
        String previewProtocol = dsArtemisDTO.getPreviewProtocol();
        if (StringUtils.isEmpty(previewProtocol)) {
            previewProtocol = "hls";
        }
        return AjaxResult.success(ArtemisPostService.getPreviewUrl(dsArtemisDTO.getVideoCode(), previewProtocol));
    }

    /**
     * 光电联动反向定位，判断监控设备和将要联动的定位目标是否超出可视范围、是否处于视角遮挡区
     *
     * @return
     */
    @Log(title = "光电联动反向定位判断", businessType = BusinessType.QUERY)
    @ApiOperation("光电联动反向定位判断")
    @PostMapping("/judgeMoveByGps")
    public AjaxResult judgeMoveByGps(@RequestBody VideoServoDTO videoServoDTO) {
        String deviceCode = videoServoDTO.getDeviceCode();
        String gpsX = videoServoDTO.getGpsX();
        String gpsY = videoServoDTO.getGpsY();
        LambdaQueryWrapper<DsVideo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DsVideo::getVideoCode, deviceCode);
        queryWrapper.last("limit 1");
        DsVideo videos = dsVideoService.getOne(queryWrapper);
        if (Objects.isNull(videos)) {
            return error("未查到该摄像头");
        }
        // 默认可视距离 5KM
        Double visibleDistance = 5d;
        if (!Objects.isNull(videos.getVisionDistance())) {
            visibleDistance = videos.getVisionDistance().doubleValue();
        }
        try {
            double latitudeVal = videos.getLatitude().doubleValue();
            double longitudeVal = videos.getLongitude().doubleValue();
            double gpsXVal = Double.parseDouble(gpsX);
            double gpsYVal = Double.parseDouble(gpsY);
            double distance = CameraDegreesUtil.getDistance(longitudeVal, latitudeVal, gpsXVal, gpsYVal).setScale(5, RoundingMode.HALF_UP).doubleValue();
            if (org.apache.commons.lang.StringUtils.isNotBlank(videos.getXRotateVal())) {
                BigDecimal degreeX = CameraDegreesUtil.rotateForNorthByLR(longitudeVal, latitudeVal, gpsXVal, gpsYVal, videos.getRotateT());
                double degreeXVal = degreeX.doubleValue();
                degreeXVal = degreeXVal < 0 ? 360 + degreeXVal : degreeXVal;
                double dxVal = degreeXVal;
                String xRotateVal = videos.getXRotateVal();
                List<Boolean> flags = Arrays.asList(xRotateVal.split(";")).stream().map(item -> {
                    String itemStr1 = item.split("-")[0];
                    String itemStr2 = item.split("-")[1];
                    double itemVal1 = Double.parseDouble(itemStr1);
                    double itemVal2 = Double.parseDouble(itemStr2);
                    return itemVal1 < dxVal && itemVal2 > dxVal;
                }).collect(Collectors.toList());
                if (!flags.contains(true)) {
                    return error("超出监控摄像头可视角度，此监控角度有遮挡");
                }
            }
            if (distance > visibleDistance) {
                return error("超出监控摄像头可视范围");
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return success();
    }

    /**
     * 云台类型监控设备列表，用于光电联动时获取联动目标附近的视频监控设备
     */
    List<DsVideo> yunVideoCodeList = Lists.newArrayList();

    /**
     * 定时（4个小时）更新一次云台类型监控设备列表
     */
    @Scheduled(cron = "0 0 0/4 * * ?")
    public List<DsVideo> updateYunVideoList() {
        LambdaQueryWrapper<DsVideo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(DsVideo::getVideoType, "云台")
                .eq(DsVideo::getRunStatus, "正常")
                // 获取没有锁定的摄像头
                .eq(DsVideo::getBeLock, 0)
        ;
        queryWrapper.orderByAsc(DsVideo::getVideoName);
        List<DsVideo> list = dsVideoService.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            yunVideoCodeList = list.stream()
                    .filter(f -> "云台".equals(f.getVideoType()) && StringUtils.isNotBlank(f.getVideoCode()))
                    .collect(Collectors.toList());
            return yunVideoCodeList;
        } else {
            return Lists.newArrayList();
        }
    }

    /**
     * 光电联动反向定位联动控制，根据监控设备和将要联动的定位目标经纬度控制视频监控设备转动对焦
     *
     * @return
     */
    @Log(title = "光电联动反向定位联动控制", businessType = BusinessType.QUERY)
    @ApiOperation("光电联动反向定位联动控制")
    @PostMapping("/sitMoveByGps")
    public AjaxResult sitMoveByGps(@RequestBody VideoServoDTO videoServoDTO) {
        String deviceCode = videoServoDTO.getDeviceCode();
        String gpsX = videoServoDTO.getGpsX();
        String gpsY = videoServoDTO.getGpsY();
        String mmsi = videoServoDTO.getTerminalCode();
        Object dynamicObj = redisTemplate.opsForValue().get("ais:" + mmsi);
        Object radarDynamicObj = redisTemplate.opsForValue().get("radar-mmsi:" + mmsi);
        DsDynamicLkdVO dynamicRadarVO = null;
        if (!Objects.isNull(dynamicObj)) {
            try {
                dynamicRadarVO = JSONObject.parseObject(dynamicObj.toString(), DsDynamicLkdVO.class);
            } catch (Exception e) {
                System.out.println("解析 redis 中的 AIS 信息[" + dynamicObj.toString() + "]报错：" + e.getMessage());
            }
        }
        if (!Objects.isNull(radarDynamicObj)) {
            DsDynamicLkdVO dynamicRadarTmp = null;
            try {
                dynamicRadarTmp = JSONObject.parseObject(radarDynamicObj.toString(), DsDynamicLkdVO.class);
            } catch (Exception e) {
                System.out.println("解析 redis 中的 Radar 信息[" + radarDynamicObj.toString() + "]报错：" + e.getMessage());
            }
            if (!Objects.isNull(dynamicRadarVO)) {
                Date gpsTime = dynamicRadarVO.getLocationTime();
                if (gpsTime.before(dynamicRadarTmp.getLocationTime())) {
                    dynamicRadarVO = dynamicRadarTmp;
                }
            } else {
                dynamicRadarVO = dynamicRadarTmp;
            }
        }
        if (!Objects.isNull(dynamicRadarVO)) {
            gpsX = dynamicRadarVO.getLongitude().toString();
            gpsY = dynamicRadarVO.getLatitude().toString();
        }
        return dsVideoService.sitMoveByGps(deviceCode, gpsX, gpsY);
    }

    @Log(title = "校准光电联动功能参数", businessType = BusinessType.QUERY)
    @ApiOperation("校准光电联动功能参数")
    @PostMapping("/correctLinkageParam")
    public AjaxResult correctLinkageParam(@RequestBody VideoServoDTO videoServoDTO) {
        String mmsi = videoServoDTO.getTerminalCode();
        String deviceCode = videoServoDTO.getDeviceCode();
        Object dynamicObj = redisTemplate.opsForValue().get("ais:" + mmsi);
        Object radarDynamicObj = redisTemplate.opsForValue().get("radar-mmsi:" + mmsi);
        DsDynamicLkdVO dynamicRadarVO = null;
        if (!Objects.isNull(dynamicObj)) {
            try {
                dynamicRadarVO = JSONObject.parseObject(dynamicObj.toString(), DsDynamicLkdVO.class);
            } catch (Exception e) {
                System.out.println("解析 redis 中的 AIS 信息[" + dynamicObj.toString() + "]报错：" + e.getMessage());
            }
        }
        if (!Objects.isNull(radarDynamicObj)) {
            DsDynamicLkdVO dynamicRadarTmp = null;
            try {
                dynamicRadarTmp = JSONObject.parseObject(radarDynamicObj.toString(), DsDynamicLkdVO.class);
            } catch (Exception e) {
                System.out.println("解析 redis 中的 Radar 信息[" + radarDynamicObj.toString() + "]报错：" + e.getMessage());
            }
            if (!Objects.isNull(dynamicRadarVO)) {
                Date gpsTime = dynamicRadarVO.getLocationTime();
                if (gpsTime.before(dynamicRadarTmp.getLocationTime())) {
                    dynamicRadarVO = dynamicRadarTmp;
                }
            } else {
                dynamicRadarVO = dynamicRadarTmp;
            }
        }
        if (Objects.isNull(dynamicRadarVO)) {
            return AjaxResult.error();
        }
        LambdaQueryWrapper<DsVideo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DsVideo::getVideoCode, deviceCode);
        queryWrapper.last(" limit 1");
        DsVideo dsVideo = dsVideoService.getOne(queryWrapper);
        if (Objects.isNull(dsVideo)) {
            return AjaxResult.error();
        }
        Object ptzObj = dsCameraService.hkGetPtzCfg(dsVideo.getVideoIp(), dsVideo.getVideoPort(), dsVideo.getVideoAccount(), dsVideo.getVideoPassword());
        if (Objects.isNull(ptzObj)) {
            return AjaxResult.error();
        }
        JSONObject ptzJSONObj = JSONObject.parseObject(JSONObject.toJSONString(ptzObj));
        System.out.println(JSONObject.toJSONString(ptzObj));
        float pVal = ptzJSONObj.getFloat("pValue");
        float tVal = ptzJSONObj.getFloat("tValue");
        float zVal = ptzJSONObj.getFloat("zValue");
        int rotateT = dsVideo.getRotateT();
        Double height = dsVideo.getHeight().doubleValue();
        double lon1 = dynamicRadarVO.getLongitude();
        double lat1 = dynamicRadarVO.getLatitude();
        double lon2 = dsVideo.getLongitude().doubleValue();
        double lat2 = dsVideo.getLatitude().doubleValue();
        String xValArr = dsVideo.getXValArr();
        String yValArr = dsVideo.getYValArr();
        String zNumValArr = dsVideo.getZNumValArr();

        BigDecimal degreeX = CameraDegreesUtil.rotateForNorthByLR(lon2, lat2, lon1, lat1, rotateT);
        double degreeXVal = degreeX.doubleValue() < 0 ? 360 + degreeX.doubleValue() : degreeX.doubleValue();
        degreeX = new BigDecimal(degreeXVal);
        BigDecimal degreeY = CameraDegreesUtil.rotateByUD(Objects.isNull(height) ? 0.2 : (height / 1000), lon2, lat2, lon1, lat1);
        BigDecimal distance = CameraDegreesUtil.getDistance(lon1, lat1, lon2, lat2).setScale(5, RoundingMode.HALF_UP);
        System.out.println("degreeX:" + degreeX + ",degreeY:" + degreeY + ",distance:" + distance);
        double xVal = new BigDecimal(pVal).subtract(degreeX).setScale(8, BigDecimal.ROUND_UP).doubleValue();
        double yVal = new BigDecimal(tVal).subtract(degreeY).setScale(8, BigDecimal.ROUND_UP).doubleValue();
        double zNumVal = new BigDecimal(zVal).divide(distance, 8, BigDecimal.ROUND_UP).doubleValue();
        JSONArray xValArray = null;
        if (StringUtils.isNotBlank(xValArr)) {
            xValArray = JSONArray.parseArray(xValArr);
        } else {
            xValArray = new JSONArray();
        }
        JSONObject xValArrItem = new JSONObject();
        xValArrItem.put("distance", degreeX.setScale(8, BigDecimal.ROUND_UP).doubleValue());
        xValArrItem.put("number", xVal);
        xValArray.add(xValArrItem);
        xValArr = JSONObject.toJSONString(xValArray);
        JSONArray yValArray = null;
        if (StringUtils.isNotBlank(yValArr)) {
            yValArray = JSONArray.parseArray(yValArr);
        } else {
            yValArray = new JSONArray();
        }
        JSONObject yValArrItem = new JSONObject();
        yValArrItem.put("distance", distance.setScale(8, BigDecimal.ROUND_UP).doubleValue());
        yValArrItem.put("number", yVal);
        yValArray.add(yValArrItem);
        yValArr = JSONObject.toJSONString(yValArray);
        JSONArray zNumValArray = null;
        if (StringUtils.isNotBlank(zNumValArr)) {
            zNumValArray = JSONArray.parseArray(zNumValArr);
        } else {
            zNumValArray = new JSONArray();
        }
        JSONObject zNumValItem = new JSONObject();
        zNumValItem.put("distance", distance.setScale(8, BigDecimal.ROUND_UP).doubleValue());
        zNumValItem.put("number", zNumVal);
        zNumValArray.add(zNumValItem);
        zNumValArr = JSONObject.toJSONString(zNumValArray);
        boolean result = dsVideoService.lambdaUpdate()
                .eq(DsVideo::getVideoIp, dsVideo.getVideoIp())
                .set(DsVideo::getXValArr, xValArr)
                .set(DsVideo::getYValArr, yValArr)
                .set(DsVideo::getZNumValArr, zNumValArr)
                .update();
        return AjaxResult.success(result);
    }

    /**
     * 光电联动查看监控设备列表
     *
     * @return 光电联动查看监控设备列表
     */
    @Log(title = "光电联动查看监控设备列表", businessType = BusinessType.QUERY)
    @ApiOperation("光电联动查看监控设备列表")
    @PostMapping("/getDevicesForServo")
    public AjaxResult getDevicesForServo(@RequestBody VideoServoDTO videoServoDTO) {
        String gpsX = videoServoDTO.getGpsX();
        String gpsY = videoServoDTO.getGpsY();
        Double gpsXVal = Double.parseDouble(gpsX);
        Double gpsYVal = Double.parseDouble(gpsY);
        yunVideoCodeList = updateYunVideoList();
        List<DsVideo> list = yunVideoCodeList.stream().map(v -> {
            double latitudeVal = v.getLatitude().doubleValue();
            double longitudeVal = v.getLongitude().doubleValue();
            BigDecimal distance = CameraDegreesUtil.getDistance(longitudeVal, latitudeVal, gpsXVal, gpsYVal).setScale(5, RoundingMode.HALF_UP);
            v.setDistance(distance);
            v.setDistance1(distance);
//            v.setDistanceVal(Objects.isNull(v.getVisionDistance()) ? 0 : distance.doubleValue() - v.getVisionDistance().doubleValue());
            if (StringUtils.isNotBlank(v.getXRotateVal())) {
                BigDecimal degreeX = CameraDegreesUtil.rotateForNorthByLR(longitudeVal, latitudeVal, gpsXVal, gpsYVal, v.getRotateT());
                double degreeXVal = degreeX.doubleValue();
                degreeXVal = degreeXVal < 0 ? 360 + degreeXVal : degreeXVal;
                double dxVal = degreeXVal;
                String xRotateVal = v.getXRotateVal();
                List<Boolean> flags = Arrays.asList(xRotateVal.split(";")).stream().map(item -> {
                    String itemStr1 = item.split("-")[0];
                    String itemStr2 = item.split("-")[1];
                    double itemVal1 = Double.parseDouble(itemStr1);
                    double itemVal2 = Double.parseDouble(itemStr2);
                    return itemVal1 < dxVal && itemVal2 > dxVal;
                }).collect(Collectors.toList());
                if (!flags.contains(true)) {
//                    return Response.fail("超出监控摄像头可视范围");
                    v.setDistance1(Objects.isNull(v.getDistance()) ? v.getDistance() : v.getDistance().add(new BigDecimal(999)));
                }
            }
            return v;
        }).sorted(Comparator.comparing(DsVideo::getDistance1)).collect(Collectors.toList());
        List<DsVideo> resultList = Lists.newArrayList();
        if (CollectionUtils.isEmpty(yunVideoCodeList)) {
            return AjaxResult.success(list);
        }
        for (int i = 0; i < list.size(); i++) {
            if (i < 5) {
                resultList.add(list.get(i));
            }
        }
        return success(resultList);
    }

    /**
     * 光电随动控制
     *
     * @return
     */
    @Log(title = "光电随动控制", businessType = BusinessType.QUERY)
    @ApiOperation("光电随动控制")
    @PostMapping("/servoByRadar")
    public AjaxResult servoByRadar(@RequestBody VideoServoDTO videoServoDTO) {
        Set<String> tempPatternKey = redisTemplate.keys("servo:*");
        String deviceCode = videoServoDTO.getDeviceCode();
        String terminalCode = videoServoDTO.getTerminalCode();
        if (!CollectionUtils.isEmpty(tempPatternKey)) {
            tempPatternKey.stream()
                    .forEach(m -> {
                        String deviceCodeTmp = redisTemplate.opsForValue().get(m).toString();
                        if (deviceCode.trim().equals(deviceCodeTmp)) {
                            redisTemplate.delete("servo:" + m);
                        }
                    });
        }
        String gpsX = videoServoDTO.getGpsX();
        String gpsY = videoServoDTO.getGpsY();
        Object dynamicObj = redisTemplate.opsForValue().get("ais:" + terminalCode);
        Object radarDynamicObj = redisTemplate.opsForValue().get("radar-mmsi:" + terminalCode);
        DsDynamicLkdVO dynamicRadarVO = null;
        if (!Objects.isNull(dynamicObj)) {
            try {
                dynamicRadarVO = JSONObject.parseObject(dynamicObj.toString(), DsDynamicLkdVO.class);
            } catch (Exception e) {
                System.out.println("解析 redis 中的 AIS 信息[" + dynamicObj.toString() + "]报错：" + e.getMessage());
            }
        }
        if (!Objects.isNull(radarDynamicObj)) {
            DsDynamicLkdVO dynamicRadarTmp = null;
            try {
                dynamicRadarTmp = JSONObject.parseObject(radarDynamicObj.toString(), DsDynamicLkdVO.class);
            } catch (Exception e) {
                System.out.println("解析 redis 中的 Radar 信息[" + radarDynamicObj.toString() + "]报错：" + e.getMessage());
            }
            if (!Objects.isNull(dynamicRadarVO)) {
                Date gpsTime = dynamicRadarVO.getLocationTime();
                if (gpsTime.before(dynamicRadarTmp.getLocationTime())) {
                    dynamicRadarVO = dynamicRadarTmp;
                }
            } else {
                dynamicRadarVO = dynamicRadarTmp;
            }
        }
        if (!Objects.isNull(dynamicRadarVO)) {
            gpsX = dynamicRadarVO.getLongitude().toString();
            gpsY = dynamicRadarVO.getLatitude().toString();
        }
        dsVideoService.sitMoveByGps(deviceCode, gpsX, gpsY);
        redisTemplate.opsForValue().set("servo:" + terminalCode, deviceCode, 30, TimeUnit.MINUTES);
        return success();
    }

    /**
     * 光电随动控制退出
     *
     * @return
     */
    @Log(title = "光电随动控制退出", businessType = BusinessType.QUERY)
    @ApiOperation("光电随动控制退出")
    @PostMapping("/servoByRadarExit")
    public AjaxResult servoByRadarExit(@RequestBody VideoServoDTO videoServoDTO) {
        String terminalCode = videoServoDTO.getTerminalCode();
        redisTemplate.delete("servo:" + terminalCode);
        return success();
    }

    /**
     * 大屏一张图 视频监控统计
     *
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2025/3/4
     */
    @ApiOperation("大屏一张图 视频监控统计")
    @PostMapping("/getVideoCount")
    public AjaxResult getVideoCount() {
        List<DsVideo> dsVideoList = dsVideoService.lambdaQuery()
                .eq(DsVideo::getDelFlag, 0)
                .list();

        VideoCountVO videoCount = new VideoCountVO()
                .setVideoCount(dsVideoList.size())
                .setVideoOnlineCount(dsVideoList.stream().filter(dsVideo -> "正常".equals(dsVideo.getRunStatus())).count())
                .setVideoOfflineCount(dsVideoList.stream().filter(dsVideo -> !("正常".equals(dsVideo.getRunStatus()))).count());

        return success(videoCount);
    }

    /**
     * 获取机场天气信息
     */
    @PostMapping("/getDockWeatherInfo")
    @Anonymous
    public AjaxResult getDockWeatherInfo() {
        LambdaQueryWrapper<UavWeather> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(UavWeather::getCreateAt);
        queryWrapper.last("limit 1");
        UavWeather uavWeather = uavWeatherService.getOne(queryWrapper);
        if (!Objects.isNull(uavWeather)) {
            return success(uavWeather);
        } else {
            return error("未查询到机场天气信息");
        }
    }


    /**
     * 摄像头锁定和解锁接口
     *
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2025/7/14
     */
    @PostMapping("/lockAndUnLock")
    public AjaxResult lockAndUnLock(@RequestBody DsVideo dsVideo) {
        DsVideo dbDsVideo = dsVideoService.lambdaQuery()
                .eq(DsVideo::getId, dsVideo.getId())
                .last("limit 1")
                .one();
        return toAjax(dsVideoService.lambdaUpdate()
                .eq(DsVideo::getVideoIp, dbDsVideo.getVideoIp())
                .set(DsVideo::getBeLock, dsVideo.getBeLock())
                .update());
    }

    /**
     * 根据海康安防平台获取摄像头在线状态
     *
     * @author Qi ChengBin
     * @date 2025/7/21
     */
    @Scheduled(cron = "0 0/10 * ? * *")
    public void updateVideoStatusByPointOnlineStatus() {
        dsVideoService.updateVideoStatusByPointOnlineStatus();
    }

    /**
     * 获取摄像头详细信息，并且获取摄像头相关的 PTZ
     *
     * @param dsVideo:
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2025/8/4
     */
    @PostMapping("/getVideoInfo")
    public AjaxResult getVideoInfo(@RequestBody DsVideo dsVideo) {
        return success(dsVideoService.getVideoInfo(dsVideo));
    }

    /**
     * 更新摄像头可视范围字段状态，并获取所有的开启了可视摄像头范围的相关数据
     *
     * @param dsVideo：需开启摄像头可视范围的相关摄像头数据
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2025/9/15
     */
    @PostMapping("/updateOneAndFindVideoInfoList")
    public AjaxResult updateOneAndFindVideoInfoList(@RequestBody DsVideo dsVideo) {
        return success(dsVideoService.updateOneAndFindVideoInfoList(dsVideo));
    }

    /**
     * 摄像头状态巡检日志
     *
     * @param req
     * @return {@link List<DsVideoLog>}
     */
    @PostMapping("/getVideoStatusLog")
    public TableDataInfo getVideoStatusLog(@RequestBody GetVideoStatusLogVo req) {
        return getDataTable(dsVideoLogService.getVideoStatusLog(req));
    }
}

