package com.all.pdfreader.pro.app.util

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.ParcelFileDescriptor
import android.print.PrintAttributes
import android.print.PrintManager
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.webkit.MimeTypeMap
import android.widget.EditText
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.core.graphics.createBitmap
import androidx.print.PrintHelper
import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.model.PrintResult
import com.all.pdfreader.pro.app.ui.adapter.PrintPdfAdapter
import com.shockwave.pdfium.PdfDocument
import com.shockwave.pdfium.PdfPasswordException
import com.shockwave.pdfium.PdfiumCore
import com.tom_roush.pdfbox.pdmodel.common.PDPageLabelRange
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.regex.Pattern

object AppUtils {

    fun View.setOnSingleClickListener(interval: Long = 1000, onClick: (View) -> Unit) {
        var lastClickTime = 0L
        setOnClickListener {
            val now = System.currentTimeMillis()
            if (now - lastClickTime < interval) return@setOnClickListener
            lastClickTime = now
            onClick(it)
        }
    }

    /**
     * 添加点击动画（点击立即执行逻辑，动画期间禁用点击）
     *
     * @param onClick 点击后立即执行的逻辑
     */
    fun View.setClickWithAnimation(
        scaleFactor: Float = 1.2f,
        duration: Long = 150,
        onClick: () -> Unit
    ) {
        this.setOnClickListener {
            // 禁用点击，防止动画未完成重复点击
            this.isEnabled = false

            // 立即执行逻辑
            onClick()

            // 播放动画
            this.animate()
                .scaleX(scaleFactor)
                .scaleY(scaleFactor)
                .setDuration(duration)
                .withEndAction {
                    this.animate()
                        .scaleX(1f)
                        .scaleY(1f)
                        .setDuration(duration)
                        .withEndAction {
                            // 动画结束恢复点击
                            this.isEnabled = true
                        }
                        .start()
                }
                .start()
        }
    }

    fun Int.dpToPx(context: Context): Int {
        return (this * context.resources.displayMetrics.density).toInt()
    }

    /**
     * 软键盘弹出
     */
    fun EditText.showKeyboard() {
        requestFocus()
        (context as? Activity)?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
        postDelayed({
            val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
        }, 200)
    }

    fun EditText.hideKeyboard() {
        clearFocus()
        postDelayed({
            val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
            imm?.hideSoftInputFromWindow(windowToken, 0)
        }, 200)

    }

