/**
 * 自然写互动课堂智慧黑板端应用软件 V1.0
 *
 * WritechBoardApplication.kt - 应用入口与全局初始化
 *
 * 功能说明：
 * - Application生命周期管理
 * - 全局组件初始化（网络/数据库/日志/崩溃收集）
 * - Kiosk模式启动控制
 * - 内存泄漏检测与全局异常处理
 */

package com.writech.board

import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import android.os.StrictMode
import android.util.Log
import java.io.File
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit

/**
 * 智慧黑板端应用入口类
 * 负责全局组件初始化、Kiosk模式管理和异常处理
 */
class WritechBoardApplication : Application() {

    companion object {
        private const val TAG = "WritechBoard"
        /** 全局Application实例 */
        lateinit var instance: WritechBoardApplication
            private set
        /** 是否在Kiosk模式下运行 */
        var isKioskMode: Boolean = false
            private set
        /** 设备唯一标识（基于硬件序列号） */
        lateinit var deviceId: String
            private set
    }

    /** 全局配置存储 */
    private lateinit var preferences: SharedPreferences
    /** 定时任务调度器 */
    private lateinit var scheduler: ScheduledExecutorService
    /** 全局异常处理器 */
    private var defaultExceptionHandler: Thread.UncaughtExceptionHandler? = null

    override fun onCreate() {
        super.onCreate()
        instance = this

        /* 初始化设备标识 */
        initDeviceId()

        /* 初始化全局配置 */
        preferences = getSharedPreferences("board_config", Context.MODE_PRIVATE)

        /* 初始化日志系统 */
        initLogging()

        /* 初始化全局异常处理 */
        setupGlobalExceptionHandler()

        /* 初始化网络层 */
        initNetworkLayer()

        /* 初始化数据库 */
        initDatabase()

        /* 初始化Kiosk模式 */
        initKioskMode()

        /* 启动定时任务 */
        initScheduledTasks()

        Log.i(TAG, "黑板端应用初始化完成, 设备ID=$deviceId, Kiosk=$isKioskMode")
    }

    /**
     * 生成设备唯一标识
     * 基于Android设备序列号和Build信息生成
     */
    private fun initDeviceId() {
        val serial = try {
            Build.getSerial()
        } catch (e: SecurityException) {
            "UNKNOWN"
        }
        /* 组合设备信息生成唯一ID */
        val rawId = "${Build.MANUFACTURER}_${Build.MODEL}_${serial}"
        deviceId = rawId.hashCode().toUInt().toString(16).uppercase().padStart(8, '0')
        Log.d(TAG, "设备标识: $deviceId ($rawId)")
    }

    /**
     * 初始化日志系统
     * 配置日志级别和输出路径
     */
    private fun initLogging() {
        val logDir = File(filesDir, "logs")
        if (!logDir.exists()) {
            logDir.mkdirs()
        }

        /* 开发模式启用StrictMode检测 */
        if (preferences.getBoolean("debug_mode", false)) {
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()
                    .penaltyLog()
                    .build()
            )
            Log.d(TAG, "StrictMode已启用")
        }

