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

import android.content.Context
import android.util.Log
import com.all.pdfreader.pro.app.PRApp
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.room.repository.PdfRepository
import com.all.pdfreader.pro.app.util.AppUtils.generateFastThumbnail
import com.all.pdfreader.pro.app.util.FileUtils.isPdfEncrypted
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import java.io.File
import java.util.concurrent.TimeUnit

class PdfScanner(
    private val context: Context, private val pdfRepository: PdfRepository
) {

    private val TAG = "ocean-PdfScanner"
    private val scanMutex = Mutex()
    suspend fun scanAndLoadPdfFiles(isNeedFullScan: Boolean, callback: (Boolean) -> Unit = {}) {
        if (!StoragePermissionHelper.hasBasicStoragePermission(context)) {
            LogUtil.logDebug(TAG, "权限不足")
            withContext(Dispatchers.Main) {
                callback.invoke(false)
            }
            return
        }
        scanMutex.withLock {// 保证同一时间只有一次扫描
            withContext(Dispatchers.IO) {
                try {
                    val startScannerTime = System.currentTimeMillis()
                    LogUtil.logDebug(TAG, "🔍开始扫描PDF文件...")
                    LogUtil.logDebug(TAG, "获取数据库数据")
                    val cachedDocs = pdfRepository.getAllDocumentsOnce()
                    var needFullScan = isNeedFullScan
                    if (!needFullScan) {
                        cachedDocs.forEach { doc ->
                            val file = File(doc.filePath)//得到数据库存储的文件路径
                            if (file.exists()) {
                                LogUtil.logDebug(TAG, "$file 文件存在，检测是否存在变化")
                                var needUpdate = false
                                var updatedDoc = doc.copy()
                                // 修改时间 与 文件大小
                                if (file.lastModified() != doc.lastModified || file.length() != doc.fileSize) {
                                    LogUtil.logDebug(
                                        TAG, "文件时间或者大小被修改 -> ${doc.fileName}"
                                    )
                                    updatedDoc = updatedDoc.copy(
                                        lastModified = file.lastModified(), fileSize = file.length()
                                    )
                                    needUpdate = true
                                }
                                if (needUpdate) {
                                    // 是否加密
                                    val currentIsPassword = isPdfEncrypted(file)
                                    if (doc.isPassword != currentIsPassword) {
                                        LogUtil.logDebug(TAG, "密码状态变化 -> ${doc.fileName}")
                                        updatedDoc = updatedDoc.copy(isPassword = currentIsPassword)
                                    }
                                    pdfRepository.insertOrUpdateDocument(updatedDoc)
                                    LogUtil.logDebug(TAG, "✅数据库已更新: ${doc.fileName}")

                                    // 异步生成缩略图，但要避免阻塞
                                    launch(Dispatchers.IO) {
                                        LogUtil.logDebug(TAG, "异步获取图片更新数据")
                                        val newThumbnail = generateFastThumbnail(context, file)
                                        if (newThumbnail != null && doc.thumbnailPath != newThumbnail) {
                                            pdfRepository.updateThumbnailPath(
                                                doc.filePath, newThumbnail
                                            )
                                            LogUtil.logDebug(TAG, "✅ 缩略图已更新")
                                        }
                                    }
                                }
                            } else {
                                // 文件不存在 → 删除数据库记录，并触发全盘扫描
                                LogUtil.logDebug(TAG, "文件不存在 -> ${doc.fileName}, 删除记录")
                                pdfRepository.deleteDocument(doc.filePath)
                                needFullScan = true
                            }
                        }
                    }
                    if (needFullScan || cachedDocs.isEmpty()) {
                        LogUtil.logDebug(TAG, "数据库不完整，执行全盘扫描...")
                        // 扫描应用私有目录（无需权限）
                        val privateFiles = FileUtils.scanPdfFiles(context)
                        LogUtil.logDebug(TAG, "📁应用私有目录找到: ${privateFiles.size} 个PDF文件")
                        // 扫描MediaStore（需要权限）
                        val mediaStoreFiles = FileUtils.scanPdfFilesFromMediaStore(context)
                        LogUtil.logDebug(TAG, "📱MediaStore找到: ${mediaStoreFiles.size} 个PDF文件")
                        // 合并并去重
                        val allFiles =
                            (privateFiles + mediaStoreFiles).distinctBy { it.absolutePath }
                        LogUtil.logDebug(TAG, "📊总计扫描到: ${allFiles.size} 个PDF文件")
                        // 处理每个PDF文件
                        allFiles.forEachIndexed { index, file ->
                            LogUtil.logDebug(
                                TAG,
                                "🔄处理文件 ${index + 1}/${allFiles.size}: ${file.name} - ${file.absolutePath}"
                            )
                            if (FileUtils.isPdfFile(file)) {
                                val existingDoc = pdfRepository.getDocumentByPath(file.absolutePath)
                                if (existingDoc == null) {
                                    LogUtil.logDebug(
                                        TAG, "🆕发现新PDF文件: ${file.name}"
                                    )
                                    val isPassword = isPdfEncrypted(file)
                                    LogUtil.logDebug(TAG, "isPassword->${isPassword}")

                                    val metadata =
                                        PdfMetadataExtractor.extractMetadata(file.absolutePath)
                                    val document = PdfDocumentEntity(
                                        filePath = file.absolutePath,
                                        fileName = file.name,
                                        fileSize = file.length(),
                                        lastModified = file.lastModified(),
                                        pageCount = metadata?.pageCount ?: 0,
                                        thumbnailPath = null,
                                        metadataTitle = metadata?.title,
                                        metadataAuthor = metadata?.author,
                                        metadataSubject = metadata?.subject,
                                        metadataKeywords = metadata?.keywords,
                                        metadataCreationDate = metadata?.creationDate?.time,
                                        metadataModificationDate = metadata?.modificationDate?.time,
                                        isPassword = isPassword
                                    )
                                    pdfRepository.insertOrUpdateDocument(document)
                                    LogUtil.logDebug(TAG, "    ✅ 已保存到数据库: ${file.name}")

                                    launch(Dispatchers.IO) {
                                        val newThumbnail = generateFastThumbnail(context, file)
                                        if (newThumbnail != null && document.thumbnailPath != newThumbnail) {
                                            pdfRepository.updateThumbnailPath(
                                                document.filePath, newThumbnail
                                            )
                                            LogUtil.logDebug(TAG, "✅ 缩略图已更新")
                                        }
                                    }
                                } else {
                                    LogUtil.logDebug(TAG, "  📋 文件已存在数据库: ${file.name}")
                                    // 🔹 文件已存在，检查是否需要更新
                                    var needUpdate = false
                                    var updatedDoc = existingDoc.copy()

                                    // 路径/修改时间更新
                                    if (existingDoc.filePath != file.absolutePath || existingDoc.lastModified != file.lastModified()) {
                                        LogUtil.logDebug(TAG, "✅ 路径/修改时间需要更新")
                                        updatedDoc = updatedDoc.copy(
                                            filePath = file.absolutePath,
                                            lastModified = file.lastModified()
                                        )
                                        needUpdate = true
                                    }

                                    // 是否加密更新
                                    val currentIsPassword = isPdfEncrypted(file)
                                    if (existingDoc.isPassword != currentIsPassword) {
                                        LogUtil.logDebug(TAG, "✅ 密码状态需要更新")
                                        updatedDoc = updatedDoc.copy(isPassword = currentIsPassword)
                                        needUpdate = true
                                    }

                                    // 执行更新
                                    if (needUpdate) {
                                        pdfRepository.insertOrUpdateDocument(updatedDoc)
                                        LogUtil.logDebug(TAG, "✅ 数据库已更新: ${file.name}")
                                    } else {
                                        LogUtil.logDebug(TAG, "⏩ 无需更新: ${file.name}")
                                    }

                                    launch(Dispatchers.IO) {
                                        LogUtil.logDebug(TAG, "异步获取图片更新数据")
                                        val newThumbnail = generateFastThumbnail(context, file)
                                        if (newThumbnail != null && existingDoc.thumbnailPath != newThumbnail) {
                                            pdfRepository.updateThumbnailPath(
                                                existingDoc.filePath, newThumbnail
                                            )
                                            LogUtil.logDebug(TAG, "✅ 缩略图已更新")
                                        }
                                    }
                                }
                            }
                        }
                        //最后过滤数据库的文件，文件不存在则删除记录，打印数据库中的总记录数
                        pdfRepository.getAllDocumentsOnce().forEach { doc ->
                            val file = File(doc.filePath)
                            if (!file.exists()) {
                                // 文件不存在 → 删除数据库记录
                                LogUtil.logDebug(
                                    TAG, "最终过滤：文件不存在 -> ${doc.fileName}, 删除记录"
                                )
                                pdfRepository.deleteDocument(doc.filePath)
                            } else {
                                LogUtil.logDebug(
                                    TAG,
                                    "    📖 ${doc.fileName} - ${doc.filePath} - ${doc.pageCount}页 - ${
                                        FileUtils.formatFileSize(
                                            doc.fileSize
                                        )
                                    } - ${doc.thumbnailPath}"
                                )
                            }
                        }
                    }
                    // 标记扫描完成
                    ScanManager.markScanComplete(context)
                    val lastScanTime = ScanManager.getLastScanTime(context)
                    LogUtil.logDebug(
                        TAG, "✅ 扫描完成，记录时间: ${java.util.Date(lastScanTime)}"
                    )
                    var string = if (needFullScan) {
                        "全盘扫描"
                    } else if (cachedDocs.isEmpty()) {
                        "数据库没有值，第一次全盘扫描"
                    } else {
                        "快速扫描"
                    }
                    // 计算扫描耗时
                    val scannerTime = System.currentTimeMillis() - startScannerTime
                    LogUtil.logDebug(
                        TAG, "$string 本次扫描耗时: $scannerTime ms (${scannerTime / 1000.0} 秒)"
                    )
                    PRApp.isNeedFullScan = false
                    withContext(Dispatchers.Main) {
                        callback.invoke(true)
                    }
                } catch (e: Exception) {
                    Log.e(TAG, "❌ 扫描出错: ${e.message}", e)
                    withContext(Dispatchers.Main) {
                        callback.invoke(false)
                    }
                }
            }
        }
    }

    /**
     * 添加单个pdf文件到数据库
     */
    suspend fun addNewPdfToDatabase(
        pathFile: String,
        thumbnailPath: String?,
        callback: (Boolean) -> Unit = {}
    ) {
        val file = File(pathFile)
        if (!file.exists() || !FileUtils.isPdfFile(file)) {
            LogUtil.logDebug(TAG, "文件不存在或不是PDF: $pathFile")
            withContext(Dispatchers.Main) {
                callback.invoke(false)
            }
            return
        }

        try {
            withContext(Dispatchers.IO) {
                val existingDoc = pdfRepository.getDocumentByPath(file.absolutePath)
                if (existingDoc == null) {
                    val isPassword = isPdfEncrypted(file)
                    val metadata = PdfMetadataExtractor.extractMetadata(file.absolutePath)

                    val document = PdfDocumentEntity(
                        filePath = file.absolutePath,
                        fileName = file.name,
                        fileSize = file.length(),
                        lastModified = file.lastModified(),
                        pageCount = metadata?.pageCount ?: 0,
                        thumbnailPath = thumbnailPath,
                        metadataTitle = metadata?.title,
                        metadataAuthor = metadata?.author,
                        metadataSubject = metadata?.subject,
                        metadataKeywords = metadata?.keywords,
                        metadataCreationDate = metadata?.creationDate?.time,
                        metadataModificationDate = metadata?.modificationDate?.time,
                        isPassword = isPassword
                    )

                    pdfRepository.insertOrUpdateDocument(document)
                    LogUtil.logDebug(TAG, "✅ 新PDF已保存到数据库: ${file.name}")

                    withContext(Dispatchers.Main) {
                        callback.invoke(true)
                    }
                } else {
                    Log.e(TAG, "数据库有已有相同的文件")
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "❌ 添加新PDF出错: ${e.message}", e)
            withContext(Dispatchers.Main) {
                callback.invoke(false)
            }
        }
    }

}