package com.seven.ikar.kotlin.feature.mainmenu

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.seven.ikar.kotlin.app.AppContainer
import com.seven.ikar.kotlin.core.model.ChatSummaryDto
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

data class MainMenuUiState(
    val unreadChatsCount: Int = 0
)

class MainMenuViewModel(private val container: AppContainer) : ViewModel() {
    private val _uiState = MutableStateFlow(MainMenuUiState())
    val uiState: StateFlow<MainMenuUiState> = _uiState.asStateFlow()

    private var debounceJob: Job? = null
    private var refreshJob: Job? = null

    init {
        attachRealtime()
        loadCachedUnreadChatsCount()
        refresh()
    }

    fun refresh() {
        val currentSession = container.sessionStore.read()
        if (currentSession == null) {
            clear()
            return
        }

        refreshJob?.cancel()
        refreshJob = viewModelScope.launch {
            runCatching {
                container.executeAuthorized { session ->
                    val chats = container.apiClient.getChats(session.accessToken)
                    session.user.id to chats
                }
            }.onSuccess { (ownerUserId, chats) ->
                if (container.sessionStore.read()?.user?.id != ownerUserId) {
                    return@onSuccess
                }
                _uiState.value = MainMenuUiState(unreadChatsCount = countUnreadChats(chats))
                cacheChatList(ownerUserId, chats)
            }.onFailure {
                loadCachedUnreadChatsCount()
            }
        }
    }

    fun clear() {
        debounceJob?.cancel()
        refreshJob?.cancel()
        _uiState.value = MainMenuUiState()
    }

    private fun loadCachedUnreadChatsCount() {
        val session = container.sessionStore.read() ?: return
        val ownerUserId = session.user.id
        viewModelScope.launch(Dispatchers.IO) {
            val chats = runCatching {
                container.chatListCache.loadChats(ownerUserId)
            }.getOrDefault(emptyList())
            if (container.sessionStore.read()?.user?.id == ownerUserId) {
                _uiState.value = MainMenuUiState(unreadChatsCount = countUnreadChats(chats))
            }
        }
    }

    private fun cacheChatList(ownerUserId: String, chats: List<ChatSummaryDto>) {
        viewModelScope.launch(Dispatchers.IO) {
            runCatching { container.chatListCache.replaceChats(ownerUserId, chats) }
        }
    }

    private fun attachRealtime() {
        viewModelScope.launch {
            container.realtimeService.chatCreated.collect { scheduleRefresh() }
        }
        viewModelScope.launch {
            container.realtimeService.chatsChanged.collect { scheduleRefresh() }
        }
        viewModelScope.launch {
            container.realtimeService.messagesCreated.collect { scheduleRefresh() }
        }
        viewModelScope.launch {
            container.realtimeService.messagesUpdated.collect { scheduleRefresh() }
        }
    }

    private fun scheduleRefresh() {
        debounceJob?.cancel()
        debounceJob = viewModelScope.launch {
            delay(400)
            refresh()
        }
    }

    private fun countUnreadChats(chats: List<ChatSummaryDto>): Int =
        chats.count { chat -> chat.unreadCount > 0 }
}