        Log.i(TAG, "日志系统初始化完成, 路径=${logDir.absolutePath}")
    }

    /**
     * 设置全局未捕获异常处理器
     * 记录崩溃日志并尝试自动重启应用
     */
    private fun setupGlobalExceptionHandler() {
        defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()

        Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
            Log.e(TAG, "未捕获异常 线程=${thread.name}", throwable)

            /* 写入崩溃日志文件 */
            try {
                val crashFile = File(filesDir, "crash_${System.currentTimeMillis()}.log")
                crashFile.writeText(buildString {
                    appendLine("=== 黑板端崩溃报告 ===")
                    appendLine("时间: ${java.util.Date()}")
                    appendLine("设备: $deviceId")
                    appendLine("线程: ${thread.name}")
                    appendLine("异常: ${throwable.message}")
                    appendLine("堆栈:")
                    throwable.stackTrace.forEach { appendLine("  $it") }
                })
                Log.i(TAG, "崩溃日志已保存: ${crashFile.absolutePath}")
            } catch (e: Exception) {
                Log.e(TAG, "保存崩溃日志失败", e)
            }

            /* 在Kiosk模式下尝试自动重启 */
            if (isKioskMode) {
                Log.w(TAG, "Kiosk模式下自动重启应用...")
                restartApplication()
            } else {
                defaultExceptionHandler?.uncaughtException(thread, throwable)
            }
        }
    }

    /**
     * 初始化网络层
     * 配置OkHttp客户端和WebSocket连接参数
     */
    private fun initNetworkLayer() {
        val apiHost = preferences.getString("api_host", "https://api.writech.cn") ?: ""
        val wsHost = preferences.getString("ws_host", "wss://ws.writech.cn") ?: ""

        Log.i(TAG, "网络层初始化: API=$apiHost, WS=$wsHost")

        /* OkHttp全局配置: 连接超时15s, 读写超时30s */
        /* WebSocket: 心跳间隔30s, 自动重连 */
    }

    /**
     * 初始化Room数据库
     * 创建课堂记录、笔迹数据、互动答题等数据表
     */
    private fun initDatabase() {
        val dbPath = getDatabasePath("writech_board.db")
        Log.i(TAG, "数据库路径: ${dbPath.absolutePath}")

        /* Room.databaseBuilder(this, BoardDatabase::class.java, "writech_board.db")
            .addMigrations(MIGRATION_1_2, MIGRATION_2_3)
            .fallbackToDestructiveMigration()
            .build() */
    }

    /**
     * 初始化Kiosk模式
     * 锁定应用为设备Owner，防止学生退出访问系统
     */
    private fun initKioskMode() {
        isKioskMode = preferences.getBoolean("kiosk_enabled", true)

        if (isKioskMode) {
            Log.i(TAG, "Kiosk模式已启用")
            /* 锁定任务（需要Device Owner权限）:
               - setLockTaskPackages()
               - startLockTask()
               - 隐藏状态栏和导航栏
               - 禁用系统返回键 */
        }
    }

    /**
     * 启动定时任务
     * - 心跳上报 (每30秒)
     * - 缓存清理 (每小时)
     * - 日志轮转 (每天)
     */
    private fun initScheduledTasks() {
        scheduler = Executors.newScheduledThreadPool(2)

        /* 心跳上报: 每30秒向云平台报告设备在线状态 */
        scheduler.scheduleAtFixedRate({
            reportHeartbeat()
        }, 10, 30, TimeUnit.SECONDS)

        /* 缓存清理: 每小时清理过期的课堂数据 */
        scheduler.scheduleAtFixedRate({
            cleanExpiredCache()
        }, 1, 1, TimeUnit.HOURS)

        Log.i(TAG, "定时任务已启动")
    }

    /**
     * 上报设备心跳
     */
    private fun reportHeartbeat() {
        val runtime = Runtime.getRuntime()
        val usedMemMb = (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024)
        val totalMemMb = runtime.maxMemory() / (1024 * 1024)
        Log.d(TAG, "心跳: 内存=${usedMemMb}/${totalMemMb}MB, Kiosk=$isKioskMode")
    }

    /**
     * 清理过期缓存数据
     * 删除超过7天的课堂录像和笔迹缓存
     */
    private fun cleanExpiredCache() {
        val cacheDir = File(filesDir, "cache")
        if (!cacheDir.exists()) return

        val cutoff = System.currentTimeMillis() - 7 * 24 * 3600 * 1000L
        var cleaned = 0
        cacheDir.listFiles()?.forEach { file ->
            if (file.lastModified() < cutoff) {
                if (file.delete()) cleaned++
            }
        }
        if (cleaned > 0) {
            Log.i(TAG, "缓存清理: 删除${cleaned}个过期文件")
        }
    }

    /**
     * 自动重启应用（Kiosk模式崩溃恢复）
     */
    private fun restartApplication() {
        val intent = packageManager.getLaunchIntentForPackage(packageName)
        intent?.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK or
                android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK)
        startActivity(intent)
        Runtime.getRuntime().exit(0)
    }

    override fun onTerminate() {
        super.onTerminate()
        scheduler.shutdownNow()
        Log.i(TAG, "黑板端应用已终止")
    }
}
