/**
 * 自然写互动课堂电视端应用软件 V1.0
 * Room数据库 - 本地数据缓存与持久化
 *
 * 功能说明：
 * 1. Room数据库定义（Entity、DAO、Database）
 * 2. 课堂笔迹数据缓存（当前课堂的实时笔迹）
 * 3. 学情报告本地缓存（减少网络请求）
 * 4. 课件资源元数据索引
 * 5. 设备配置持久化（网关绑定、显示设置）
 * 6. 数据库版本迁移
 */

package com.writech.tv.data

import android.content.Context
import android.util.Log
import java.util.concurrent.ConcurrentHashMap

/* ========== Entity定义 ========== */

/**
 * 课堂笔迹缓存实体
 * 缓存当前课堂接收到的学生笔迹数据
 */
data class StrokeCacheEntity(
    val id: String,                    // 记录ID
    val classroomId: String,           // 课堂ID
    val studentId: String,             // 学生ID
    val studentName: String,           // 学生姓名
    val pageId: Int,                   // 点阵纸页面ID
    val strokeData: String,            // 笔迹坐标JSON数据
    val strokeCount: Int,              // 笔画数量
    val collectTime: Long,             // 采集时间
    val thumbnailPath: String = ""     // 缩略图路径
)

/**
 * 学情报告缓存实体
 * 缓存从云端拉取的学情报告数据，避免频繁网络请求
 */
data class ReportCacheEntity(
    val studentId: String,             // 学生ID（联合主键）
    val subject: String,               // 科目（联合主键）
    val studentName: String,           // 学生姓名
    val overallScore: Double,          // 综合评分
    val writingScore: Double,          // 书写评分
    val knowledgeScore: Double,        // 知识掌握评分
    val reportJson: String,            // 完整报告JSON
    val cachedAt: Long                 // 缓存时间
)

/**
 * 课件资源元数据实体
 * 索引本地缓存的课件文件
 */
data class ResourceCacheEntity(
    val resourceId: String,            // 资源ID
    val title: String,                 // 资源标题
    val type: String,                  // 类型: ppt/pdf/image/copybook
    val subject: String,               // 科目
    val grade: String,                 // 年级
    val localPath: String,             // 本地文件路径
    val fileSize: Long,                // 文件大小（字节）
    val downloadTime: Long,            // 下载时间
    val lastAccessTime: Long,          // 最后访问时间
    val cloudUrl: String               // 云端原始URL
)

/**
 * 设备配置实体
 * 持久化TV端运行配置
 */
data class DeviceConfigEntity(
    val key: String,                   // 配置键
    val value: String,                 // 配置值
    val updatedAt: Long                // 更新时间
)

/* ========== DAO定义 ========== */

/**
 * 笔迹数据DAO - 管理笔迹缓存的增删改查
 */
class StrokeCacheDao {
    /** 内存缓存（模拟Room查询） */
    private val cache = ConcurrentHashMap<String, StrokeCacheEntity>()

    /** 插入笔迹缓存记录 */
    fun insert(entity: StrokeCacheEntity) {
        cache[entity.id] = entity
    }

    /** 批量插入 */
    fun insertAll(entities: List<StrokeCacheEntity>) {
        for (entity in entities) {
            cache[entity.id] = entity
        }
    }

    /** 按课堂ID查询所有笔迹 */
    fun getByClassroom(classroomId: String): List<StrokeCacheEntity> {
        return cache.values.filter { it.classroomId == classroomId }
            .sortedBy { it.collectTime }
    }

    /** 按学生ID查询笔迹 */
    fun getByStudent(classroomId: String, studentId: String): List<StrokeCacheEntity> {
        return cache.values.filter {
            it.classroomId == classroomId && it.studentId == studentId
        }.sortedBy { it.collectTime }
    }

    /** 获取课堂中所有有笔迹的学生ID列表 */
    fun getActiveStudentIds(classroomId: String): List<String> {
        return cache.values.filter { it.classroomId == classroomId }
            .map { it.studentId }
            .distinct()
    }

    /** 获取课堂笔迹总数 */
    fun getStrokeCount(classroomId: String): Int {
        return cache.values.filter { it.classroomId == classroomId }
            .sumOf { it.strokeCount }
    }

    /** 删除指定课堂的所有笔迹（课堂结束后清理） */
    fun deleteByClassroom(classroomId: String) {
        val keysToRemove = cache.entries
            .filter { it.value.classroomId == classroomId }
            .map { it.key }
        for (key in keysToRemove) {
            cache.remove(key)
        }
    }

    /** 清空所有缓存 */
    fun deleteAll() {
        cache.clear()
    }

    /** 获取缓存记录总数 */
    fun count(): Int = cache.size
}

/**
 * 学情报告DAO - 管理报告缓存
 */
class ReportCacheDao {
    private val cache = ConcurrentHashMap<String, ReportCacheEntity>()

    /** 键生成（studentId + subject） */
    private fun makeKey(studentId: String, subject: String) = "${studentId}_$subject"

    /** 插入或更新报告缓存 */
    fun upsert(entity: ReportCacheEntity) {
        cache[makeKey(entity.studentId, entity.subject)] = entity
    }

    /** 查询学生某科目的报告 */
    fun getReport(studentId: String, subject: String): ReportCacheEntity? {
        return cache[makeKey(studentId, subject)]
    }

    /** 查询学生所有科目的报告 */
    fun getStudentReports(studentId: String): List<ReportCacheEntity> {
        return cache.values.filter { it.studentId == studentId }
    }