    /**
     * 分享文件（自动识别 MIME 类型）
     * @param context 上下文
     * @param file 要分享的文件
     */
    fun shareFile(context: Context, file: File) {
        try {
            if (!file.exists()) {
                ToastUtils.show(context, context.getString(R.string.error_file_not_exist))
                return
            }

            val uri: Uri = FileProvider.getUriForFile(
                context,
                "${context.packageName}.fileprovider",
                file
            )

            val mimeType = getMimeType(file) ?: "*/*"

            val shareIntent = Intent(Intent.ACTION_SEND).apply {
                type = mimeType
                putExtra(Intent.EXTRA_STREAM, uri)
                addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            }

            context.startActivity(
                Intent.createChooser(shareIntent, "share")
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 分享多个文件（自动识别 MIME 类型）
     * @param context 上下文
     * @param files 要分享的文件列表
     */
    fun shareMultipleFiles(context: Context, files: List<File>) {
        try {
            if (files.isEmpty()) {
                ToastUtils.show(context, context.getString(R.string.error_file_not_exist))
                return
            }
            if (files.size == 1) {
                shareFile(context, files[0])
                return
            }

            // 过滤掉不存在的文件
            val validFiles = files.filter { it.exists() }
            if (validFiles.isEmpty()) {
                ToastUtils.show(context, context.getString(R.string.error_file_not_exist))
                return
            }

            val uris = ArrayList<Uri>()
            for (file in validFiles) {
                val uri = FileProvider.getUriForFile(
                    context,
                    "${context.packageName}.fileprovider",
                    file
                )
                uris.add(uri)
            }

            // 统一判断 MIME 类型（若不同类型，则用 "*/*"）
            val firstMime = getMimeType(validFiles.first())
            val allSameMime = validFiles.all { getMimeType(it) == firstMime }
            val mimeType = if (allSameMime) firstMime ?: "*/*" else "*/*"

            val shareIntent = Intent(Intent.ACTION_SEND_MULTIPLE).apply {
                type = mimeType
                putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
                addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            }

            context.startActivity(
                Intent.createChooser(shareIntent, "share")
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    /**
     * 根据文件扩展名自动获取 MIME 类型
     */
    private fun getMimeType(file: File): String? {
        val extension = file.extension.lowercase()
        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
    }

    /**
     * 打印 PDF 文件的方法
     *
     * @param context 上下文，用于访问系统服务和资源
     * @param uri 需要打印的 PDF 文件的 Uri
     * @return PrintResult 打印结果的状态（成功、密码保护、设备不支持等）
     */
    fun printPdfFile(context: Context, uri: Uri?): PrintResult {
        return try {
            // 打开文件描述符，用于访问 PDF 文件内容
            val pd = context.contentResolver.openFileDescriptor(
                uri!!,
                PDPageLabelRange.STYLE_ROMAN_LOWER
            )

            // 使用 PdfiumCore 尝试打开 PDF，如果无法打开会抛出异常
            PdfiumCore(context).newDocument(pd)

//            val tempFile = File(context.cacheDir, "temp_print.pdf")
//            PDDocument.load(context.contentResolver.openInputStream(uri), "").use { document ->
//                document.save(tempFile) // 保存解密后的 PDF，耗时操作，后续看是否做打印需要密码的PDF。
            //大概流程为：
            //1.先制造 PrintResult.PasswordRequired 的异常
            //2.输入密码后进行 PDDocument.load 带入密码加载pdf，保存在临时文件
            //3.把临时文件的地址传入到PrintPdfAdapter中进行系统的打印
//            }


            // 检查设备是否支持打印功能
            if (PrintHelper.systemSupportsPrint()) {
                // 获取系统的打印服务
                val printManager = context.getSystemService(Context.PRINT_SERVICE) as PrintManager

                // 设置打印任务名称（显示在打印队列中）
                val str = context.getString(R.string.app_name) + " Document"

                // 发起打印任务，传入自定义的 PrintDocumentAdapter
                printManager.print(
                    str,
                    PrintPdfAdapter(context, uri),
                    null as PrintAttributes? // 打印属性为空，使用系统默认配置
                )
                PrintResult.Success
            } else {
                // 设备不支持打印
                PrintResult.DeviceNotSupported
            }
        } catch (e: PdfPasswordException) {
            // 捕获 PDF 有密码保护的异常
            PrintResult.PasswordRequired
        } catch (e: IOException) {
            // 捕获 PDF 文件损坏或读取失败的异常
            PrintResult.MalformedPdf
        } catch (e: Exception) {
            // 捕获其他未知异常
            PrintResult.Error(e)
        }
    }


    fun generateFastThumbnail(
        context: Context,
        pdfFile: File,
        maxWidth: Int = 200,
        maxHeight: Int = 300
    ): String? {
        return try {
            val pdfiumCore = PdfiumCore(context)
            val fd = ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)
            val pdfDocument: PdfDocument = pdfiumCore.newDocument(fd)

            // 打开第一页
            pdfiumCore.openPage(pdfDocument, 0)

            // 获取原始页宽高
            val width = pdfiumCore.getPageWidthPoint(pdfDocument, 0)
            val height = pdfiumCore.getPageHeightPoint(pdfDocument, 0)

            // 计算缩略图尺寸
            val scale = minOf(maxWidth.toFloat() / width, maxHeight.toFloat() / height)
            val thumbWidth = (width * scale).toInt()
            val thumbHeight = (height * scale).toInt()

            val bitmap = createBitmap(thumbWidth, thumbHeight)
            bitmap.eraseColor(Color.WHITE) // 白底

            // 渲染第一页到 Bitmap
            pdfiumCore.renderPageBitmap(pdfDocument, bitmap, 0, 0, 0, thumbWidth, thumbHeight)

            // 保存到缓存
            val cacheDir = File(context.cacheDir, "thumbnails")
            if (!cacheDir.exists()) cacheDir.mkdirs()
            val thumbFile = File(cacheDir, pdfFile.nameWithoutExtension + ".jpg")
            FileOutputStream(thumbFile).use { out ->
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out)
            }

            pdfiumCore.closeDocument(pdfDocument)
            fd.close()

            thumbFile.absolutePath
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

    /**
     * 高亮文字，主要是搜索方面
     */
    fun String.toHighlightedSpannable(keyword: String, highlightColor: Int): SpannableString {
        val spannable = SpannableString(this)
        if (keyword.isBlank()) return spannable

        val regex = Regex(Pattern.quote(keyword), RegexOption.IGNORE_CASE)
        regex.findAll(this).forEach { matchResult ->
            spannable.setSpan(
                ForegroundColorSpan(highlightColor),
                matchResult.range.first,
                matchResult.range.last + 1,
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
            )
        }
        return spannable
    }


    /**
     * 打开图片文件（返回提示信息）
     *
     * @param context Context
     * @param file 要打开的图片文件
     * @return 提示信息
     */
    fun openImageFile(context: Context, file: File): String {
        return try {
            val uri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                FileProvider.getUriForFile(
                    context,
                    "${context.packageName}.fileprovider",
                    file
                )
            } else {
                Uri.fromFile(file)
            }

            val intent = Intent(Intent.ACTION_VIEW).apply {
                setDataAndType(uri, "image/*")
                addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }

            context.startActivity(Intent.createChooser(intent, context.getString(R.string.open)))
            "" // 成功返回空字符串
        } catch (e: ActivityNotFoundException) {
            context.getString(R.string.no_app_to_open_image)
        } catch (e: Exception) {
            e.printStackTrace()
            context.getString(R.string.failed_to_open_image)
        }
    }

    fun shareAppInfo(context: Context) {
        try {
            val appPackageName = context.packageName
            val packageManager = context.packageManager
            val appInfo = packageManager.getApplicationInfo(appPackageName, 0)

            // 获取应用名称，兼容 labelRes 为空的情况
            val appName = if (appInfo.labelRes != 0) {
                context.getString(appInfo.labelRes)
            } else {
                packageManager.getApplicationLabel(appInfo).toString()
            }

            // 应用链接（可自定义成其他市场链接）
            val appPlayStoreLink = "https://play.google.com/store/apps/details?id=$appPackageName"

            // 分享内容
            val shareMessage = "Check out $appName on Google Play:\n$appPlayStoreLink"

            // 构建 Intent
            val shareIntent = Intent(Intent.ACTION_SEND).apply {
                type = "text/plain"
                putExtra(Intent.EXTRA_SUBJECT, appName)
                putExtra(Intent.EXTRA_TEXT, shareMessage)
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }

            // 弹出系统分享面板
            val chooser = Intent.createChooser(shareIntent, "Share $appName")
            if (shareIntent.resolveActivity(packageManager) != null) {
                context.startActivity(chooser)
            } else {
                Toast.makeText(context, "No app available to share.", Toast.LENGTH_SHORT).show()
            }

        } catch (e: Exception) {
            e.printStackTrace()
            Toast.makeText(context, "Unable to share app info.", Toast.LENGTH_SHORT).show()
        }
    }
}