package com.base.browserwhite.utils

import android.annotation.SuppressLint
import android.content.Context
import android.database.Cursor
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_APK
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_AUDIO
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_DOC
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_DOCX
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_IMAGE
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_PDF
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_PPT
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_PPTX
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_VIDEO
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_XLS
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_XLSX
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_ZIP
import com.base.browserwhite.bean.MediaBean
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import java.io.File


object MediaStoreUtils {

    private val TAG = "MediaStoreUtils"

    private val commonMediaDir = arrayOf(
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).absolutePath,
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath,
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath,
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).absolutePath,
    )

    fun Context.updateMediaStore(
        filePath: Array<String> = commonMediaDir
    ) {
        MediaScannerConnection.scanFile(
            this, filePath, null
        ) { path: String?, uri: Uri? -> }
    }

    //图片视频音频不用这个查
    fun Context.getMediaFile(selectionArgs: Array<String>? = null): ArrayList<MediaBean> {

        val list = arrayListOf<MediaBean>()

        val projection = arrayOf(
            MediaStore.Files.FileColumns._ID,
            MediaStore.Files.FileColumns.DATA,
//            MediaStore.Files.FileColumns.TITLE,
            MediaStore.Files.FileColumns.MIME_TYPE,
//            MediaStore.Files.FileColumns.SIZE,
        )

        val mimeTypeSelectionArgs = selectionArgs ?: arrayOf(
            MIME_TYPE_IMAGE,
            MIME_TYPE_VIDEO,
            MIME_TYPE_AUDIO,
            MIME_TYPE_PDF,
            MIME_TYPE_DOC,
            MIME_TYPE_DOCX,
            MIME_TYPE_XLS,
            MIME_TYPE_XLSX,
            MIME_TYPE_PPT,
            MIME_TYPE_PPTX,
            MIME_TYPE_APK
        )

        val mimeTypeSelection = if (mimeTypeSelectionArgs.size == 1) {
            "${MediaStore.Files.FileColumns.MIME_TYPE} = ?"
        } else {
            "${MediaStore.Files.FileColumns.MIME_TYPE} IN (" + mimeTypeSelectionArgs.joinToString(",") { "?" } + ")"
        }

//        val selection = "$timeSelection AND $mimeTypeSelection"
        val selection = mimeTypeSelection

        LogEx.logDebug(TAG, "selection=$selection")

        var cursor: Cursor? = null
        try {
            // 进行查询，并设置排序方式，按照文件添加时间降序排序
            cursor = this.contentResolver.query(
                MediaStore.Files.getContentUri("external"),
                projection,
                selection,
                selectionArgs ?: mimeTypeSelectionArgs,
                MediaStore.Files.FileColumns.DATE_ADDED + " DESC"
            )
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    runCatching {
                        val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
                        val uri = Uri.withAppendedPath(MediaStore.Files.getContentUri("external"), id.toString())

                        val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA))
//                        val title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.TITLE))
                        val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MIME_TYPE))
