package com.ltgk.video.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ltgk.common.utils.StringUtils;
import com.ltgk.common.utils.bean.BeanUtils;
import com.ltgk.video.domain.dto.VideoIdentificationDTO;
import com.ltgk.video.domain.entity.DsVideo;
import com.ltgk.video.domain.entity.VideoIdentification;
import com.ltgk.video.mapper.VideoIdentificationMapper;
import com.ltgk.video.service.IDsVideoService;
import com.ltgk.video.service.IVideoIdentificationService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ltgk.common.utils.PageUtils.startPage;

/**
 * 监控识别记录表 (VideoIdentification)实现层
 *
 * @author Qi ChengBin
 * @date 2025-02-20
 */
@Service
public class VideoIdentificationServiceImpl extends ServiceImpl<VideoIdentificationMapper, VideoIdentification> implements IVideoIdentificationService {

    @Resource
    private IDsVideoService dsVideoService;

    /**
     * 分页查询监控识别信息
     *
     * @param dto: 监控识别记录表数据传输对象
     * @return java.util.List<com.ltgk.video.domain.entity.VideoIdentification>
     * @author Qi ChengBin
     * @date 2025/2/20
     */
    @Override
    public List<VideoIdentification> findVideoIdentificationByPage(VideoIdentificationDTO dto) {
        int pageNum = dto.getPageNum();
        int pageSize = dto.getPageSize();
        dto.queryCheck();
        VideoIdentification videoIdentification = new VideoIdentification();
        BeanUtils.copyProperties(dto, videoIdentification);

        LambdaQueryWrapper<VideoIdentification> wrapper = new LambdaQueryWrapper<>(videoIdentification);

        // 为空时 则是不传时间;;;
        boolean beginTimeAndEndTimeNotBlank = StringUtils.isNotBlank(dto.getStartTime()) && StringUtils.isNotBlank(dto.getEndTime());

        if (Objects.nonNull(dto.getIdentifyType())) {
            wrapper.ne(dto.getIdentifyType().equals(0), VideoIdentification::getBoatName, "未检测到船名")
                    .eq(dto.getIdentifyType().equals(1), VideoIdentification::getBoatName, "未检测到船名");
        }
        if (StringUtils.isBlank(dto.getIdentificationType())) {
            wrapper.ne(VideoIdentification::getIdentificationType, "烟火事件");
        }
        wrapper.between(beginTimeAndEndTimeNotBlank, VideoIdentification::getTakeTime, dto.getStartTime(), dto.getEndTime())
                .orderByDesc(VideoIdentification::getTakeTime);

        startPage(pageNum, pageSize);
        return this.list(wrapper);
    }

    /**
     * 分页查询烟火事件信息
     *
     * @param dto: 分页查询烟火事件信息
     * @return java.util.List<com.ltgk.video.domain.entity.VideoIdentification>
     * @author Qi ChengBin
     * @date 2025/2/20
     */
    @Override
    public List<VideoIdentification> findFirePage(VideoIdentificationDTO dto) {
        dto.queryCheck();
        dto.setIdentificationType("烟火事件");

        List<DsVideo> dsVideoList = dsVideoService.lambdaQuery()
                .like(StringUtils.isNotBlank(dto.getVideoName()), DsVideo::getVideoName, dto.getVideoName())
                .list();

        List<String> videoIpList = dsVideoList.stream()
                .map(DsVideo::getVideoIp)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(videoIpList)) {
            return Collections.emptyList();
        }

        // 将 视频列表转换成map， ip 相同的情况下 value 的获取规则见方法注释
        Map<String, DsVideo> videoMap = dsVideoList.stream()
                .collect(Collectors.toMap(DsVideo::getVideoIp, Function.identity(), this::selectDsVideoByVideoName));

        dto.setVideoName(null);

        int pageNum = dto.getPageNum();
        int pageSize = dto.getPageSize();
        VideoIdentification videoIdentification = new VideoIdentification();
        BeanUtils.copyProperties(dto, videoIdentification);

        // 为空时 则是不传时间;;;
        boolean beginTimeAndEndTimeNotBlank = StringUtils.isNotBlank(dto.getStartTime()) && StringUtils.isNotBlank(dto.getEndTime());

