package com.all.pdfreader.pro.app.ui.act

import android.content.Context
import android.content.Intent
import android.media.MediaScannerConnection
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.Parcelable
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.all.pdfreader.pro.app.PRApp
import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.ActivityPdfSplitResultBinding
import com.all.pdfreader.pro.app.model.PdfPageItem
import com.all.pdfreader.pro.app.model.PdfPickerSource
import com.all.pdfreader.pro.app.model.PdfSelectedPagesItem
import com.all.pdfreader.pro.app.model.PdfSplitResultItem
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.ui.adapter.PdfResultAdapter
import com.all.pdfreader.pro.app.ui.dialog.PromptDialogFragment
import com.all.pdfreader.pro.app.util.AppUtils
import com.all.pdfreader.pro.app.util.AppUtils.dpToPx
import com.all.pdfreader.pro.app.util.AppUtils.generateFastThumbnail
import com.all.pdfreader.pro.app.util.FileUtils.toUnderscoreDateTime
import com.all.pdfreader.pro.app.util.PdfScanner
import com.all.pdfreader.pro.app.util.PdfSecurityUtils
import com.all.pdfreader.pro.app.util.PdfUtils
import com.all.pdfreader.pro.app.util.ToastUtils
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.Serializable

class PdfResultActivity : BaseActivity() {
    override val TAG: String = "PdfResultActivity"

    companion object {
        private const val EXTRA_SELECTED_LIST = "extra_selected_list"
        private const val EXTRA_FILE_LIST = "extra_file_list"
        private const val EXTRA_MERGE_LIST = "extra_merge_list"//合并传输使用的key
        private const val EXTRA_SOURCE = "extra_source"
        private const val EXTRA_LOCK_UNLOCK_PASSWORD = "extra_lock_unlock_password"
        private const val EXTRA_FILE_PATH = "extra_file_path"
        private const val EXTRA_SPLIT_PASSWORD = "extra_split_password"
        private const val EXTRA_PDF_TO_IMAGE_LIST = "extra_pdf_to_image_list"
        private const val EXTRA_PDF_TO_IMAGE_PASSWORD = "extra_pdf_to_image_password"

        fun createIntentSplitPdfActivityToResult(
            context: Context,
            list: ArrayList<PdfSelectedPagesItem>,
            source: PdfPickerSource,
            password: String? = null
        ): Intent {
            return Intent(context, PdfResultActivity::class.java).apply {
                putParcelableArrayListExtra(EXTRA_SELECTED_LIST, list)
                putExtra(EXTRA_SOURCE, source)
                putExtra(EXTRA_SPLIT_PASSWORD, password)
            }
        }

        fun createIntentInputFile(
            context: Context, list: ArrayList<String>, source: PdfPickerSource
        ): Intent {
            return Intent(context, PdfResultActivity::class.java).apply {
                putStringArrayListExtra(EXTRA_FILE_LIST, list)
                putExtra(EXTRA_SOURCE, source)
            }
        }

        fun createIntentMergePdfActivityToResult(
            context: Context, list: ArrayList<PdfDocumentEntity>, source: PdfPickerSource
        ): Intent {
            return Intent(context, PdfResultActivity::class.java).apply {
                putParcelableArrayListExtra(EXTRA_MERGE_LIST, list)
                putExtra(EXTRA_SOURCE, source)
            }
        }

        fun createIntentLock(
            context: Context, filepath: String, password: String, source: PdfPickerSource
        ): Intent {
            return Intent(context, PdfResultActivity::class.java).apply {
                putExtra(EXTRA_FILE_PATH, filepath)
                putExtra(EXTRA_LOCK_UNLOCK_PASSWORD, password)
                putExtra(EXTRA_SOURCE, source)
            }
        }

        fun createIntentPdfToImageActivityToResult(
            context: Context,
            filepath: String,
            list: ArrayList<PdfPageItem>,
            source: PdfPickerSource,
            password: String? = null
        ): Intent {
            return Intent(context, PdfResultActivity::class.java).apply {
                putExtra(EXTRA_FILE_PATH, filepath)
                putParcelableArrayListExtra(EXTRA_PDF_TO_IMAGE_LIST, list)
                putExtra(EXTRA_SOURCE, source)
                putExtra(EXTRA_PDF_TO_IMAGE_PASSWORD, password)
            }
        }
    }

