package com.rosetta.messenger.domain.chats.usecase

import android.content.Context
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.webkit.MimeTypeMap
import java.util.Locale
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

data class ResolveVideoCircleMetaCommand(
    val context: Context,
    val videoUri: Uri
)

data class VideoCircleMeta(
    val durationSec: Int,
    val width: Int,
    val height: Int,
    val mimeType: String
)

class ResolveVideoCircleMetaUseCase @Inject constructor() {
    operator fun invoke(command: ResolveVideoCircleMetaCommand): VideoCircleMeta {
        var durationSec = 1
        var width = 0
        var height = 0

        val mimeType =
            command.context.contentResolver.getType(command.videoUri)?.trim().orEmpty().ifBlank {
                val ext =
                    MimeTypeMap.getFileExtensionFromUrl(command.videoUri.toString())
                        ?.lowercase(Locale.ROOT)
                        .orEmpty()
                MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext) ?: "video/mp4"
            }

        runCatching {
            val retriever = MediaMetadataRetriever()
            retriever.setDataSource(command.context, command.videoUri)
            val durationMs =
                retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
                    ?.toLongOrNull()
                    ?: 0L
            val rawWidth =
                retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)
                    ?.toIntOrNull()
                    ?: 0
            val rawHeight =
                retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)
                    ?.toIntOrNull()
                    ?: 0
            val rotation =
                retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)
                    ?.toIntOrNull()
                    ?: 0
            retriever.release()

            durationSec = ((durationMs + 999L) / 1000L).toInt().coerceAtLeast(1)
            val rotated = rotation == 90 || rotation == 270
            width = if (rotated) rawHeight else rawWidth
            height = if (rotated) rawWidth else rawHeight
        }

        return VideoCircleMeta(
            durationSec = durationSec,
            width = width.coerceAtLeast(0),
            height = height.coerceAtLeast(0),
            mimeType = mimeType
        )
    }
}

data class EncodeVideoUriToHexCommand(
    val context: Context,
    val videoUri: Uri
)

class EncodeVideoUriToHexUseCase @Inject constructor() {
    suspend operator fun invoke(command: EncodeVideoUriToHexCommand): String? {
        return withContext(Dispatchers.IO) {
            runCatching {
                command.context.contentResolver.openInputStream(command.videoUri)?.use { stream ->
                    val bytes = stream.readBytes()
                    if (bytes.isEmpty()) {
                        null
                    } else {
                        bytesToHex(bytes)
                    }
                }
            }.getOrNull()
        }
    }

    private fun bytesToHex(bytes: ByteArray): String {
        val hexChars = "0123456789abcdef".toCharArray()
        val output = CharArray(bytes.size * 2)
        var index = 0
        bytes.forEach { byte ->
            val value = byte.toInt() and 0xFF
            output[index++] = hexChars[value ushr 4]
            output[index++] = hexChars[value and 0x0F]
        }
        return String(output)
    }
}
