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 authRepository: auth.domain.repository.AuthRepository, private val signalrClient: ChatHubClient, private val serverConfig: ServerConfig, private val tokenManager: TokenManager ) : ViewModel() { private val _state = MutableStateFlow(ChatListState()) val state: StateFlow = _state.asStateFlow() init { updatePushToken() val isStoriesEnabled = try { serverConfig.getServerConfig().features.stories } catch (e: Exception) { true } _state.update { it.copy(isStoriesEnabled = isStoriesEnabled) } val token = tokenManager.getToken() val baseUrl = serverConfig.getBaseUrl() // Подключаемся к SignalR только если есть токен И введён URL сервера if (token != null && baseUrl.isNotBlank()) { signalrClient.connect(baseUrl.removeSuffix("/api/"), token) } loadChats() observeSignalREvents() } private fun updatePushToken() { com.google.firebase.messaging.FirebaseMessaging.getInstance().token.addOnCompleteListener { task -> if (task.isSuccessful) { val token = task.result viewModelScope.launch { try { authRepository.updatePushToken(token) } catch (e: Exception) { android.util.Log.e("ChatListVM", "Failed to update push token: ${e.message}") } } } } } 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) } } is ChatEvent.MessagesRead -> { if (event.userId == getCurrentUserId()) { _state.update { currentState -> val updatedChats = currentState.chats.map { chat -> if (chat.id == event.chatId) { chat.copy(unreadCount = 0) } else chat } currentState.copy(chats = sortChats(updatedChats)) } } } else -> Unit } } .launchIn(viewModelScope) } private fun updateChatsWithNewMessage(event: ChatEvent.NewMessage) { val baseUrl = serverConfig.getBaseUrl().removeSuffix("/api/") val currentUserId = getCurrentUserId() _state.update { currentState -> val updatedChats = currentState.chats.map { chat -> if (chat.id.equals(event.message.chatId, ignoreCase = true)) { val isMyMessage = event.message.senderId == currentUserId val isAlreadySeen = chat.lastMessage?.id == event.message.id val lastMsgDomain = event.message.toDomain(currentUserId, baseUrl) val newCount = if (isMyMessage || isAlreadySeen) { chat.unreadCount } else { chat.unreadCount + 1 } if (!isAlreadySeen) { android.util.Log.d("ChatListVM", "Message ${event.message.id} -> Count ${chat.unreadCount} -> $newCount") } chat.copy( lastMessage = lastMsgDomain, unreadCount = newCount ) } else chat } currentState.copy(chats = sortChats(updatedChats)) } } }