package com.cool.store.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
import com.cool.store.constants.RedisConstant;
import com.cool.store.dao.AssessmentDataDAO;
import com.cool.store.dto.SmallVideoDTO;
import com.cool.store.dto.SmallVideoInfoDTO;
import com.cool.store.entity.AssessmentDataDO;
import com.cool.store.enums.video.ResourceStatusEnum;
import com.cool.store.enums.video.UploadTypeEnum;
import com.cool.store.service.VodService;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.vod.CallbackRequest;
import com.cool.store.utils.vod.CallbackStreamInfo;
import com.cool.store.utils.vod.EventType;
import com.cool.store.utils.vod.SmallVideoParam;
import com.google.common.io.Files;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author byd
 * @date 2024-05-07 19:28
 */
@Slf4j
@Service
public class VodServiceImpl implements VodService {

    @Resource
    private RedisUtilPool redisUtilPool;

    @Resource
    private AssessmentDataDAO assessmentDataDAO;

    public static final Integer EXPIRE_TIME = 3600 * 72;


    @Override
    public void callback(CallbackRequest request) {
        log.info("CallbackRequest:{}", JSONObject.toJSONString(request));
        //未完成转码的视频
        String videoId = request.getVideoId();

        String eventType = request.getEventType();
        String newVideoInfo = "";
        String callbackCache = redisUtilPool.getString(RedisConstant.VIDEO_CALLBACK_CACHE + videoId);
        SmallVideoDTO smallVideoDTO;
        if (StringUtils.isNotBlank(callbackCache)) {
            smallVideoDTO = JSONObject.parseObject(callbackCache, SmallVideoDTO.class);
        } else {
            smallVideoDTO = new SmallVideoDTO();
        }
        log.info("smallVideoDTO:{}", JSONObject.toJSONString(smallVideoDTO));
        smallVideoDTO.setSize(request.getSize());
        smallVideoDTO.setVideoId(videoId);
        switch (eventType) {
            //视频上传完成
            case EventType.FileUploadComplete:
                smallVideoDTO.setStatus(ResourceStatusEnum.TRANSCODING.getValue());
                smallVideoDTO.setVideoUrlBefore(request.getFileUrl());
                log.info("视频原始地址：{}", request.getFileUrl());
                //mp4不转码处理
                if (Files.getFileExtension(request.getFileUrl()).equalsIgnoreCase(CommonConstants.TRANSCODE_VIDEO)) {
                    if (CommonConstants.SUCCESS_STR.equalsIgnoreCase(request.getStatus())) {
                        smallVideoDTO.setVideoUrl(request.getFileUrl());
                    } else {
                        smallVideoDTO.setStatus(ResourceStatusEnum.TRANSCODE_FAILED.getValue());
                    }
                }
                smallVideoDTO.setUploadStatus(true);
                newVideoInfo = JSONObject.toJSONString(smallVideoDTO);
                //过期时间为一周
                redisUtilPool.setString(RedisConstant.VIDEO_CALLBACK_CACHE + videoId, newVideoInfo, EXPIRE_TIME);
                break;
            //视频截图完成
            case EventType.SnapshotComplete:
                // 视频截图完成，且课件状态在转码完成之前时，更新状态为截图完成
                if (smallVideoDTO.getStatus() == null || smallVideoDTO.getStatus() < ResourceStatusEnum.TRANSCODE_FINISH.getValue()) {
                    smallVideoDTO.setStatus(ResourceStatusEnum.SCREENSHOT_FINISHED.getValue());
                }
                //视频封面
                smallVideoDTO.setVideoSnapshot(request.getCoverUrl());

                //如果上传的就是mp4，就不进行转码，截图完成就把状态改为转码完成
                if (StringUtils.isNotBlank(smallVideoDTO.getVideoUrlBefore())
                        && Files.getFileExtension(smallVideoDTO.getVideoUrlBefore()).equalsIgnoreCase(CommonConstants.TRANSCODE_VIDEO)
                        && !smallVideoDTO.getStatus().equals(ResourceStatusEnum.TRANSCODE_FAILED.getValue())) {

                    smallVideoDTO.setStatus(ResourceStatusEnum.TRANSCODE_FINISH.getValue());
                    smallVideoDTO.setTransCodeStatus(true);
                }
                smallVideoDTO.setSnapShotStatus(true);
                newVideoInfo = JSONObject.toJSONString(smallVideoDTO);

                //过期时间为一周
                redisUtilPool.setString(RedisConstant.VIDEO_CALLBACK_CACHE + videoId, newVideoInfo, EXPIRE_TIME);
                break;
            //视频全部清晰度转码完成
            case EventType.TranscodeComplete:
                if (CommonConstants.SUCCESS_STR.equalsIgnoreCase(request.getStatus())) {
                    smallVideoDTO.setTransCodeStatus(true);
                    smallVideoDTO.setStatus(ResourceStatusEnum.TRANSCODE_FINISH.getValue());
                    List<CallbackStreamInfo> streamInfoList = request.getStreamInfos();
                    for (CallbackStreamInfo streamInfo : streamInfoList) {
                        log.info("VodService callback playInfo.getFormat:{}", streamInfo.getFormat());
                        if (Objects.nonNull(smallVideoDTO.getStatus()) && smallVideoDTO.getStatus().intValue() != ResourceStatusEnum.TRANSCODE_FAILED.getValue()) {
                            smallVideoDTO.setVideoUrl(streamInfo.getFileUrl());
                        }
                    }
                } else {
                    smallVideoDTO.setStatus(ResourceStatusEnum.TRANSCODE_FAILED.getValue());
                }

                log.info("视频转码完成,videoId:{}", videoId);
                newVideoInfo = JSONObject.toJSONString(smallVideoDTO);
                //过期时间为一周
                redisUtilPool.setString(RedisConstant.VIDEO_CALLBACK_CACHE + videoId, newVideoInfo, EXPIRE_TIME);
                break;
            default:
        }
        log.info("videoId:{}，转码状态:{}", videoId, smallVideoDTO.getStatus());
        //未完成转码处理
        notCompleteCacheHandle(smallVideoDTO, videoId);
    }

