package cn.reghao.oss.store.task;

import cn.reghao.jutil.jdk.security.DigestUtil;
import cn.reghao.oss.storeapi.dto.ObjectMeta;
import cn.reghao.oss.store.db.repository.ObjectRepository;
import cn.reghao.oss.store.model.vo.ObjectProp;
import cn.reghao.oss.store.service.FileStoreService;
import cn.reghao.oss.store.service.PutObjectService;
import cn.reghao.jutil.media.model.AudioProps;
import cn.reghao.jutil.media.model.MediaProps;
import cn.reghao.jutil.media.model.VideoProps;
import cn.reghao.oss.store.model.vo.ObjectResult;
import cn.reghao.oss.store.util.FileType;
import cn.reghao.oss.store.service.ObjectNameService;
import cn.reghao.jutil.media.FFmpegWrapper;
import cn.reghao.jutil.media.MediaQuality;
import cn.reghao.jutil.media.MediaResolution;
import cn.reghao.oss.storeapi.rest.UploadFileRet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author reghao
 * @date 2023-01-11 10:40:17
 */
@Slf4j
@Service
public class VideoFileProcessor {
    private final ObjectNameService objectNameService;
    private final PutObjectService putObjectService;
    private final ObjectRepository objectRepository;
    private final FileStoreService fileStoreService;

    public VideoFileProcessor(ObjectNameService objectNameService, PutObjectService putObjectService,
                              ObjectRepository objectRepository, FileStoreService fileStoreService) {
        this.objectNameService = objectNameService;
        this.putObjectService = putObjectService;
        this.objectRepository = objectRepository;
        this.fileStoreService = fileStoreService;
    }

    public UploadFileRet process(ObjectResult objectResult) throws Exception {
        String objectName = objectResult.getObjectName();
        String objectId = objectResult.getObjectId();
        String videoFileId = objectId;
        String objectUrl = objectNameService.getObjectUrl(objectName);
        boolean duplicate = objectResult.isDuplicate();
        if (duplicate) {
            String dupObjectId = objectResult.getDupObjectId();
            //List<VideoFile> videoFiles = videoRepository.getVideoFiles(dupObjectId);
            List<VideoFile> videoFiles = new ArrayList<>();
            VideoFile videoFile = videoFiles.get(0);
            VideoFile videoFile1 = new VideoFile(videoFileId, objectId, objectUrl, videoFile);
            List<VideoFile> list = new ArrayList<>();
            list.add(videoFile1);

            if (videoFiles.size() > 1) {
                for (int i = 1; i < videoFiles.size(); i++) {
                    VideoFile videoFile2 = videoFiles.get(i);
                    ObjectResult objectResult1 = putObjectService.copyFromObjectId(videoFile2.getObjectId());
                    String objectId1 = objectResult1.getObjectId();
                    String objectUrl1 = objectNameService.getObjectUrl(objectResult1.getObjectName());
                    list.add(new VideoFile(videoFileId, objectId1, objectUrl1, videoFile2));
                }
            }

            //videoRepository.saveVideoFiles(list);
            return new UploadFileRet(videoFileId, null);
        }

        String absolutePath = objectResult.getAbsolutePath();
        MediaProps mediaProps = FFmpegWrapper.getMediaProps(absolutePath);
        if (mediaProps == null) {
            String errMsg = String.format("%s 的 FFmpeg 媒体信息为 null", objectName);
            throw new Exception(errMsg);
        }

        VideoProps videoProps = mediaProps.getVideoProps();
        if (videoProps == null) {
            String errMsg = String.format("%s 的 FFmpeg 视频信息为 null", objectName);
            throw new Exception(errMsg);
        }

        String videoCodec = videoProps.getCodecName();
        long vbitRate = videoProps.getBitRate();

        String audioCodec = null;
        long abitRate = 0;
        AudioProps audioProps1 = mediaProps.getAudioProps();
        if (audioProps1 != null) {
            audioCodec = audioProps1.getCodecName();
            abitRate = audioProps1.getBitRate();
        }

        /*if (videoCodecs.contains(videoCodec)) {
            AudioProps audioProps = mediaProps.getAudioProps();
            if (audioProps != null && !audioCodecs.contains(audioProps.getCodecName())) {
                log.error("{} 对象的音频非 aac&mp3 编码, 暂不处理", objectName);
                return null;
            }
        } else {
            log.error("{} 对象的视频非 h264 编码, 暂不处理", objectName);
            return null;
        }*/
        int width = videoProps.getCodedWidth().intValue();
        int height = videoProps.getCodedHeight().intValue();
        int duration = videoProps.getDuration().intValue();
        MediaResolution mediaResolution = MediaQuality.getQuality(width, height);
        String quality = mediaResolution.getQualityStr();
        String urlType = FileType.getVideoUrlType(absolutePath);
        VideoFile videoFile = new VideoFile(videoFileId, objectId, videoCodec, vbitRate, audioCodec, abitRate,
                urlType, objectUrl, quality, width, height, duration);
        //videoRepository.saveVideoFiles(List.of(videoFile));
        return new UploadFileRet(videoFileId, null);
    }

