package com.adealink.weparty.util

import com.adealink.frame.base.Rlt
import com.adealink.frame.log.Log
import com.adealink.frame.oss.data.UploadFile
import com.adealink.frame.oss.listener.IOssListener
import com.adealink.frame.storage.file.imageProgressPath
import com.adealink.frame.util.deleteFiles
import com.adealink.frame.util.getFileSuffix
import com.adealink.frame.util.md5
import com.adealink.weparty.App
import com.adealink.weparty.commonui.ext.isGIFImage
import com.adealink.weparty.commonui.mediapicker.imageselect.util.compressImage
import com.adealink.weparty.commonui.mediapicker.imageselect.util.compressVideo
import com.adealink.weparty.commonui.mediapicker.imageselect.util.processFastStart
import com.adealink.weparty.module.image.data.PhotoData
import com.adealink.weparty.module.image.data.VideoData
import com.adealink.weparty.module.profile.data.VoiceData
import com.adealink.weparty.oss.OssCompressor
import java.io.File

private const val TAG_FILE = "tag_file"
private const val TAG_UPLOAD = "tag_upload"

fun String?.getFilePathBy(path: String, fileType: UploadFile.FileType): String? {
    if (isNullOrEmpty()) {
        return null
    }
    return File(
        imageProgressPath,
        "${md5()}.${fileType.suffix.ifEmpty { getFileSuffix(this) }}"
    ).path
}


suspend fun uploadPhoto(
    photo: PhotoData,
    reqWidth: Int = OssCompressor.IMAGE_MAX_WIDTH,
    reqHeight: Int = OssCompressor.IMAGE_MAX_HEIGHT,
    maxSizeKB: Int = OssCompressor.IMAGE_MAX_SIZE_KB,
    minQuality: Int = OssCompressor.IMAGE_MIN_QUALITY,
    fileType: UploadFile.FileType = UploadFile.FileType.IMAGE
): Rlt<List<PhotoData>> {
    return uploadPhotos(
        listOf(photo),
        reqWidth,
        reqHeight,
        maxSizeKB,
        minQuality,
        fileType
    )
}

suspend fun uploadPhotos(
    photos: List<PhotoData>,
    reqWidth: Int = OssCompressor.IMAGE_MAX_WIDTH,
    reqHeight: Int = OssCompressor.IMAGE_MAX_HEIGHT,
    maxSizeKB: Int = OssCompressor.IMAGE_MAX_SIZE_KB,
    minQuality: Int = OssCompressor.IMAGE_MIN_QUALITY,
    fileType: UploadFile.FileType = UploadFile.FileType.IMAGE
): Rlt<List<PhotoData>> {
    //通知上传开始
    for (photo in photos) {
        photo.mediaUpload.startLD.postValue(Unit)
    }

    try {
        for (photo in photos) {
            val localPath = photo.path
            if (!photo.isLocal() || localPath.isNullOrEmpty()) {
                continue
            }
            val compressFilePath = if (isGIFImage(localPath)) {
                localPath
            } else {
                val compressRlt =
                    compressImage(
                        localPath,
                        reqWidth,
                        reqHeight,
                        maxSizeKB,
                        minQuality
                    )

                if (compressRlt is Rlt.Failed) {
                    Log.logRltD(
                        TAG_UPLOAD,
                        "uploadPhotos, compress failed, filePath:${localPath}",
                        compressRlt
                    )
                    return compressRlt
                }
                val compressResult = (compressRlt as Rlt.Success).data
                compressResult.path
            }

            val rlt = App.instance.ossService.suspendUploadFile(
                UploadFile.LocalFile(
                    compressFilePath,
                    fileType,
                    compress = false,
                    deleteAfterUploaded = localPath != compressFilePath
                ),
                object : IOssListener {
                    override fun onProgress(progress: Int?, currentSize: Long, totalSize: Long) {
                        super.onProgress(progress, currentSize, totalSize)
                        photo.mediaUpload.progressLD.postValue(Pair(currentSize, totalSize))
                    }
                }
            )
            when (rlt) {
                is Rlt.Failed -> {
                    Log.logRltD(
                        TAG_UPLOAD,
                        "uploadPhotos, upload failed, filePath:${localPath}",
                        rlt
                    )
                }

                is Rlt.Success -> {
                    Log.d(TAG_UPLOAD, "uploadPhoto, url: ${rlt.data}")
                    photo.url = rlt.data
                }
            }

            photo.mediaUpload.endLD.postValue(Unit)
        }
    } finally {
        for (photo in photos) {
            photo.mediaUpload.endLD.postValue(Unit)
        }
    }
    return Rlt.Success(photos)
}


