package com.dronex.rec.recording

import android.content.ContentValues
import android.content.Context
import android.os.Build
import android.provider.MediaStore
import androidx.camera.video.FileOutputOptions
import java.io.File
import java.io.FileInputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

object RecordingOutputFactory {
    private const val RELATIVE_PATH = "Movies/飞行极控录像工作台"
    private const val MIME_TYPE = "video/mp4"

    fun buildSegmentOutputOptions(segmentFile: File): FileOutputOptions {
        return FileOutputOptions.Builder(segmentFile).build()
    }

    fun createSegmentFile(
            context: Context,
            displayName: String?,
            index: Int,
    ): File {
        val directory = File(context.cacheDir, "recording_segments")
        if (!directory.exists()) {
            directory.mkdirs()
        }
        val baseName = resolveFileName(displayName).removeSuffix(".mp4")
        return File(directory, "${baseName}_${System.currentTimeMillis()}_part$index.mp4")
    }

    fun createMergeFile(context: Context, displayName: String?): File {
        val directory = File(context.cacheDir, "recording_segments")
        if (!directory.exists()) {
            directory.mkdirs()
        }
        val baseName = resolveFileName(displayName).removeSuffix(".mp4")
        return File(directory, "${baseName}_${System.currentTimeMillis()}_merged.mp4")
    }

    fun publishToMediaStore(
            context: Context,
            displayName: String?,
            sourceFile: File,
    ): String? {
        val fileName = resolveFileName(displayName)
        val contentValues =
                ContentValues().apply {
                    put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
                    put(MediaStore.MediaColumns.MIME_TYPE, MIME_TYPE)
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        put(MediaStore.Video.Media.RELATIVE_PATH, RELATIVE_PATH)
                        put(MediaStore.Video.Media.IS_PENDING, 1)
                    }
                }

        val resolver = context.contentResolver
        val uri =
                resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues)
                        ?: return null
        try {
            val outputStream =
                    resolver.openOutputStream(uri)
                            ?: throw IllegalStateException("Cannot open MediaStore output stream")
            outputStream.use { output ->
                FileInputStream(sourceFile).use { input -> input.copyTo(output) }
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                val publishedValues =
                        ContentValues().apply { put(MediaStore.Video.Media.IS_PENDING, 0) }
                resolver.update(uri, publishedValues, null, null)
            }
            return uri.toString()
        } catch (error: Exception) {
            resolver.delete(uri, null, null)
            throw error
        }
    }

    fun publishPartToMediaStore(
            context: Context,
            displayName: String?,
            sourceFile: File,
            partIndex: Int,
    ): String? {
        val resolvedName = resolveFileName(displayName)
        val partName = resolvedName.replace(".mp4", "_part$partIndex.mp4")
        return publishToMediaStore(context, partName, sourceFile)
    }

    fun resolveFileName(displayName: String?): String {
        val trimmed = displayName?.trim().orEmpty()
        if (trimmed.isNotEmpty()) {
            return if (trimmed.lowercase(Locale.US).endsWith(".mp4")) {
                trimmed
            } else {
                "$trimmed.mp4"
            }
        }
        val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
        return "REC_$timestamp.mp4"
    }
}
