package com.base.pdfviewerscannerwhite.ui.main

import android.app.Activity
import android.content.Context
import android.content.IntentSender
import android.net.Uri
import android.os.Environment
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LifecycleCoroutineScope
import com.base.pdfviewerscannerwhite.ads.AdmobHelper
import com.base.pdfviewerscannerwhite.ads.AdmobHelper.lastScanShowAd
import com.base.pdfviewerscannerwhite.ads.admob.AdmobInterstitialUtils
import com.base.pdfviewerscannerwhite.bean.ConstObject
import com.base.pdfviewerscannerwhite.bean.ConstObject.BOOKMARK_DATA_TYPE
import com.base.pdfviewerscannerwhite.bean.ConstObject.DOCUMENT_DATA_TYPE
import com.base.pdfviewerscannerwhite.bean.ConstObject.RECENT_DATA_TYPE
import com.base.pdfviewerscannerwhite.bean.DocumentBean
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_EXCEL
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_PDF
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_PPT
import com.base.pdfviewerscannerwhite.bean.DocumentBean.Companion.TYPE_WORD
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfBoxUtils
import com.base.pdfviewerscannerwhite.utils.AssetUtils.saveAssetsFile
import com.base.pdfviewerscannerwhite.utils.KotlinExt.toFormatTime3
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.SpStringUtils
import com.base.pdfviewerscannerwhite.utils.SpStringUtils.BOOKMARK_KEY
import com.base.pdfviewerscannerwhite.utils.SpStringUtils.LAST_VIEW_KEY
import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast
import com.base.pdfviewerscannerwhite.utils.getMediaFile
import com.base.pdfviewerscannerwhite.utils.upDateDemoStore
import com.base.pdfviewerscannerwhite.utils.updateMediaStore
import com.google.mlkit.vision.documentscanner.GmsDocumentScannerOptions
import com.google.mlkit.vision.documentscanner.GmsDocumentScanning
import com.google.mlkit.vision.documentscanner.GmsDocumentScanningResult
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import java.io.File