        LambdaQueryWrapper<VideoIdentification> wrapper = new LambdaQueryWrapper<>(videoIdentification);
        wrapper.in(VideoIdentification::getVideoIp, videoIpList)
                .between(beginTimeAndEndTimeNotBlank, VideoIdentification::getTakeTime, dto.getStartTime(), dto.getEndTime())
                .orderByDesc(VideoIdentification::getTakeTime);

        startPage(pageNum, pageSize);
        List<VideoIdentification> videoIdentificationList = this.list(wrapper);

        videoIdentificationList.forEach(item -> {
            if (StringUtils.isNotBlank(item.getVideoIp()) && videoMap.containsKey(item.getVideoIp())) {
                item.setVideoName(videoMap.get(item.getVideoIp()).getVideoName());
            }
            item.setPictureUrl(
                    Arrays.stream(item.getPictureUrl().split(","))
                            .map(url -> "http://39.175.75.233:6803/" + url)
                            .collect(Collectors.joining(",")));
        });
        return videoIdentificationList;
    }

    /**
     * 在相同的videoIp 下选择一条 dsVideo的数据
     * -- 在相同的videoIp 下，
     * -- 优先选择名称中有 可见光的数据；
     * -- 如果多条数据都有可见光，则随机选择一条；
     * -- 如果多条数据都没有，则随机选择一条；
     * -- 否则选择有可见光的数据
     *
     * @param item1:
     * @param item2  :
     * @return com.ltgk.video.domain.entity.DsVideo
     * @author Qi ChengBin
     * @date 2025/4/16
     */
    private DsVideo selectDsVideoByVideoName(DsVideo item1, DsVideo item2) {
        boolean containsVisibleLight1 = item1.getVideoName().contains("可见光");
        boolean containsVisibleLight2 = item2.getVideoName().contains("可见光");
        if (containsVisibleLight1 && !containsVisibleLight2) {
            return new Random().nextBoolean() ? item1 : item2;
        } else if (containsVisibleLight1) {
            return item1;
        } else if (containsVisibleLight2) {
            return item2;
        } else {
            return new Random().nextBoolean() ? item1 : item2;
        }
    }

    /**
     * 分页查询卡口抓拍记录数据
     *
     * @param dto:
     * @return com.ltgk.common.core.page.TableDataInfo
     * @author Qi ChengBin
     * @date 2025/4/2
     */
    @Override
    public List<VideoIdentification> findBayonetVideoIdentificationList(VideoIdentificationDTO dto) {
        // 查询所有的 卡口抓拍的摄像头 的 ip 地址
        List<String> dsVideoIpList = dsVideoService.lambdaQuery()
                .eq(DsVideo::getBeBayonet, 1)
                .list()
                .stream()
                .map(DsVideo::getVideoIp)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(dsVideoIpList)) {
            return Collections.emptyList();
        }

        int pageNum = dto.getPageNum();
        int pageSize = dto.getPageSize();
        dto.queryCheck();
        VideoIdentification videoIdentification = new VideoIdentification();
        BeanUtils.copyProperties(dto, videoIdentification);

        LambdaQueryWrapper<VideoIdentification> wrapper = new LambdaQueryWrapper<>(videoIdentification);
        // 为空时 则是不传时间;;;
        boolean beginTimeAndEndTimeNotBlank = StringUtils.isNotBlank(dto.getStartTime()) && StringUtils.isNotBlank(dto.getEndTime());

        if (Objects.nonNull(dto.getIdentifyType())) {
            wrapper.ne(dto.getIdentifyType().equals(0), VideoIdentification::getBoatName, "未检测到船名")
                    .eq(dto.getIdentifyType().equals(1), VideoIdentification::getBoatName, "未检测到船名");
        }
        wrapper
                .ne(VideoIdentification::getIdentificationType, "烟火事件")
                .in(VideoIdentification::getVideoIp, dsVideoIpList)
                .between(beginTimeAndEndTimeNotBlank, VideoIdentification::getTakeTime, dto.getStartTime(), dto.getEndTime())
                .orderByDesc(VideoIdentification::getTakeTime);

        startPage(pageNum, pageSize);
        return this.list(wrapper);
    }
}

