package chats.presentation.chat_list import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import chats.domain.model.Chat import chats.domain.repository.ChatRepository import chats.data.remote.signalr.ChatHubClient import chats.data.remote.signalr.ChatEvent import core.network.ServerConfig import core.security.TokenManager import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import javax.inject.Inject import chats.data.repository.toDomain data class ChatListState( val chats: List = emptyList(), val isLoading: Boolean = false, val error: String? = null, val isStoriesEnabled: Boolean = true ) @HiltViewModel class ChatListViewModel @Inject constructor( private val repository: ChatRepository, private val signalrClient: ChatHubClient, private val serverConfig: ServerConfig, private val tokenManager: TokenManager ) : ViewModel() { private val _state = MutableStateFlow(ChatListState()) val state: StateFlow = _state.asStateFlow() init { val isStoriesEnabled = try { serverConfig.getServerConfig().features.stories } catch (e: Exception) { true } _state.update { it.copy(isStoriesEnabled = isStoriesEnabled) } val token = tokenManager.getToken() if (token != null) { val baseUrl = serverConfig.getBaseUrl().removeSuffix("/api/") signalrClient.connect(baseUrl, token) } loadChats() observeSignalREvents() } private fun getCurrentUserId(): String = tokenManager.getUserId() ?: "" fun loadChats() { viewModelScope.launch { _state.update { it.copy(isLoading = true) } try { val chats = repository.getChats() _state.update { it.copy(chats = sortChats(chats), isLoading = false) } } catch (e: Exception) { _state.update { it.copy(isLoading = false, error = e.message) } } } } private fun sortChats(chats: List): List { return chats.sortedWith(compareByDescending { it.name.equals("Избранное", ignoreCase = true) || it.name.equals("Saved Messages", ignoreCase = true) }.thenByDescending { it.lastMessage?.createdAt }) } private fun observeSignalREvents() { signalrClient.events .onEach { event -> when (event) { is ChatEvent.NewMessage -> { updateChatsWithNewMessage(event) } is ChatEvent.NewChat -> { val currentUserId = getCurrentUserId() val baseUrl = serverConfig.getBaseUrl().removeSuffix("/api/") _state.update { it.copy(chats = listOf(event.chat.toDomain(currentUserId, baseUrl)) + it.chats) } } else -> Unit } } .launchIn(viewModelScope) } private fun updateChatsWithNewMessage(event: ChatEvent.NewMessage) { val baseUrl = serverConfig.getBaseUrl().removeSuffix("/api/") _state.update { currentState -> val updatedChats = currentState.chats.map { chat -> if (chat.id == event.message.chatId) { chat.copy( lastMessage = event.message.toDomain(baseUrl), unreadCount = chat.unreadCount + 1 ) } else chat } currentState.copy(chats = sortChats(updatedChats)) } } }