    private lateinit var binding: ActivityPdfSplitResultBinding
    private lateinit var adapter: PdfResultAdapter
    private var resultList: MutableList<PdfSplitResultItem> = mutableListOf()
    private lateinit var source: PdfPickerSource
    private var isProcessing = false
    private var exitDialog: PromptDialogFragment? = null
    private val pdfRepository = getRepository()
    private lateinit var pdfScanner: PdfScanner
    private var isSaving = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityPdfSplitResultBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setupBackPressedCallback()
        source = getSerializableOrDefault(EXTRA_SOURCE, PdfPickerSource.NONE)
        if (source == PdfPickerSource.NONE) {
            showToast(getString(R.string.pdf_loading_failed))
            finish()
            return
        }
        pdfScanner = PdfScanner(this, pdfRepository)
        initView()
        setupClick()
        initData()
    }

    private fun initView() {
        adapter = PdfResultAdapter(resultList)
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.adapter = adapter
    }

    private fun initData() {
        lifecycleScope.launch(Dispatchers.IO) {
            withContext(Dispatchers.Main) {
                isProcessing = true
                binding.processingLayout.visibility = View.VISIBLE
            }
            if (source == PdfPickerSource.SPLIT) {
                val splitPassword = intent.getStringExtra(EXTRA_SPLIT_PASSWORD) ?: ""
                runOnUiThread {
                    binding.progressBar.isIndeterminate = false
                    binding.progressBar.progress = 0
                    binding.progressBar.max = 100
                    binding.okBtnTv.text = getString(R.string.open)
                }
                val selectedList: ArrayList<PdfSelectedPagesItem> =
                    requireParcelableArrayList(EXTRA_SELECTED_LIST)
                if (selectedList.isEmpty()) {
                    showToast(getString(R.string.pdf_loading_failed))
                    finish()
                    return@launch
                }
                val totalPages = selectedList.sumOf { it.pages.count { it.isSelected } }
                var processedPages = 0
                for (item in selectedList) {
                    val selectedPages = item.pages.filter { it.isSelected }
                    if (selectedPages.isEmpty()) continue
                    val splitInputFile = File(item.filePath)
                    val outputDir = File(
                        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
                        "PDFReaderPro/split"
                    ).apply { if (!exists()) mkdirs() }

                    PdfUtils.exportSelectedPages(
                        inputFile = splitInputFile,
                        selectedPages = selectedPages,
                        outputDir = outputDir,
                        outputFileName = "${item.fileName}.pdf",
                        onProgress = { _, _ -> // 不需要单文件百分比
                            processedPages++// 每页处理完成就加一，多个 PDF 顺序处理时，总进度线性递增
                            val percent = (processedPages.toFloat() / totalPages * 100).toInt()
                            lifecycleScope.launch(Dispatchers.Main) {
                                binding.progressTv.text = "$percent"
                                binding.progressBar.progress = percent
                            }
                        },
                        splitPassword
                    )?.let { resultFile ->
                        val thumbnails = generateFastThumbnail(this@PdfResultActivity, resultFile)
                        val result = PdfSplitResultItem(resultFile.absolutePath, thumbnails, false)
                        pdfScanner.addNewPdfToDatabase(result.filePath, result.thumbnailPath) {
                            resultList.add(result)
                        }
                    }
                }
            } else if (source == PdfPickerSource.MERGE) {
                runOnUiThread {
                    binding.progressBar.isIndeterminate = false
                    binding.progressBar.progress = 0
                    binding.progressBar.max = 100
                    binding.okBtnTv.text = getString(R.string.open)
                }
                val mergeInputFile: ArrayList<PdfDocumentEntity> =
                    requireParcelableArrayList(EXTRA_MERGE_LIST)
                if (mergeInputFile.isEmpty()) {
                    showToast(getString(R.string.pdf_loading_failed))
                    finish()
                    return@launch
                }
                val inputWithPasswords = mergeInputFile.map { pdf ->
                    File(pdf.filePath) to pdf.password
                }
                val outputDir = File(
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
                    "PDFReaderPro/merge"
                ).apply { if (!exists()) mkdirs() }
                val outputFileName =
                    getString(R.string.merge) + "_" + System.currentTimeMillis()
                        .toUnderscoreDateTime() + ".pdf"
                PdfUtils.mergePdfFilesWithPassword(
                    inputFiles = inputWithPasswords,
                    outputDir = outputDir,
                    outputFileName = outputFileName,
                    onProgress = { current, total ->
                        val progressPercent = current * 100 / total
                        lifecycleScope.launch(Dispatchers.Main) {
                            binding.progressBar.progress = progressPercent
                            binding.progressTv.text = "$progressPercent"
                        }
                    })?.let { resultFile ->
                    val thumbnails = generateFastThumbnail(this@PdfResultActivity, resultFile)
                    val result = PdfSplitResultItem(resultFile.absolutePath, thumbnails, false)
                    pdfScanner.addNewPdfToDatabase(result.filePath, result.thumbnailPath) {
                        resultList.add(result)
                    }
                }
            } else if (source == PdfPickerSource.LOCK) {
                val filepath = intent.getStringExtra(EXTRA_FILE_PATH) ?: ""
                if (filepath.isEmpty()) {
                    showToast(getString(R.string.pdf_loading_failed))
                    finish()
                    return@launch
                }
                val lockPassword = intent.getStringExtra(EXTRA_LOCK_UNLOCK_PASSWORD) ?: ""
                runOnUiThread {
                    binding.congratulationsDesc.text = getString(R.string.set_password_successfully)
                    binding.okBtnTv.text = getString(R.string.open)
                }
                PdfSecurityUtils.setPasswordToPdfWithProgress(
                    filepath, lockPassword, lockPassword
                ) { progress ->
                    binding.progressTv.text = "$progress"
                }.let { it ->
                    if (it) {
                        pdfRepository.updateIsPassword(filepath, true)
                    }
                    val result = PdfSplitResultItem(filePath = filepath, isPassword = true)
                    resultList.add(result)
                }
            } else if (source == PdfPickerSource.UNLOCK) {
                val filepath = intent.getStringExtra(EXTRA_FILE_PATH) ?: ""
                if (filepath.isEmpty()) {
                    showToast(getString(R.string.pdf_loading_failed))
                    finish()
                    return@launch
                }
                val unlockPassword = intent.getStringExtra(EXTRA_LOCK_UNLOCK_PASSWORD) ?: ""
                runOnUiThread {
                    binding.congratulationsDesc.text =
                        getString(R.string.remove_password_successfully)
                    binding.okBtnTv.text = getString(R.string.open)
                }
                PdfSecurityUtils.removePasswordFromPdfWithProgress(
                    filepath, unlockPassword
                ) { progress ->
                    binding.progressTv.text = "$progress"
                }?.let { it ->
                    val result = PdfSplitResultItem(
                        filePath = filepath, thumbnailPath = it, isPassword = false
                    )
                    resultList.add(result)
                }
            } else if (source == PdfPickerSource.IMAGES_TO_PDF) {
                val files = requireStringArrayList(EXTRA_FILE_LIST)
                if (files.isEmpty()) {
                    showToast(getString(R.string.pdf_loading_failed))
                    finish()
                    return@launch
                }
                runOnUiThread {
                    binding.okBtnTv.text = getString(R.string.open)
                }
                val inputFiles: List<File> = files.map { path -> File(path) }
                val outputDir = File(
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
                    "PDFReaderPro/img2Pdf"
                ).apply { if (!exists()) mkdirs() }
                val outputFileName = getString(R.string.app_name) + "_" + System.currentTimeMillis()
                    .toUnderscoreDateTime() + ".pdf"
                PdfUtils.imgToPdfFilesSafe(
                    inputFiles = inputFiles,
                    outputDir = outputDir,
                    outputFileName = outputFileName,
                    onProgress = { current, total ->
                        val progressPercent = current * 100 / total
                        runOnUiThread {
                            binding.progressBar.progress = progressPercent
                            binding.progressTv.text = "$progressPercent"
                        }
                    })?.let { resultFile ->
                    val thumbnails = generateFastThumbnail(this@PdfResultActivity, resultFile)
                    val result = PdfSplitResultItem(resultFile.absolutePath, thumbnails, false)
                    pdfScanner.addNewPdfToDatabase(result.filePath, result.thumbnailPath) {
                        resultList.add(result)
                    }
                }
            } else if (source == PdfPickerSource.PDF_TO_IMAGES) {
                val filepath = intent.getStringExtra(EXTRA_FILE_PATH) ?: ""
                if (filepath.isEmpty()) {
                    showToast(getString(R.string.pdf_loading_failed))
                    finish()
                    return@launch
                }
                runOnUiThread {
                    binding.congratulationsDesc.text = getString(R.string.converted_successfully)
                    binding.okBtnTv.text = getString(R.string.save_to_album)
                }
                val selectedPages: ArrayList<PdfPageItem> =
                    requireParcelableArrayList(EXTRA_PDF_TO_IMAGE_LIST)
                val pdfToImgPassword = intent.getStringExtra(EXTRA_PDF_TO_IMAGE_PASSWORD) ?: ""
                val outputDir = File(
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
                    "PDFReaderPro/pdf2Img"
                ).apply { if (!exists()) mkdirs() }
                PdfUtils.exportSelectedPagesToImages(
                    context = this@PdfResultActivity,
                    inputFile = File(filepath),
                    selectedPages = selectedPages,
                    outputDir = outputDir,
                    password = pdfToImgPassword,
                    onProgress = { current, total ->
                        val progressPercent = current * 100 / total
                        runOnUiThread {
                            binding.progressBar.progress = progressPercent
                            binding.progressTv.text = "$progressPercent"
                        }
                    }).let { resultFiles ->
                    if (resultFiles.isNotEmpty()) {
                        resultFiles.forEach {
                            val result = PdfSplitResultItem(it.absolutePath, it.absolutePath, false)
                            resultList.add(result)
                        }
                    }
                }
            } else if (source == PdfPickerSource.TO_LONG_IMAGE) {
                val filepath = intent.getStringExtra(EXTRA_FILE_PATH) ?: ""
                if (filepath.isEmpty()) {
                    showToast(getString(R.string.pdf_loading_failed))
                    finish()
                    return@launch
                }
                runOnUiThread {
                    binding.congratulationsDesc.text = getString(R.string.converted_successfully)
                    binding.okBtnTv.text = getString(R.string.save_to_album)
                }
                val selectedPages: ArrayList<PdfPageItem> =
                    requireParcelableArrayList(EXTRA_PDF_TO_IMAGE_LIST)
                val pdfToImgPassword = intent.getStringExtra(EXTRA_PDF_TO_IMAGE_PASSWORD) ?: ""
                val outputDir = File(
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
                    "PDFReaderPro/pdf2LongImg"
                ).apply { if (!exists()) mkdirs() }
                PdfUtils.exportPagesAsLongImage(
                    context = this@PdfResultActivity,
                    inputFile = File(filepath),
                    selectedPages = selectedPages,
                    outputDir = outputDir,
                    password = pdfToImgPassword,
                    onProgress = { current, total ->
                        val progressPercent = current * 100 / total
                        runOnUiThread {
                            binding.progressBar.progress = progressPercent
                            binding.progressTv.text = "$progressPercent"
                        }
                    }
                )?.let { file ->
                    val result = PdfSplitResultItem(file.absolutePath, file.absolutePath, false)
                    resultList.add(result)
                }
            }
            withContext(Dispatchers.Main) {
                binding.processingLayout.visibility = View.GONE
                if (resultList.isNotEmpty()) {
                    if (resultList.size == 1) {
                        binding.multipleImageLayout.visibility = View.GONE
                        binding.oneResultView.visibility = View.VISIBLE
                        binding.recyclerView.visibility = View.GONE
                        val item = resultList[0]
                        if (item.thumbnailPath != null) {
                            Glide.with(binding.root).load(File(item.thumbnailPath))
                                .transform(
                                    CenterCrop(),
                                    RoundedCorners(4.dpToPx(binding.root.context))
                                )
                                .into(binding.image)
                        }
                        if (item.isPassword) {
                            binding.lockLayout.visibility = View.VISIBLE
                        } else {
                            binding.lockLayout.visibility = View.GONE
                        }
                        binding.fileNameTv.text = File(item.filePath).name
                        binding.pathTv.text =
                            binding.root.context.getString(R.string.path_details, item.filePath)
                    } else {
                        if (source == PdfPickerSource.PDF_TO_IMAGES) {
                            binding.multipleImageLayout.visibility = View.VISIBLE
                            binding.oneResultView.visibility = View.GONE
                            binding.recyclerView.visibility = View.GONE
                            val item = resultList[0]
                            if (item.thumbnailPath != null) {
                                Glide.with(binding.root).load(File(item.thumbnailPath))
                                    .transform(
                                        CenterCrop(),
                                        RoundedCorners(4.dpToPx(binding.root.context))
                                    )
                                    .into(binding.multipleImage)
                            }
                            binding.multipleNumberTv.text = "${resultList.size}"
                            binding.multipleImageTv.text = getString(R.string.number_image_converted,resultList.size)
                        } else {
                            binding.multipleImageLayout.visibility = View.GONE
                            binding.oneResultView.visibility = View.GONE
                            binding.recyclerView.visibility = View.VISIBLE
                        }
                    }
                }
                // 默认选中第一个，只有一个也是第一个，所以点击的地方就不做修改了。就展示这里做修改
                if (resultList.isNotEmpty() && resultList.none { it.isSelected }) {
                    resultList[0].isSelected = true
                }
                adapter.updateAdapter()
                isProcessing = false
                exitDialog?.dismissAllowingStateLoss()
                exitDialog = null
            }
        }
    }

    private fun setupClick() {
        binding.backBtn.setOnClickListener {
            onBackPressedDispatcher.onBackPressed()
        }
        binding.shareBtn.setOnClickListener {
            if (source == PdfPickerSource.PDF_TO_IMAGES || source == PdfPickerSource.TO_LONG_IMAGE) {
                AppUtils.shareMultipleFiles(this, adapter.getAllFiles())
            } else {
                val selectedItem = adapter.getSelectedItem()
                selectedItem?.let {
                    AppUtils.shareFile(this, File(selectedItem.filePath))
                }
            }
        }
        binding.okBtn.setOnClickListener {
            if (source == PdfPickerSource.PDF_TO_IMAGES || source == PdfPickerSource.TO_LONG_IMAGE) {
                if (isSaving) return@setOnClickListener

                val imageFiles = adapter.getAllFiles()
                val triggered = addImagesToGallery(this, imageFiles)

                if (triggered) {
                    isSaving = true  // 触发过就不允许重复点击
                    //2秒后恢复按钮
                    binding.okBtn.postDelayed({ isSaving = false }, 2000)
                }
            } else {
                val selectedItem = adapter.getSelectedItem()
                selectedItem?.let {
                    val intent = PdfViewActivity.createIntent(this, selectedItem.filePath)
                    startActivity(intent)
                }
                finish()
            }
        }
    }

    override fun onResume() {
        super.onResume()
    }

    override fun onDestroy() {
        super.onDestroy()
        isProcessing = false
        exitDialog?.dismissAllowingStateLoss()
        exitDialog = null
    }

    private fun setupBackPressedCallback() {
        onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                if (isProcessing) {
                    exitDialog = PromptDialogFragment(
                        getString(R.string.exit_split),
                        getString(R.string.confirm_discard_changes),
                        getString(R.string.discard),
                        onOkClick = {
                            isEnabled = false
                            onBackPressedDispatcher.onBackPressed()
                        })
                    exitDialog?.show(supportFragmentManager, getString(R.string.exit_split))
                } else {
                    isEnabled = false
                    onBackPressedDispatcher.onBackPressed()
                }
            }
        })
    }

    @Suppress("DEPRECATION")
    private inline fun <reified T : Parcelable> requireParcelableArrayList(key: String): ArrayList<T> {
        val result: ArrayList<T>? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            intent.getParcelableArrayListExtra(key, T::class.java)
        } else {
            intent.getParcelableArrayListExtra(key)
        }
        return result ?: arrayListOf()
    }

    private fun requireStringArrayList(key: String): ArrayList<String> {
        val result: ArrayList<String>? =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                intent.getStringArrayListExtra(key)
            } else {
                @Suppress("DEPRECATION") intent.getStringArrayListExtra(key)
            }
        return result ?: arrayListOf()
    }

    private inline fun <reified T : Serializable> getSerializableOrDefault(
        key: String, default: T
    ): T {
        val result: T? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            intent.getSerializableExtra(key, T::class.java)
        } else {
            @Suppress("DEPRECATION") intent.getSerializableExtra(key) as? T
        }
        return result ?: default
    }

    /**
     * 将指定图片文件列表同步到系统相册，并返回是否成功触发操作
     *
     * @param context 上下文
     * @param imageFiles 要导入的图片文件列表
     * @return true 表示触发扫描成功，false 表示无有效图片
     */
    fun addImagesToGallery(context: Context, imageFiles: List<File>): Boolean {
        if (imageFiles.isEmpty()) {
            ToastUtils.show(context, context.getString(R.string.gallery_no_images_found))
            return false
        }

        // 过滤有效图片
        val validFiles = imageFiles.filter { file ->
            file.exists() && file.isFile && (
                    file.extension.equals("jpg", true) ||
                            file.extension.equals("jpeg", true) ||
                            file.extension.equals("png", true) ||
                            file.extension.equals("webp", true)
                    )
        }

        if (validFiles.isEmpty()) {
            ToastUtils.show(context, context.getString(R.string.gallery_no_images_found))
            return false
        }

        val paths = validFiles.map { it.absolutePath }.toTypedArray()

        // 扫描文件（异步触发系统媒体库）
        MediaScannerConnection.scanFile(context, paths, null) { path, uri ->
            Log.d("GallerySync", "Scanned: $path -> $uri")
        }

        ToastUtils.show(
            context,
            context.getString(R.string.gallery_saved_to_album, validFiles.size)
        )

        return true
    }

}