Загрузка данных


package ru.notesapp.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import ru.notesapp.data.NotesRepository
import ru.notesapp.data.remote.NetworkResult
import ru.notesapp.domain.Note
import ru.notesapp.domain.NoteType
import javax.inject.Inject

@HiltViewModel
class NotesViewModel @Inject constructor(
    private val repository: NotesRepository,
) : ViewModel() {

    private val _uiState = MutableStateFlow<NotesUiState>(NotesUiState.Loading)
    val uiState: StateFlow<NotesUiState> = _uiState.asStateFlow()

    private val _isRefreshing = MutableStateFlow(false)
    val isRefreshing: StateFlow<Boolean> = _isRefreshing.asStateFlow()

    private val _snackbarMessage = MutableStateFlow<String?>(null)
    val snackbarMessage: StateFlow<String?> = _snackbarMessage.asStateFlow()

    private val _searchMode = MutableStateFlow(false)
    val searchMode: StateFlow<Boolean> = _searchMode.asStateFlow()

    private val _searchQuery = MutableStateFlow("")
    val searchQuery: StateFlow<String> = _searchQuery.asStateFlow()

    private var notesJob: Job? = null

    init {
        loadNotes()
    }

    fun loadNotes() {
        notesJob?.cancel()
        notesJob = viewModelScope.launch {
            _uiState.value = NotesUiState.Loading
            repository.observeAll().collect { notes ->
                _uiState.value = if (notes.isEmpty()) NotesUiState.Empty
                                  else NotesUiState.Success(notes)
            }
        }
    }

    fun refresh() {
        viewModelScope.launch {
            _isRefreshing.value = true
            when (val result = repository.refresh()) {
                is NetworkResult.Success -> {
                    // Берём актуальный список прямо из репозитория — он уже обновлён
                    val current = repository.observeAll().first()
                    _snackbarMessage.value = "Обновлено: ${current.size} заметок"
                }
                is NetworkResult.Error -> {
                    _snackbarMessage.value = "Ошибка сервера: ${result.code}"
                }
                is NetworkResult.NetworkError -> {
                    _snackbarMessage.value = "Нет соединения с интернетом"
                }
            }
            _isRefreshing.value = false
        }
    }

    fun addNote(
        title: String,
        content: String,
        type: NoteType,
        imageUrl: String? = null,
    ) {
        viewModelScope.launch {
            repository.add(
                Note(
                    id = 0L,
                    title = title,
                    content = content,
                    createdAt = System.currentTimeMillis(),
                    type = type,
                    imageUrl = imageUrl,
                )
            )
        }
    }

    fun updateNote(note: Note) {
        viewModelScope.launch {
            repository.update(note)
        }
    }

    fun deleteNote(id: Long) {
        viewModelScope.launch {
            repository.delete(id)
        }
    }

    fun openSearch() {
        _searchMode.value = true
    }

    fun closeSearch() {
        _searchMode.value = false
        _searchQuery.value = ""
        loadNotes()
    }

    fun searchNotes(query: String) {
        _searchQuery.value = query
        notesJob?.cancel()
        if (query.isBlank()) {
            loadNotes()
            return
        }
        notesJob = viewModelScope.launch {
            repository.search(query).collect { notes ->
                _uiState.value = if (notes.isEmpty()) NotesUiState.Empty
                                  else NotesUiState.Success(notes)
            }
        }
    }

    fun clearSnackbarMessage() {
        _snackbarMessage.value = null
    }
}