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


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.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()

    // --- Состояние поиска живёт в ViewModel и переживает навигацию ---
    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 count = (uiState.value as? NotesUiState.Success)?.notes?.size ?: 0
                    _snackbarMessage.value = "Обновлено: $count заметок"
                }
                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 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
    }
}