package com.narutohuo.xindazhou.common.crash

import android.app.Application
import androidx.core.content.pm.PackageInfoCompat
import com.narutohuo.xindazhou.core.log.ILog
import java.io.File
import java.io.FileWriter
import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.util.*

/**
 * 崩溃收集管理器
 * 
 * 统一封装崩溃收集功能，自动捕获未处理的异常并记录
 * 
 * 使用方式：
 * ```kotlin
 * // Application 中初始化
 * CrashHelper.init(this) { throwable ->
 *     // 自定义崩溃处理（如上报到服务器）
 *     // 上报崩溃日志到服务器
 * }
 * 
 * // 手动记录异常
 * CrashHelper.logException(exception)
 * ```
 */
object CrashHelper {
    
    private const val TAG = "CrashHelper"
    private var application: Application? = null
    private var crashCallback: ((Throwable) -> Unit)? = null
    private var crashLogDir: File? = null
    private val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
    
    /**
     * 初始化崩溃收集
     * 
     * @param application Application 实例
     * @param crashLogDir 崩溃日志保存目录（可选，如果为 null 则使用应用缓存目录）
     * @param crashCallback 崩溃回调（可选，用于上报崩溃日志）
     */
    fun init(
        application: Application,
        crashLogDir: File? = null,
        crashCallback: ((Throwable) -> Unit)? = null
    ) {
        this.application = application
        this.crashLogDir = crashLogDir ?: application.cacheDir
        this.crashCallback = crashCallback
        
        // 设置全局异常处理器
        Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
            handleCrash(thread, throwable)
        }
        
        ILog.d(TAG, "崩溃收集已初始化，日志目录: ${this.crashLogDir?.absolutePath}")
    }
    
    /**
     * 处理崩溃
     */
    private fun handleCrash(thread: Thread, throwable: Throwable) {
        try {
            // 记录崩溃日志
            val crashLog = generateCrashLog(thread, throwable)
            saveCrashLog(crashLog)
            
            // 调用回调
            crashCallback?.invoke(throwable)
            
            // 记录日志
            ILog.e(TAG, "应用崩溃", throwable)
            ILog.e(TAG, "崩溃日志已保存")
        } catch (e: Exception) {
            ILog.e(TAG, "处理崩溃时发生异常", e)
        } finally {
            // 调用系统默认处理器（可选，如果需要显示系统崩溃对话框）
            // 如果需要自定义崩溃界面，可以不调用系统默认处理器
            val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
            if (defaultHandler !is Thread.UncaughtExceptionHandler || 
                defaultHandler.javaClass.name.contains("CrashHelper")) {
                // 如果已经是我们的处理器，不再调用系统默认处理器
            } else {
                // 调用系统默认处理器（会显示系统崩溃对话框）
                // defaultHandler.uncaughtException(thread, throwable)
            }
        }
    }
    
    /**
     * 生成崩溃日志
     */
    private fun generateCrashLog(thread: Thread, throwable: Throwable): String {
        val sb = StringBuilder()
        sb.append("========== 崩溃信息 ==========\n")
        sb.append("时间: ${dateFormat.format(Date())}\n")
        sb.append("线程: ${thread.name}\n")
        sb.append("异常类型: ${throwable.javaClass.name}\n")
        sb.append("异常消息: ${throwable.message}\n")
        sb.append("\n")
        sb.append("========== 堆栈信息 ==========\n")
        
        val sw = java.io.StringWriter()
        val pw = PrintWriter(sw)
        throwable.printStackTrace(pw)
        sb.append(sw.toString())
        
        sb.append("\n")
        sb.append("========== 设备信息 ==========\n")
        application?.let { app ->
            sb.append("应用版本: ${getAppVersion(app)}\n")
            sb.append("Android版本: ${android.os.Build.VERSION.RELEASE}\n")
            sb.append("设备型号: ${android.os.Build.MODEL}\n")
            sb.append("设备厂商: ${android.os.Build.MANUFACTURER}\n")
            sb.append("SDK版本: ${android.os.Build.VERSION.SDK_INT}\n")
        }
        
        sb.append("============================\n")
        
        return sb.toString()
    }
    
    /**
     * 保存崩溃日志到文件
     */
    private fun saveCrashLog(crashLog: String) {
        try {
            val logDir = crashLogDir ?: return
            if (!logDir.exists()) {
                logDir.mkdirs()
            }
            
            val fileName = "crash_${System.currentTimeMillis()}.log"
            val logFile = File(logDir, fileName)
            
            FileWriter(logFile).use { writer ->
                writer.write(crashLog)
                writer.flush()
            }
            
            ILog.d(TAG, "崩溃日志已保存: ${logFile.absolutePath}")
        } catch (e: Exception) {
            ILog.e(TAG, "保存崩溃日志失败", e)
        }
    }
    
    /**
     * 手动记录异常（用于捕获的异常）
     * 
     * @param throwable 异常对象
     */
    fun logException(throwable: Throwable) {
        try {
            val crashLog = generateCrashLog(Thread.currentThread(), throwable)
            saveCrashLog(crashLog)
            crashCallback?.invoke(throwable)
            ILog.e(TAG, "异常已记录", throwable)
        } catch (e: Exception) {
            ILog.e(TAG, "记录异常时发生错误", e)
        }
    }
    
    /**
     * 获取应用版本信息
     */
    private fun getAppVersion(application: Application): String {
        return try {
            val packageInfo = application.packageManager.getPackageInfo(application.packageName, 0)
            val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo)
            "${packageInfo.versionName} ($versionCode)"
        } catch (e: Exception) {
            "未知"
        }
    }
    
    /**
     * 获取所有崩溃日志文件
     * 
     * @return 崩溃日志文件列表
     */
    fun getAllCrashLogs(): List<File> {
        val logDir = crashLogDir ?: return emptyList()
        if (!logDir.exists()) {
            return emptyList()
        }
        
        return logDir.listFiles { _, name ->
            name.startsWith("crash_") && name.endsWith(".log")
        }?.toList() ?: emptyList()
    }
    
    /**
     * 清除所有崩溃日志
     */
    fun clearCrashLogs() {
        val logDir = crashLogDir ?: return
        if (!logDir.exists()) {
            return
        }
        
        getAllCrashLogs().forEach { it.delete() }
        ILog.d(TAG, "所有崩溃日志已清除")
    }
}