class MainPresenter(
    val context: Context,
    val mainView: MainView,
    val lifecycleScope: LifecycleCoroutineScope
) {

    private val TAG = "MainPresenter"
    fun getDocumentAppDir(): File {
        val appDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), context.packageName)
        if (!appDir.exists())
            appDir.exists()
        return appDir
    }

    //所有fragment的数据,都从这里取
    val pdfDocuments = arrayListOf<DocumentBean>()
    val wordDocuments = arrayListOf<DocumentBean>()
    val excelDocuments = arrayListOf<DocumentBean>()
    val pptDocuments = arrayListOf<DocumentBean>()

    var scannerLauncher: ActivityResultLauncher<IntentSenderRequest>? = null

    companion object {
        var mainRefreshData: Boolean = false
    }

    fun initAllDocumentData() = lifecycleScope.launch(Dispatchers.IO) {
        mainRefreshData = true
        val start = System.currentTimeMillis()
        Log.d("glc", "pdfs 清理前:" + pdfDocuments.size)
        context.upDateDemoStore()
        if (!ConstObject.haveSaveDemo) {
            context.saveAssetsFile()
            ConstObject.haveSaveDemo = true
        }
        val pdfs = initAllPdfData()
        pdfs.map { it.state = PdfBoxUtils.checkPdfEncryption(it.path) }
        pdfDocuments.clear()
        wordDocuments.clear()
        excelDocuments.clear()
        pptDocuments.clear()
        Log.d("glc", "pdfs:" + pdfs.size)
        pdfDocuments.addAll(pdfs)
        Log.d("glc", "添加了 pdfDocuments:" + pdfDocuments.size)
        wordDocuments.addAll(initAllWordData())
        excelDocuments.addAll(initAllExcelData())
        pptDocuments.addAll(initAllPptData())
        mainRefreshData = false
        lifecycleScope.launch(Dispatchers.Main) {
            val end = System.currentTimeMillis()
            val time = end - start
            LogEx.logDebug(TAG, "time=$time")
            mainView.refreshPageList()
        }
    }


    fun getDataByType(documentType: String, dataType: String): List<DocumentBean> {

        val bookmarkList = SpStringUtils.getSpStringList(SpStringUtils.BOOKMARK_KEY)

        Log.d("glc", "pdfDocuments:" + pdfDocuments.size)
        val recentList = SpStringUtils.getSpStringList(LAST_VIEW_KEY)

        when (documentType) {
            TYPE_PDF -> {
                val data = arrayListOf<DocumentBean>()
                data.addAll(pdfDocuments)

                data.forEach {
                    it.isBookmarked = bookmarkList.contains(it.path)
                    it.state = PdfBoxUtils.checkPdfEncryption(it.path)
                }
                when (dataType) {
                    DOCUMENT_DATA_TYPE -> {
                        return data
                    }

                    RECENT_DATA_TYPE -> {
                        return data.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
                    }

                    BOOKMARK_DATA_TYPE -> {
                        return data.filter { it.isBookmarked }
                    }

                }
            }

            TYPE_WORD -> {
                val data = arrayListOf<DocumentBean>()
                data.addAll(wordDocuments)

                data.forEach {
                    it.isBookmarked = bookmarkList.contains(it.path)
                }
                when (dataType) {

                    DOCUMENT_DATA_TYPE -> {
                        return data
                    }

                    RECENT_DATA_TYPE -> {
                        data.forEach { recentFilter(recentList, it) }
                        return data.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
                    }

                    BOOKMARK_DATA_TYPE -> {
                        return data.filter { it.isBookmarked }
                    }

                }
            }

            TYPE_EXCEL -> {
                val data = arrayListOf<DocumentBean>()
                data.addAll(excelDocuments)

                data.forEach {
                    it.isBookmarked = bookmarkList.contains(it.path)
                }
                when (dataType) {
                    DOCUMENT_DATA_TYPE -> {
                        return data
                    }

                    RECENT_DATA_TYPE -> {
                        data.forEach { recentFilter(recentList, it) }
                        return data.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
                    }

                    BOOKMARK_DATA_TYPE -> {
                        return data.filter { it.isBookmarked }
                    }

                }
            }

            TYPE_PPT -> {
                val data = arrayListOf<DocumentBean>()
                data.addAll(pptDocuments)

                pptDocuments.forEach {
                    it.isBookmarked = bookmarkList.contains(it.path)
                }
                when (dataType) {
                    DOCUMENT_DATA_TYPE -> {
                        return data
                    }

                    RECENT_DATA_TYPE -> {
                        data.forEach { recentFilter(recentList, it) }
                        return data.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
                    }

                    BOOKMARK_DATA_TYPE -> {
                        return data.filter { it.isBookmarked }
                    }

                }
            }
        }
        return listOf()
    }

    private fun recentFilter(recentList: List<String>, documentBean: DocumentBean) {

        val findLastTime = recentList.filter { it.contains(documentBean.path) }.map {
            it.split("_/_")[1].toLong()
        }
        if (findLastTime.isNotEmpty()) {
            val max = findLastTime.max()
            LogEx.logDebug(TAG, "recentFilter ${documentBean.path} ${max.toFormatTime3()}")
            documentBean.lastViewTime = max
        }
    }


    private fun initAllPdfData(): MutableList<DocumentBean> {
        val demoDocumentBean = DocumentBean()
        demoDocumentBean.type = TYPE_PDF
        val demoFile = File(context.filesDir, "demo")

        val selectionArgs = arrayOf(ConstObject.MIME_TYPE_PDF)
        demoDocumentBean.path = demoFile.listFiles()?.find { it.name.contains(".pdf") }?.absolutePath ?: ""


        val list = context.getMediaFile(selectionArgs = selectionArgs)
        val documentList = list.map {
            DocumentBean(it.path, uri = it.uri, type = TYPE_PDF)
        }
        val new = documentList.toMutableList()
        if (File(demoDocumentBean.path).exists()) {
            new.add(0, demoDocumentBean)
        }
        return new
    }

    private fun initAllWordData(): MutableList<DocumentBean> {
        val demoDocumentBean = DocumentBean()
        demoDocumentBean.type = TYPE_WORD
        val demoFile = File(context.filesDir, "demo")

        val selectionArgs = arrayOf(ConstObject.MIME_TYPE_DOC, ConstObject.MIME_TYPE_DOCX)
        demoDocumentBean.path = demoFile.listFiles()?.find { it.name.contains(".docx") }?.absolutePath ?: ""


        val list = context.getMediaFile(selectionArgs = selectionArgs)
        val documentList = list.map {
            DocumentBean(it.path, uri = it.uri, type = TYPE_WORD)
        }
        val new = documentList.toMutableList()
        if (File(demoDocumentBean.path).exists()) {
            new.add(0, demoDocumentBean)
        }
        return new
    }

    private fun initAllExcelData(): MutableList<DocumentBean> {
        val demoDocumentBean = DocumentBean()
        demoDocumentBean.type = TYPE_EXCEL
        val demoFile = File(context.filesDir, "demo")

        val selectionArgs = arrayOf(ConstObject.MIME_TYPE_XLS, ConstObject.MIME_TYPE_XLSX)
        demoDocumentBean.path = demoFile.listFiles()?.find { it.name.contains(".xlsx") }?.absolutePath ?: ""

        val list = context.getMediaFile(selectionArgs = selectionArgs)
        val documentList = list.map {
            DocumentBean(it.path, uri = it.uri, type = TYPE_EXCEL)
        }
        val new = documentList.toMutableList()
        if (File(demoDocumentBean.path).exists()) {
            new.add(0, demoDocumentBean)
        }
        return new
    }


    private fun initAllPptData(): MutableList<DocumentBean> {
        val demoDocumentBean = DocumentBean()
        demoDocumentBean.type = TYPE_PPT
        val demoFile = File(context.filesDir, "demo")

        val selectionArgs = arrayOf(ConstObject.MIME_TYPE_PPT, ConstObject.MIME_TYPE_PPTX)
        demoDocumentBean.path = demoFile.listFiles()?.find { it.name.contains(".pptx") }?.absolutePath ?: ""


        val list = context.getMediaFile(selectionArgs = selectionArgs)
        val documentList = list.map {
            DocumentBean(it.path, uri = it.uri, type = TYPE_PPT)
        }
        val new = documentList.toMutableList()
        if (File(demoDocumentBean.path).exists()) {
            new.add(0, demoDocumentBean)
        }
        return new
    }

    var scannerLauncherRegister: Boolean = false
    fun initScannerLauncher(appCompatActivity: AppCompatActivity) {
        scannerLauncher =
            appCompatActivity.registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->

                val resultCode = activityResult.resultCode
                val result = GmsDocumentScanningResult.fromActivityResultIntent(activityResult.data)
//                appCompatActivity.toast("回调1")
                if (resultCode == Activity.RESULT_OK && result != null) {
                    val pages = result.pages
//                    appCompatActivity.toast("回调2 ${pages?.size}")
                    var imageUri = Uri.EMPTY
                    if (!pages.isNullOrEmpty()) {
//                        appCompatActivity.toast("回调3")
                        imageUri = pages[0].imageUri
                    }
                    val pdfUri = result.pdf?.uri ?: Uri.EMPTY
                    mainView.handleActivityGmsScanResult(imageUri, pdfUri)
                } else {
                    mainView.handleActivityGmsScanResult(null, null)
                }
            }

        scannerLauncherRegister = true
    }


    fun starAdGmsScan(activity: Activity) {

        if (AdmobHelper.isShowScanInter() && AdmobHelper.canCommonShowAd()) {
            AdmobInterstitialUtils.showInterstitialAd(activity) {
                if (it) {
                    lastScanShowAd = System.currentTimeMillis()
                }
                starGmsScan(activity)
            }
        } else {
            starGmsScan(activity)
        }

    }

    fun starGmsScan(activity: Activity) {
        runCatching {
            if (scannerLauncher == null && !scannerLauncherRegister) return
            val options =
                GmsDocumentScannerOptions.Builder()
                    .setScannerMode(GmsDocumentScannerOptions.SCANNER_MODE_BASE)
                    .setResultFormats(GmsDocumentScannerOptions.RESULT_FORMAT_PDF)
                    .setGalleryImportAllowed(true)

            options.setScannerMode(GmsDocumentScannerOptions.SCANNER_MODE_FULL)

            val pageLimit = 1
            options.setPageLimit(pageLimit)


            GmsDocumentScanning.getClient(options.build())
                .getStartScanIntent(activity)
                .addOnSuccessListener { intentSender: IntentSender ->
                    scannerLauncher?.launch(IntentSenderRequest.Builder(intentSender).build())
                }
                .addOnFailureListener { e: Exception ->
                }
        }
    }


    fun deleteList(list: List<DocumentBean>) {
        MainScope().launch(Dispatchers.IO) {
            list.forEach {
                runCatching {
                    val file = File(it.path)
                    file.delete()
                }
            }
            context.updateMediaStore()
        }
    }

    fun renameDocumentBean(
        file: File,
        newName: String,
        documentPageFragment: DocumentPageFragment,
    ) = lifecycleScope.launch(Dispatchers.IO) {

        try {
            val newFile = File(file.parentFile, newName)
            val result = file.renameTo(newFile)
            if (result) {
                when (documentPageFragment.type) {
                    TYPE_PDF -> pdfDocuments.find { it.path == file.absolutePath }?.path = newFile.absolutePath
                    TYPE_WORD -> wordDocuments.find { it.path == file.absolutePath }?.path = newFile.absolutePath
                    TYPE_EXCEL -> excelDocuments.find { it.path == file.absolutePath }?.path = newFile.absolutePath
                    TYPE_PPT -> pptDocuments.find { it.path == file.absolutePath }?.path = newFile.absolutePath
                }
            }
        } catch (e: Exception) {

        }
        launch(Dispatchers.Main) {
            documentPageFragment.refreshData()
        }
    }

    fun deleteDocument(path: String, documentPageFragment: DocumentPageFragment) = lifecycleScope.launch(Dispatchers.IO) {
        val flag = File(path).delete()
        if (flag) {
            when (documentPageFragment.type) {
                TYPE_PDF -> pdfDocuments.removeIf { it.path == path }
                TYPE_WORD -> wordDocuments.removeIf { it.path == path }
                TYPE_EXCEL -> excelDocuments.removeIf { it.path == path }
                TYPE_PPT -> pptDocuments.removeIf { it.path == path }
            }
            launch(Dispatchers.Main) {
                documentPageFragment.refreshData()
            }
        }

    }

    fun changeBookmark(path: String, isBookmarked: Boolean, documentPageFragment: DocumentPageFragment) =
        lifecycleScope.launch(Dispatchers.IO) {
            if (isBookmarked) {
                SpStringUtils.addSpString(BOOKMARK_KEY, path)
            } else {
                SpStringUtils.deleteSpString(BOOKMARK_KEY, path)
            }
            when (documentPageFragment.type) {
                TYPE_PDF -> pdfDocuments.find { it.path == path }?.isBookmarked = isBookmarked
                TYPE_WORD -> wordDocuments.find { it.path == path }?.isBookmarked = isBookmarked
                TYPE_EXCEL -> excelDocuments.find { it.path == path }?.isBookmarked = isBookmarked
                TYPE_PPT -> pptDocuments.find { it.path == path }?.isBookmarked = isBookmarked
            }

            launch(Dispatchers.Main) {
                documentPageFragment.refreshData()
            }
        }

    fun copyFile(file: File, newFile: File) {
        runCatching {
            file.copyTo(newFile, true)
        }
    }


    fun changePdfLock(item: DocumentBean, documentPageFragment: DocumentPageFragment) {
        val pdf = pdfDocuments.find { it.path == item.path }
        pdf?.state = PdfBoxUtils.checkPdfEncryption(item.path)
        documentPageFragment.refreshData()
    }

}