package com.aiosman.ravenow.data.repo

import android.content.Context
import android.util.Log
import com.aiosman.ravenow.data.UserService
import com.aiosman.ravenow.data.UserServiceImpl
import com.aiosman.ravenow.data.db.MessageCacheDatabase
import com.aiosman.ravenow.data.db.TrtcParticipantCache
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.concurrent.ConcurrentHashMap

object TrtcUserTypeRepository {
    private const val TAG = "TrtcUserTypeRepo"
    private const val MAX_BATCH = 100
    private const val TTL_MS: Long = 5L * 24 * 60 * 60 * 1000 // 5 天

    private val memoryCache = ConcurrentHashMap<String, CacheEntry>()
    private var initialized = false
    private lateinit var userService: UserService
    private lateinit var db: com.aiosman.ravenow.data.db.MessageCacheDatabase

    data class CacheEntry(
        val isAI: Boolean,
        val updatedAt: Long
    ) {
        fun isExpired(now: Long): Boolean = now - updatedAt > TTL_MS
    }

    private fun ensureInit(context: Context) {
        if (!initialized) {
            db = MessageCacheDatabase.getInstance(context)
            userService = UserServiceImpl()
            initialized = true
        }
    }

    fun getCachedType(trtcId: String): Boolean? {
        val entry = memoryCache[trtcId] ?: return null
        return if (!entry.isExpired(System.currentTimeMillis())) entry.isAI else null
    }

    suspend fun getType(context: Context, trtcId: String): Boolean? {
        ensureInit(context)
        val now = System.currentTimeMillis()
        val mem = memoryCache[trtcId]
        if (mem != null && !mem.isExpired(now)) return mem.isAI

        return withContext(Dispatchers.IO) {
            val dao = db.trtcParticipantCacheDao()
            val entity = dao.get(trtcId)
            if (entity != null && now - entity.updatedAt <= TTL_MS) {
                memoryCache[trtcId] = CacheEntry(entity.isAI, entity.updatedAt)
                entity.isAI
            } else {
                null
            }
        }
    }

    suspend fun ensureTypes(context: Context, trtcIds: List<String>) {
        ensureInit(context)
        if (trtcIds.isEmpty()) return

        val now = System.currentTimeMillis()
        // 从内存/本地命中
        val toFetch = withContext(Dispatchers.IO) {
            val dao = db.trtcParticipantCacheDao()
            val result = mutableSetOf<String>()
            val needFromDb = mutableListOf<String>()

            trtcIds.forEach { id ->
                val mem = memoryCache[id]
                if (mem == null || mem.isExpired(now)) {
                    needFromDb.add(id)
                }
            }

            if (needFromDb.isNotEmpty()) {
                val entities = dao.getMany(needFromDb)
                val fromDbSet = entities.toMutableList()
                // 写回内存并决定是否需要网络
                val dbValid = mutableSetOf<String>()
                fromDbSet.forEach { e ->
                    if (now - e.updatedAt <= TTL_MS) {
                        memoryCache[e.trtcId] = CacheEntry(e.isAI, e.updatedAt)
                        dbValid.add(e.trtcId)
                    }
                }
                needFromDb.forEach { id ->
                    if (!dbValid.contains(id)) {
                        result.add(id)
                    }
                }
            }
            result.toList()
        }

        if (toFetch.isEmpty()) return

        // 批量分片请求
        val chunks = toFetch.chunked(MAX_BATCH)
        for (chunk in chunks) {
            try {
                val profiles = withContext(Dispatchers.IO) {
                    userService.getUserProfilesByTrtcUserIds(chunk, includeAI = true)
                }
                // 将返回的 profile 按 trtcUserId -> isAI 映射
                val upserts = profiles.mapNotNull { profile ->
                    val id = profile.trtcUserId
                    if (id.isNullOrEmpty()) null
                    else TrtcParticipantCache(
                        trtcId = id,
                        isAI = profile.aiAccount,
                        updatedAt = System.currentTimeMillis()
                    )
                }
                // 落库 + 内存
                withContext(Dispatchers.IO) {
                    db.trtcParticipantCacheDao().upsertAll(upserts)
                }
                upserts.forEach { e ->
                    memoryCache[e.trtcId] = CacheEntry(e.isAI, e.updatedAt)
                }
                Log.d(TAG, "Fetched types: size=${upserts.size}, batch=${chunk.size}")
            } catch (e: Exception) {
                Log.w(TAG, "ensureTypes fetch failed: ${e.message}")
            }
        }
    }
}


