package com.ycwl.basic.repository;

import com.alibaba.fastjson.JSON;
import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.model.pc.video.entity.MemberVideoEntity;
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
import com.ycwl.basic.model.pc.video.resp.VideoRespVO;
import com.ycwl.basic.model.task.req.VideoInfoReq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

@Component
public class VideoRepository {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private VideoMapper videoMapper;

    public static final String VIDEO_CACHE_KEY = "video:%s";
    public static final String VIDEO_BY_TASK_ID_CACHE_KEY = "video:task:%s";

    public VideoEntity getVideo(Long videoId) {
        if (redisTemplate.hasKey(String.format(VIDEO_CACHE_KEY, videoId))) {
            return JSON.parseObject(redisTemplate.opsForValue().get(String.format(VIDEO_CACHE_KEY, videoId)), VideoEntity.class);
        }
        VideoEntity video = videoMapper.getEntity(videoId);
        if (video != null) {
            redisTemplate.opsForValue().set(String.format(VIDEO_CACHE_KEY, videoId), JSON.toJSONString(video));
            redisTemplate.opsForValue().set(String.format(VIDEO_BY_TASK_ID_CACHE_KEY, video.getTaskId()), JSON.toJSONString(video));
        }
        return video;
    }

    public VideoEntity getVideoByTaskId(Long taskId) {
        if (redisTemplate.hasKey(String.format(VIDEO_BY_TASK_ID_CACHE_KEY, taskId))) {
            return JSON.parseObject(redisTemplate.opsForValue().get(String.format(VIDEO_BY_TASK_ID_CACHE_KEY, taskId)), VideoEntity.class);
        }
        VideoEntity video = videoMapper.findByTaskId(taskId);
        if (video != null) {
            redisTemplate.opsForValue().set(String.format(VIDEO_BY_TASK_ID_CACHE_KEY, taskId), JSON.toJSONString(video));
            redisTemplate.opsForValue().set(String.format(VIDEO_CACHE_KEY, video.getId()), JSON.toJSONString(video));
        }
        return video;
    }

    public void updateMeta(Long videoId, VideoInfoReq req) {
        VideoRespVO video = videoMapper.getById(videoId);
        if (video.getDuration() != null) {
            if (video.getDuration().subtract(req.getDuration()).abs().compareTo(BigDecimal.ONE) <= 0) {
                return;
            }
        }
        VideoEntity update = new VideoEntity();
        update.setId(videoId);
        update.setHeight(req.getHeight());
        update.setWidth(req.getWidth());
        update.setDuration(req.getDuration());
        videoMapper.updateMeta(update);
        clearVideoCache(videoId);
    }

    public void setUserIsBuyItem(Long memberId, Long videoId, Long orderId) {
        MemberVideoEntity memberVideo = new MemberVideoEntity();
        memberVideo.setVideoId(videoId);
        memberVideo.setMemberId(memberId);
        memberVideo.setIsBuy(1);
        memberVideo.setOrderId(orderId);
        videoMapper.updateRelation(memberVideo);
    }

    public void setUserNotBuyItem(Long memberId, Long videoId) {
        MemberVideoEntity memberVideo = new MemberVideoEntity();
        memberVideo.setVideoId(videoId);
        memberVideo.setMemberId(memberId);
        memberVideo.setIsBuy(0);
        memberVideo.setOrderId(null);
        videoMapper.updateRelation(memberVideo);
    }

    public boolean getUserIsBuy(Long userId, Long videoId) {
        MemberVideoEntity memberVideo = videoMapper.queryUserVideo(userId, videoId);
        if (memberVideo == null) {
            return false;
        }
        return Integer.valueOf(1).equals(memberVideo.getIsBuy());
    }

    public boolean clearVideoCache(Long videoId) {
        if (redisTemplate.hasKey(String.format(VIDEO_CACHE_KEY, videoId))) {
            VideoEntity video = getVideo(videoId);
            redisTemplate.delete(String.format(VIDEO_CACHE_KEY, videoId));
            redisTemplate.delete(String.format(VIDEO_BY_TASK_ID_CACHE_KEY, video.getTaskId()));
        }
        return true;
    }
}
