package com.ningdatech.carapi.open.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.exception.code.ExceptionCode;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.cache.redis.RedisOps;
import com.ningdatech.carapi.open.aop.TaskLock;
import com.ningdatech.carapi.open.contants.AlarmContant;
import com.ningdatech.carapi.open.model.dto.AlarmDataPictureDTO;
import com.ningdatech.carapi.open.model.dto.AlarmDataVideoDTO;
import com.ningdatech.carapi.safe.entity.AlarmDataPicture;
import com.ningdatech.carapi.safe.entity.AlarmDataVideo;
import com.ningdatech.carapi.safe.service.IAlarmDataPictureService;
import com.ningdatech.carapi.safe.service.IAlarmDataVideoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Classname AlarmDataManage
 * @Description
 * @Date 2022/10/28 11:05
 * @Created by PoffyZhang
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class AlarmDataManage {
    private final IAlarmDataPictureService alarmDataPictureService;
    private final IAlarmDataVideoService alarmDataVideoService;

    private static final Long MAX_CACHE = 1000L;

    private final RedisOps redisOps;

    public Boolean savePicture(AlarmDataPictureDTO alarmDataPicture) {
        if(Objects.isNull(alarmDataPicture)){
            throw new BizException(ExceptionCode.PARAM_EX.getCode(),"推送数据为空");
        }

        AlarmDataPicture entity = BeanUtil.copyProperties(alarmDataPicture, AlarmDataPicture.class);

        //当前如果大于1000 则先去批量插入
        if(MAX_CACHE <= redisOps.lLen(AlarmContant.ALARM_DATA_PRICTURE_KEY)){
            AlarmDataManage clazz = (AlarmDataManage) AopContext.currentProxy();
            clazz.savePicturesOver();
        }

        redisOps.rPush(AlarmContant.ALARM_DATA_PRICTURE_KEY,entity);

        return Boolean.TRUE;
    }

    public Boolean saveVideo(AlarmDataVideoDTO alarmDataVideo) {
        if(Objects.isNull(alarmDataVideo)){
            throw new BizException(ExceptionCode.PARAM_EX.getCode(),"推送数据为空");
        }

        AlarmDataVideo entity= BeanUtil.copyProperties(alarmDataVideo, AlarmDataVideo.class);

        //当前如果大于1000 则先去批量插入
        if(MAX_CACHE <= redisOps.lLen(AlarmContant.ALARM_DATA_VIDEO_KEY)){
            AlarmDataManage clazz = (AlarmDataManage) AopContext.currentProxy();
            clazz.saveVideoOver();
        }

        redisOps.rPush(AlarmContant.ALARM_DATA_VIDEO_KEY,entity);

        return Boolean.TRUE;
    }

    @TaskLock(name = "批量插入图片锁", key = "alarm-data:picture_lock",expired = 5)
    public void savePicturesOver() {
        Long len = redisOps.lLen(AlarmContant.ALARM_DATA_PRICTURE_KEY);
        List<Object> objects = redisOps.lRange(AlarmContant.ALARM_DATA_PRICTURE_KEY, 0, len);
        List<AlarmDataPicture> addList = Objects.nonNull(objects) ? objects.stream().filter(Objects::nonNull)
                .map(AlarmDataPicture.class::cast)
                .collect(Collectors.toList()) : Collections.emptyList();

        if (CollUtil.isEmpty(addList)) {
            log.info("暂无 告警数据 需要插入!");
            return;
        }

        if(alarmDataPictureService.saveBatchForSql(addList)){
            //清理掉这部分缓存 不直接删除 怕有并发问题
            redisOps.lTrim( AlarmContant.ALARM_DATA_PRICTURE_KEY,len,-1);
        }
    }

    @TaskLock(name = "批量插入短视频锁", key = "alarm-data:video_lock",expired = 5)
    public void saveVideoOver() {
        //当缓存不为空
        if(0 >= redisOps.lLen(AlarmContant.ALARM_DATA_VIDEO_KEY)){
            return;
        }

        Long len = redisOps.lLen(AlarmContant.ALARM_DATA_VIDEO_KEY);
        List<Object> objects = redisOps.lRange(AlarmContant.ALARM_DATA_VIDEO_KEY, 0, len);
        List<AlarmDataVideo> addList = Objects.nonNull(objects) ? objects.stream().filter(Objects::nonNull)
                .map(AlarmDataVideo.class::cast)
                .collect(Collectors.toList()) : Collections.emptyList();

        if (CollUtil.isEmpty(addList)) {
            log.info("暂无 告警数据 需要插入!");
            return;
        }

        if(alarmDataVideoService.saveBatchForSql(addList)){
            //清理掉这部分缓存 不直接删除 怕有并发问题
            redisOps.lTrim( AlarmContant.ALARM_DATA_PRICTURE_KEY,len,-1);
        }
    }
}
