package cn.reghao.oss.store.task;

import cn.reghao.jutil.media.FFmpegWrapper;
import cn.reghao.jutil.media.ImageOps;
import cn.reghao.jutil.media.MediaQuality;
import cn.reghao.jutil.media.MediaResolution;
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.storeapi.dto.ObjectMeta;
import cn.reghao.oss.storeapi.dto.media.AudioInfo;
import cn.reghao.oss.storeapi.dto.media.ConvertedImageInfo;
import cn.reghao.oss.storeapi.dto.media.ImageInfo;
import cn.reghao.oss.storeapi.dto.media.VideoInfo;
import cn.reghao.oss.store.db.repository.ObjectRepository;
import cn.reghao.oss.store.model.vo.ObjectResult;
import cn.reghao.oss.store.service.FileStoreService;
import cn.reghao.oss.store.service.ObjectNameService;
import cn.reghao.oss.store.service.PutObjectService;
import cn.reghao.oss.store.util.FileType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

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

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

    public VideoInfo getVideoInfo(String videoFileId) throws Exception {
        ObjectMeta objectMeta = objectRepository.getObjectMetaById(videoFileId);
        if (objectMeta == null) {
            return null;
        }

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

        VideoProps videoProps = mediaProps.getVideoProps();
        if (videoProps == null) {
            String errMsg = String.format("%s 的 FFmpeg 视频信息为 null", videoFileId);
            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();
        }

        String objectId = videoFileId;
        String objectName = objectMeta.getObjectName();
        String objectUrl = objectNameService.getObjectUrl(objectName);
        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);
        LocalDateTime createTime = mediaProps.getCreateTime();

        return new VideoInfo(videoFileId, objectId, videoCodec, vbitRate, audioCodec, abitRate,
                urlType, objectUrl, quality, width, height, duration, createTime);
    }

    public ImageInfo getImageInfo(String imageFileId) throws Exception {
        ObjectMeta objectMeta = objectRepository.getObjectMetaById(imageFileId);
        if (objectMeta == null) {
            return null;
        }

        String absolutePath = objectMeta.getAbsolutePath();
        File file = new File(absolutePath);
        String format = ImageOps.getFormat(file);
        ImageOps.Size size = ImageOps.info(new File(absolutePath));
        int width = size.getWidth();
        int height = size.getHeight();
        String objectId = imageFileId;
        String objectName = objectMeta.getObjectName();
        String objectUrl = objectNameService.getObjectUrl(objectName);

        ImageInfo imageInfo = new ImageInfo(imageFileId, objectId, format, objectUrl, width, height);
        return imageInfo;
    }

    public List<ConvertedImageInfo> getWebpInfos(List<String> imageFileIds) {
        return imageFileIds.stream()
                .map(imageFileId -> {
                    try {
                        return getWebpInfo(imageFileId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    public ConvertedImageInfo getWebpInfo(String imageFileId) throws Exception {
        ObjectMeta objectMeta = objectRepository.getObjectMetaById(imageFileId);
        if (objectMeta == null) {
            log.error("{} not exist", imageFileId);
            return null;
        }

        String originalObjectName = objectMeta.getObjectName();
        String absolutePath = objectMeta.getAbsolutePath();
        File srcFile = new File(absolutePath);

        String format = "webp";
        String suffix = "." + format;
        String contentId = UUID.randomUUID().toString().replace("-", "");
        String destPath = fileStoreService.genFilePath(contentId, srcFile.length(), suffix);
        File destFile = new File(destPath);
        ImageOps.convert2webp(srcFile, destFile);

        if (destFile.exists()) {
            ObjectResult objectResult1 = putObjectService.putObject(originalObjectName, contentId, suffix, destFile);
            String objectName1 = objectResult1.getObjectName();
            String objectId1 = objectResult1.getObjectId();
            String objectUrl1 = objectNameService.getObjectUrl(objectName1);
            ConvertedImageInfo convertedImageInfo = new ConvertedImageInfo(imageFileId, objectId1, format, objectUrl1);
            return convertedImageInfo;
        } else {
            log.error("image conversion failed");
            return null;
        }
    }

    public List<ImageInfo> getImagesInfo(List<String> imageFileIds) {
        return imageFileIds.stream()
                .map(imageFileId -> {
                    try {
                        return getImageInfo(imageFileId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    public AudioInfo getAudioInfo(String audioFileId) throws Exception {
        ObjectMeta objectMeta = objectRepository.getObjectMetaById(audioFileId);
        if (objectMeta == null) {
            return null;
        }

        String absolutePath = objectMeta.getAbsolutePath();
        MediaProps mediaProps = FFmpegWrapper.getMediaProps(absolutePath);
        if (mediaProps == null || mediaProps.getAudioProps() == null) {
            String errMsg = String.format("%s 的 FFmpeg 音频信息为 null", audioFileId);
            throw new Exception(errMsg);
        }

        AudioProps audioProps = mediaProps.getAudioProps();
        String audioCodec = audioProps.getCodecName();
        int duration = audioProps.getDuration().intValue();
        long bitRate = audioProps.getBitRate();
        String objectId = audioFileId;
        String objectName = objectMeta.getObjectName();
        String objectUrl = objectNameService.getObjectUrl(objectName);

        return new AudioInfo(audioFileId, objectId, duration, audioCodec, bitRate, objectUrl);
    }
}