    class ConvertVideoTask implements Runnable {
        private final VideoFile videoFile;

        public ConvertVideoTask(VideoFile videoFile) {
            this.videoFile = videoFile;
        }

        public void run() {
            String videoFileId = videoFile.getVideoFileId();
            log.info("convert video file {}", videoFileId);
            int width = videoFile.getWidth();
            int height = videoFile.getHeight();

            ObjectMeta objectMeta = objectRepository.getObjectMetaById(videoFileId);
            String originalObjectName = objectMeta.getObjectName();
            String srcPath = objectMeta.getAbsolutePath();
            File srcFile = new File(srcPath);

            String contentId = UUID.randomUUID().toString().replace("-", "");
            String suffix = ".mp4";
            String destPath = fileStoreService.genFilePath(contentId, srcFile.length(), suffix);
            try {
                File savedFile = new File(destPath);
                if (savedFile.exists()) {
                    throw new IOException(destPath + " exist");
                }

                String format = suffix.replace(".", "");
                int ret = FFmpegWrapper.formatCovert(srcFile.getAbsolutePath(), destPath, format);
                if (ret != 0) {
                    throw new Exception("视频转码失败");
                }
                String sha256sum = DigestUtil.sha256sum(destPath);

                ObjectProp objectProp = objectNameService.getObjectProp(originalObjectName, suffix);
                String originalFilename = "converted_video";
                ObjectResult objectResult = putObjectService.putObject(objectProp, contentId, savedFile, originalFilename, sha256sum);

                String objectId = objectResult.getObjectId();
                String url = objectNameService.getObjectUrl(objectResult.getObjectName());
                String urlType = FileType.getVideoUrlType(destPath);

                MediaProps mediaProps = FFmpegWrapper.getMediaProps(destPath);
                if (mediaProps == null) {
                    log.error("{} 的 FFmpeg 媒体信息为 null", destPath);
                    return;
                }

                VideoProps videoProps = mediaProps.getVideoProps();
                if (videoProps == null) {
                    log.error("{} 的 FFmpeg 视频信息为 null", destPath);
                    return;
                }

                String videoCodec = videoProps.getCodecName();
                long vbitRate = videoProps.getBitRate();

                String audioCodec = null;
                long abitRate = 0;
                AudioProps audioProps1 = mediaProps.getAudioProps();
                if (audioProps1 != null) {
                    audioCodec = audioProps1.getCodecName();
                    abitRate = audioProps1.getBitRate();
                }

                int duration = videoFile.getDuration();
                MediaResolution mediaResolution = MediaQuality.getQuality(width, height);
                String quality = mediaResolution.getQualityStr();
                VideoFile videoFile1 = new VideoFile(videoFileId, objectId, videoCodec, vbitRate, audioCodec, abitRate,
                        urlType, url, quality, width, height, duration);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