//                        val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.SIZE))

                        LogEx.logDebug(TAG, "path=$path mimeType=$mimeType")
                        list.add(
                            MediaBean(path = path, uri = uri, mimeType = mimeType)
                        )
                    }
                }
            }

        } catch (e: Exception) {
            LogEx.logDebug(TAG, "Exception $e")
        } finally {
            cursor?.close()
        }

        return list

    }

    @SuppressLint("Range")
    fun Context.getMediaPhotoCountSize(): Pair<Int, Long> {
        var count = 0
        var totalSize = 0L
        runCatching {
            val contentResolver = this.contentResolver

            // 定义查询的Uri和列
            val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
            val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.SIZE)

            // 执行查询
            val cursor = contentResolver.query(uri, projection, null, null, null)

            // 检查cursor是否包含数据
            count = cursor?.count ?: 0
            while (cursor?.moveToNext() == true) {
                totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
            }
            // 关闭cursor
            cursor?.close()
        }


        return Pair(count, totalSize)
    }

    fun Context.getMediaPhoto(): List<MediaBean> {

        val list = arrayListOf<MediaBean>()
        val contentResolver = this.contentResolver

        // 定义查询的Uri和列
        val baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA)

        // 执行查询
        var cursor: Cursor? = null

        try {
            cursor = contentResolver.query(baseUri, projection, null, null, null)

            if (cursor != null) {
                while (cursor.moveToNext()) {
                    val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID))
                    val uri = Uri.withAppendedPath(baseUri, id.toString())
                    val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
                    list.add(MediaBean(path = path, uri = uri))
                }
            }
        } catch (e: Exception) {

        } finally {
            cursor?.close()
        }

        return list
    }

    fun Context.getMediaVideo(): List<MediaBean> {

        val list = arrayListOf<MediaBean>()
        val contentResolver = this.contentResolver

        // 定义查询的Uri和列
        val baseUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
        val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.DATA, MediaStore.Video.Media.MIME_TYPE)

        // 执行查询
        var cursor: Cursor? = null

        try {
            cursor = contentResolver.query(baseUri, projection, null, null, null)

            if (cursor != null) {
                while (cursor.moveToNext()) {
                    val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
                    val uri = Uri.withAppendedPath(baseUri, id.toString())
                    LogEx.logDebug(TAG, "getMediaVideo uri=$uri")
                    val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))
                    val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE))
                    list.add(MediaBean(path = path, uri = uri, mimeType = mimeType))
                }
            }
        } catch (e: Exception) {

        } finally {
            cursor?.close()
        }

        return list
    }

    fun Context.getMediaAudio(): List<MediaBean> {

        val list = arrayListOf<MediaBean>()
        val contentResolver = this.contentResolver

        // 定义查询的Uri和列
        val baseUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
        val projection = arrayOf(MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.MIME_TYPE)

        // 执行查询
        var cursor: Cursor? = null

        try {
            cursor = contentResolver.query(baseUri, projection, null, null, null)

            if (cursor != null) {
                while (cursor.moveToNext()) {
                    val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
                    val uri = Uri.withAppendedPath(baseUri, id.toString())
                    val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))
                    val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE))
                    list.add(MediaBean(path = path, uri = uri, mimeType = mimeType))
                }
            }
        } catch (e: Exception) {

        } finally {
            cursor?.close()
        }

        return list
    }


    @SuppressLint("Range")
    fun Context.getMediaVideoCountSize(): Pair<Int, Long> {

        var count = 0
        var totalSize: Long = 0

        runCatching {
            val contentResolver = this.contentResolver

            // 定义查询的Uri和列
            val uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
            val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.SIZE)

            // 执行查询
            val cursor = contentResolver.query(uri, projection, null, null, null)

            // 检查cursor是否包含数据
            count = cursor?.count ?: 0
            while (cursor?.moveToNext() == true) {
                totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
            }
            // 关闭cursor
            cursor?.close()
        }
        return Pair(count, totalSize)
    }

    @SuppressLint("Range")
    fun Context.getMediaAudioCountSize(): Pair<Int, Long> {
        var count = 0
        var totalSize: Long = 0
        runCatching {
            val contentResolver = this.contentResolver

            // 定义查询的Uri和列
            val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
            val projection = arrayOf(
                MediaStore.Audio.Media._ID,
                MediaStore.Audio.Media.SIZE,
            )

            // 执行查询
            val cursor = contentResolver.query(uri, projection, null, null, null)

            // 检查cursor是否包含数据
            count = cursor?.count ?: 0
            while (cursor?.moveToNext() == true) {
                totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE))
            }

            // 关闭cursor
            cursor?.close()
        }
        return Pair(count, totalSize)
    }


    fun Context.getMediaDocumentCountSize(): Int {
        var count = 0
        runCatching {
            val contentResolver = this.contentResolver

            val mimeTypeSelectionArgs = arrayOf(
                MIME_TYPE_PDF,
                MIME_TYPE_DOC,
                MIME_TYPE_DOCX,
                MIME_TYPE_XLS,
                MIME_TYPE_XLSX,
                MIME_TYPE_PPT,
                MIME_TYPE_PPTX,
            )
            val mimeTypeSelection =
                "${MediaStore.Files.FileColumns.MIME_TYPE} IN (" + mimeTypeSelectionArgs.joinToString(",") { "?" } + ")"

            // 定义查询的Uri和列
            val uri = MediaStore.Files.getContentUri("external")
            val projection = arrayOf(MediaStore.Files.FileColumns._ID)

            // 执行查询
            val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)

            // 检查cursor是否包含数据
            count = cursor?.count ?: 0

            // 关闭cursor
            cursor?.close()
        }
        return count
    }

    fun Context.getMediaApkCountSize(): Int {
        var count = 0
        runCatching {
            val contentResolver = this.contentResolver

            val mimeTypeSelectionArgs = arrayOf(
                MIME_TYPE_APK
            )
            val mimeTypeSelection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?"

            // 定义查询的Uri和列
            val uri = MediaStore.Files.getContentUri("external")
            val projection = arrayOf(MediaStore.Files.FileColumns._ID)

            // 执行查询
            val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)

            // 检查cursor是否包含数据
            count = cursor?.count ?: 0

            // 关闭cursor
            cursor?.close()
        }
        return count
    }

    fun Context.getMediaZipCountSize(): Int {
        var count = 0
        runCatching {
            val contentResolver = this.contentResolver

            val mimeTypeSelectionArgs = arrayOf(
                MIME_TYPE_ZIP
            )
            val mimeTypeSelection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?"

            // 定义查询的Uri和列
            val uri = MediaStore.Files.getContentUri("external")
            val projection = arrayOf(MediaStore.Files.FileColumns._ID)

            // 执行查询
            val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)

            // 检查cursor是否包含数据
            count = cursor?.count ?: 0

            // 关闭cursor
            cursor?.close()
        }
        return count
    }

    private fun getFileTypeSelection(fileSuffix: String): String {
        return (MediaStore.Files.FileColumns.MEDIA_TYPE + "="
                + MediaStore.Files.FileColumns.MEDIA_TYPE_NONE + " AND "
                + MediaStore.Files.FileColumns.DATA + " LIKE '%" + fileSuffix + "'")
    }


    fun CoroutineScope.queryFiles(context: Context, fileSuffix: String, flow: MutableSharedFlow<String>? = null) =
        async(Dispatchers.IO) {
            val selection = getFileTypeSelection(fileSuffix)
            val fileList: MutableList<File> = ArrayList()
            val projection = arrayOf(
                MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DATA,
            )
            val sortOrder = MediaStore.Files.FileColumns._ID + " DESC"
            val queryUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
            } else {
                MediaStore.Files.getContentUri("external")
            }
            val cursor = context.contentResolver.query(queryUri, projection, selection, null, sortOrder)
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    delay(150)
                    val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA))
                    flow?.emit(path)
                    fileList.add(File(path))
                }
                cursor.close()
            }
            fileList
        }
}