    /** 获取所有缓存的学生报告摘要（按综合分数排序） */
    fun getAllReportsSorted(): List<ReportCacheEntity> {
        return cache.values.sortedByDescending { it.overallScore }
    }

    /** 清理过期缓存（超过指定时间的记录） */
    fun cleanExpired(maxAgeMs: Long): Int {
        val threshold = System.currentTimeMillis() - maxAgeMs
        val keysToRemove = cache.entries
            .filter { it.value.cachedAt < threshold }
            .map { it.key }
        for (key in keysToRemove) {
            cache.remove(key)
        }
        return keysToRemove.size
    }

    /** 清空所有缓存 */
    fun deleteAll() {
        cache.clear()
    }
}

/**
 * 资源缓存DAO
 */
class ResourceCacheDao {
    private val cache = ConcurrentHashMap<String, ResourceCacheEntity>()

    /** 插入资源记录 */
    fun insert(entity: ResourceCacheEntity) {
        cache[entity.resourceId] = entity
    }

    /** 按资源ID查询 */
    fun getById(resourceId: String): ResourceCacheEntity? {
        return cache[resourceId]
    }

    /** 按类型和科目查询 */
    fun getByTypeAndSubject(type: String, subject: String): List<ResourceCacheEntity> {
        return cache.values.filter { it.type == type && it.subject == subject }
            .sortedByDescending { it.lastAccessTime }
    }

    /** 获取最近访问的资源 */
    fun getRecent(limit: Int = 20): List<ResourceCacheEntity> {
        return cache.values.sortedByDescending { it.lastAccessTime }.take(limit)
    }

    /** 更新最后访问时间 */
    fun updateAccessTime(resourceId: String) {
        cache[resourceId]?.let { old ->
            cache[resourceId] = old.copy(lastAccessTime = System.currentTimeMillis())
        }
    }

    /** 获取缓存总大小（字节） */
    fun getTotalCacheSize(): Long {
        return cache.values.sumOf { it.fileSize }
    }

    /** 按LRU策略清理缓存（超出容量限制时删除最久未访问的） */
    fun evictLRU(maxSizeBytes: Long): List<String> {
        val evicted = mutableListOf<String>()
        var totalSize = getTotalCacheSize()

        if (totalSize <= maxSizeBytes) return evicted

        // 按最后访问时间排序，优先删除最旧的
        val sorted = cache.values.sortedBy { it.lastAccessTime }
        for (entity in sorted) {
            if (totalSize <= maxSizeBytes) break
            cache.remove(entity.resourceId)
            totalSize -= entity.fileSize
            evicted.add(entity.localPath)
        }
        return evicted
    }

    fun deleteAll() {
        cache.clear()
    }
}

/**
 * 设备配置DAO
 */
class DeviceConfigDao {
    private val configs = ConcurrentHashMap<String, DeviceConfigEntity>()

    /** 设置配置项 */
    fun set(key: String, value: String) {
        configs[key] = DeviceConfigEntity(key, value, System.currentTimeMillis())
    }

    /** 获取配置项 */
    fun get(key: String, defaultValue: String = ""): String {
        return configs[key]?.value ?: defaultValue
    }

    /** 删除配置项 */
    fun delete(key: String) {
        configs.remove(key)
    }

    /** 获取所有配置 */
    fun getAll(): Map<String, String> {
        return configs.mapValues { it.value.value }
    }
}

/* ========== Database定义 ========== */

/**
 * TV端本地数据库
 * 聚合所有DAO，提供统一的数据访问入口
 */
class TvDatabase private constructor(context: Context) {

    companion object {
        private const val TAG = "TvDatabase"
        private const val DB_VERSION = 2

        @Volatile
        private var instance: TvDatabase? = null

        /** 获取数据库单例 */
        fun getInstance(context: Context): TvDatabase {
            return instance ?: synchronized(this) {
                instance ?: TvDatabase(context.applicationContext).also {
                    instance = it
                }
            }
        }
    }

    /** 笔迹缓存DAO */
    val strokeDao = StrokeCacheDao()

    /** 报告缓存DAO */
    val reportDao = ReportCacheDao()

    /** 资源缓存DAO */
    val resourceDao = ResourceCacheDao()

    /** 设备配置DAO */
    val configDao = DeviceConfigDao()

    init {
        Log.i(TAG, "数据库初始化完成，版本: $DB_VERSION")
    }

    /** 获取数据库统计信息 */
    fun getStatistics(): Map<String, Any> {
        return mapOf(
            "stroke_records" to strokeDao.count(),
            "resource_cache_size" to resourceDao.getTotalCacheSize(),
            "db_version" to DB_VERSION
        )
    }

    /** 清理所有缓存数据 */
    fun clearAllCaches() {
        strokeDao.deleteAll()
        reportDao.deleteAll()
        resourceDao.deleteAll()
        Log.i(TAG, "所有缓存已清理")
    }

    /** 定期维护（清理过期数据） */
    fun performMaintenance() {
        // 清理超过7天的报告缓存
        val reportCleaned = reportDao.cleanExpired(7L * 24 * 60 * 60 * 1000)
        // 清理超出500MB的资源缓存
        val evicted = resourceDao.evictLRU(500L * 1024 * 1024)

        Log.i(TAG, "数据库维护完成: 清理报告${reportCleaned}条, 清理资源${evicted.size}个")
    }
}