    /**
     * 如果前端提交的时候，视频还没有转码成功，会把videoId存入缓存，回调的时候再进行处理
     *
     * @param smallVideoDTO
     * @param videoId
     * @return void
     * @author chenyupeng
     * @date 2021/10/14
     */
    public void notCompleteCacheHandle(SmallVideoDTO smallVideoDTO, String videoId) {
        log.info("videoId:{}, smallVideoDTO:{}", videoId, JSONObject.toJSONString(smallVideoDTO));
        //回调事件都完成才入库
        if (!(smallVideoDTO.isUploadStatus() && smallVideoDTO.isSnapShotStatus() && smallVideoDTO.isTransCodeStatus())) {
            log.info("回调事件都完成才入库videoId:{}", videoId);
            return;
        }
        String notCompleteCache = redisUtilPool.hashGet(RedisConstant.VIDEO_NOT_COMPLETE_CACHE, videoId);
        log.info("notCompleteCache:{}", notCompleteCache);
        if (StringUtils.isNotBlank(notCompleteCache)) {
            if (StringUtils.isNotBlank(smallVideoDTO.getVideoUrl())) {
                smallVideoDTO.setVideoUrl(smallVideoDTO.getVideoUrl().replace("http://", "https://"));
            }

            if (StringUtils.isNotBlank(smallVideoDTO.getVideoUrlBefore())) {
                smallVideoDTO.setVideoUrlBefore(smallVideoDTO.getVideoUrlBefore().replace("http://", "https://"));
            }
            SmallVideoParam smallVideoParam = JSONObject.parseObject(notCompleteCache, SmallVideoParam.class);
            if (UploadTypeEnum.ASSESSMENT_DATA_CONTENT.getValue().equals(smallVideoParam.getUploadType())) {
                //检查项提交
                dealVideo(smallVideoDTO, smallVideoParam);
                //保存完删除缓存
                redisUtilPool.hashDel(RedisConstant.VIDEO_NOT_COMPLETE_CACHE, videoId);
            }
        }
    }

    public void dealVideo(SmallVideoDTO smallVideoDTO, SmallVideoParam smallVideoParam) {

        AssessmentDataDO assessmentDataDO = assessmentDataDAO.selectByPrimaryKey(smallVideoParam.getBusinessId());

        log.info("视频信息,checkVideo:{}", assessmentDataDO.getVideo());
        assessmentDataDO.setVideo(transSmallVideoDTO(assessmentDataDO.getVideo(), smallVideoDTO));
        assessmentDataDAO.updateByPrimaryKeySelective(assessmentDataDO);
    }

    public static String transSmallVideoDTO(String videoInfo, SmallVideoDTO smallVideoDto) {

        log.info("transSmallVideoDTO,videoInfo:{},smallVideoDto:{}", videoInfo, smallVideoDto.toString());
        SmallVideoInfoDTO smallVideoInfoDTO = JSONObject.parseObject(videoInfo, SmallVideoInfoDTO.class);
        if (smallVideoInfoDTO == null) {
            smallVideoInfoDTO = new SmallVideoInfoDTO();
        }
        if (CollectionUtils.isEmpty(smallVideoInfoDTO.getVideoList())) {
            smallVideoInfoDTO.setVideoList(Collections.singletonList(smallVideoDto));
            return JSONObject.toJSONString(smallVideoInfoDTO);
        }
        for (SmallVideoDTO smallVideo : smallVideoInfoDTO.getVideoList()) {
            if (smallVideo.getVideoId() == null || StringUtils.equals(smallVideo.getVideoId(), smallVideoDto.getVideoId())) {
                BeanUtils.copyProperties(smallVideoDto, smallVideo);
            }
        }
        return JSONObject.toJSONString(smallVideoInfoDTO);
    }
}