suspend fun uploadVoice(
    voice: VoiceData,
    deleteAfterUploaded: Boolean = true
): Rlt<VoiceData> {
    val localPath = voice.path
    if (!voice.isLocal() || localPath.isNullOrEmpty()) {
        return Rlt.Success(voice)
    }
    val rlt = App.instance.ossService.suspendUploadFile(
        UploadFile.LocalFile(
            localPath,
            UploadFile.FileType.AUDIO,
            deleteAfterUploaded = deleteAfterUploaded
        )
    )
    when (rlt) {
        is Rlt.Failed -> {
            Log.logRltD(
                TAG_UPLOAD,
                "uploadPhotos, upload failed, filePath:${localPath}",
                rlt
            )
            return rlt
        }

        is Rlt.Success -> {
            voice.url = rlt.data
            return Rlt.Success(voice)
        }
    }
}


suspend fun uploadVideo(
    videos: List<VideoData>,
    resolution: Int = OssCompressor.VIDEO_RESOLUTION,
    bitrate: Int = OssCompressor.VIDEO_BITRATE,
    maxSizeKB: Int = OssCompressor.VIDEO_MAX_SIZE_KB,
    fileType: UploadFile.FileType = UploadFile.FileType.VIDEO,
    deleteAfterUploaded: Boolean = true
): Rlt<List<VideoData>> {
    for (video in videos) {
        video.mediaUpload.startLD.postValue(Unit)
    }
    try {
        for (video in videos) {
            //上传视频
            val uploadVideoRlt = uploadVideoInner(
                video,
                resolution,
                bitrate,
                maxSizeKB,
                fileType,
                deleteAfterUploaded
            )
            when (uploadVideoRlt) {
                is Rlt.Failed -> {
                    return uploadVideoRlt
                }

                is Rlt.Success -> {
                    //上传视频预览图
                    video.cover?.let { cover ->
                        uploadPhoto(
                            cover
                        )
                    }
                }
            }
        }
    } finally {
        for (video in videos) {
            video.mediaUpload.endLD.postValue(Unit)
        }
    }
    return Rlt.Success(videos)
}


private suspend fun uploadVideoInner(
    video: VideoData,
    resolution: Int = OssCompressor.VIDEO_RESOLUTION,
    bitrate: Int = OssCompressor.VIDEO_BITRATE,
    maxSizeKB: Int = OssCompressor.VIDEO_MAX_SIZE_KB,
    fileType: UploadFile.FileType = UploadFile.FileType.VIDEO,
    deleteAfterUploaded: Boolean = true
): Rlt<VideoData> {
    val localPath = video.path
    if (!video.isLocal() || localPath.isNullOrEmpty()) {
        return Rlt.Success(video)
    }
    var uploadVideoPath: String = localPath

    val tempVideoList = mutableListOf<String>()
    video.mediaUpload.progressLD.postValue(Pair(0, 100))

    try {
        //压缩视频(进度20%)
        compressVideo(
            localPath,
            resolution,
            bitrate,
            maxSizeKB,
        ).let { compressRlt ->
            if (compressRlt is Rlt.Failed) {
                Log.logRltD(
                    TAG_UPLOAD,
                    "uploadVideo, compress failed, filePath:${localPath}",
                    compressRlt
                )
                return compressRlt
            }
            val compressResult = (compressRlt as Rlt.Success).data
            uploadVideoPath = compressResult.path

            tempVideoList.add(compressResult.path)
            Log.d(TAG_UPLOAD, "uploadVideo, compressPath: ${compressResult.path}")
        }
        video.mediaUpload.progressLD.postValue(Pair(20, 100))

        //FastStart(MP4视频流式播放)(进度20%)
        processFastStart(uploadVideoPath).let { rlt ->
            if (rlt is Rlt.Failed) {
                Log.logRltD(
                    TAG_UPLOAD,
                    "processFastStart failed, filePath:${localPath}",
                    rlt
                )
                return@let
            }
            val fastStartPath = (rlt as Rlt.Success).data
            uploadVideoPath = fastStartPath

            tempVideoList.add(fastStartPath)
            Log.e(TAG_UPLOAD, "processFastStart, filePath:${localPath}")
        }
        video.mediaUpload.progressLD.postValue(Pair(40, 100))

        //上传视频(进度60%)
        val rlt = App.instance.ossService.suspendUploadFile(
            UploadFile.LocalFile(
                uploadVideoPath,
                fileType,
                deleteAfterUploaded = deleteAfterUploaded
            ),
            object : IOssListener {
                override fun onProgress(progress: Int?, currentSize: Long, totalSize: Long) {
                    super.onProgress(progress, currentSize, totalSize)
                    val progress = 40L + (60 * (currentSize * 1f / totalSize)).toLong()
                    video.mediaUpload.progressLD.postValue(Pair(progress, 100))
                }
            }
        )
        when (rlt) {
            is Rlt.Failed -> {
                Log.logRltD(
                    TAG_UPLOAD,
                    "uploadVideo, upload failed, filePath:${localPath}",
                    rlt
                )
            }

            is Rlt.Success -> {
                video.url = rlt.data
            }
        }
        Log.i(TAG_UPLOAD, "uploadVideo, url:${video.url}, path:$uploadVideoPath")
    } finally {
        try {
            for (videoPath in tempVideoList) {
                deleteFiles(videoPath)
            }
        } catch (e: Exception) {

        }
    }
    return Rlt.Success(video)
}