package com.base.pdfviewerscannerwhite.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.DocumentsContract
import android.provider.MediaStore
import android.provider.OpenableColumns
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_APK
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_DOC
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_DOCX
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_PDF
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_PPT
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_PPTX
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_XLS
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_XLSX
import com.base.pdfviewerscannerwhite.bean.ConstObject.MIME_TYPE_ZIP
import com.base.pdfviewerscannerwhite.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


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.upDateDemoStore() {
    val demoFile = File(filesDir, "demo")
    MediaScannerConnection.scanFile(
        this,        arrayOf(demoFile.absolutePath) , 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_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 uri=$uri 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, mimeType = "image/*"))
            }
        }
    } 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
    }

fun queryFiles(context: Context, fileSuffix: String): MutableList<File> {
    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()) {
            val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA))
            fileList.add(File(path))
        }
        cursor.close()
    }
    return fileList
}

fun getFileNameFromUri(context: Context, uri: Uri): String {
    var displayName = ""
    if (DocumentsContract.isDocumentUri(context, uri)) {
        val projection = arrayOf(OpenableColumns.DISPLAY_NAME)
        var cursor: Cursor? = null
        try {
            cursor = context.contentResolver.query(uri, projection, null, null, null)
            val column_index = cursor!!.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
            if (cursor.moveToFirst()) {
                displayName = cursor.getString(column_index)
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        } finally {
            cursor?.close()
        }
    }
    return displayName
}