package agzam.vyatsu.ui.schedule import agzam.vyatsu.domain.ScheduleDates import agzam.vyatsu.domain.model.Schedule import agzam.vyatsu.domain.repository.PreferencesRepository import agzam.vyatsu.domain.repository.ScheduleRepository import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import java.time.LocalDate class ScheduleViewModel( private val scheduleRepository: ScheduleRepository, private val preferencesRepository: PreferencesRepository ) : ViewModel() { private val _uiState = MutableStateFlow(ScheduleUiState()) val uiState: StateFlow = _uiState.asStateFlow() private var currentGroupId: String? = null init { viewModelScope.launch { val groupId = preferencesRepository.selectedGroupId() if (groupId != null) { selectGroup(groupId) } else { _uiState.value = _uiState.value.copy(noGroup = true) } } } fun selectGroup(groupId: String) { currentGroupId = groupId viewModelScope.launch { preferencesRepository.setSelectedGroup(groupId) val savedWeekStart = runCatching { preferencesRepository.selectedWeekStart()?.let(LocalDate::parse) }.getOrNull() val savedDayDate = runCatching { preferencesRepository.selectedDayDate()?.let(LocalDate::parse) }.getOrNull() _uiState.value = _uiState.value.copy( noGroup = false, weekStart = savedWeekStart, dayDate = savedDayDate ) launch { scheduleRepository.observeSchedule(groupId).collect { schedule -> currentGroupId?.let { applySchedule(schedule) } } } launch { syncIfMissingToday(groupId) } } } private suspend fun applySchedule(schedule: Schedule?) { val current = _uiState.value if (schedule == null || schedule.periods.isEmpty()) { _uiState.value = current.copy(schedule = schedule, todayDate = null) return } val today = ScheduleDates.moscowToday() val todayDate = if (schedule.periodOf(today) != null) today else null val weekStart = when { schedule.periods.any { it.weekStart == current.weekStart } -> current.weekStart!! todayDate != null -> schedule.periodOf(todayDate)!!.weekStart else -> schedule.periods.first().weekStart } val period = schedule.periods.first { it.weekStart == weekStart } val weekDays = schedule.daysOf(period) val dayDate = when { weekDays.any { it.date == current.dayDate } -> current.dayDate weekDays.any { it.date == todayDate && todayDate != null } -> todayDate else -> weekDays.firstOrNull()?.date } preferencesRepository.setSelectedWeekStart(weekStart.toString()) dayDate?.let { preferencesRepository.setSelectedDayDate(it.toString()) } _uiState.value = current.copy( schedule = schedule, weekStart = weekStart, dayDate = dayDate, todayDate = todayDate ) } fun selectWeek(weekStart: LocalDate) { val state = _uiState.value val schedule = state.schedule ?: return val period = schedule.periods.firstOrNull { it.weekStart == weekStart } ?: return viewModelScope.launch { val today = ScheduleDates.moscowToday() val weekDays = schedule.daysOf(period) val dayDate = when { weekDays.any { it.date == today } -> today else -> weekDays.firstOrNull()?.date } preferencesRepository.setSelectedWeekStart(weekStart.toString()) dayDate?.let { preferencesRepository.setSelectedDayDate(it.toString()) } _uiState.value = _uiState.value.copy(weekStart = weekStart, dayDate = dayDate) } } fun selectDay(date: LocalDate) { val state = _uiState.value val schedule = state.schedule ?: return val period = schedule.periodOf(date) ?: return viewModelScope.launch { preferencesRepository.setSelectedWeekStart(period.weekStart.toString()) preferencesRepository.setSelectedDayDate(date.toString()) _uiState.value = _uiState.value.copy(weekStart = period.weekStart, dayDate = date) } } private suspend fun syncIfMissingToday(groupId: String) { val schedule = scheduleRepository.getSchedule(groupId) val today = ScheduleDates.moscowToday() val hasTodayPeriod = schedule?.periodOf(today) != null if (hasTodayPeriod) return _uiState.value = _uiState.value.copy(isSyncing = true) scheduleRepository.sync(groupId) _uiState.value = _uiState.value.copy(isSyncing = false) } fun switchGroup() { viewModelScope.launch { currentGroupId = null preferencesRepository.clearSelectedGroup() _uiState.value = _uiState.value.copy(noGroup = true) } } fun refresh() { val groupId = currentGroupId ?: return viewModelScope.launch { _uiState.value = _uiState.value.copy(isRefreshing = true) scheduleRepository.sync(groupId) _uiState.value = _uiState.value.copy(isRefreshing = false) } } fun clearAll() { val groupId = currentGroupId ?: return viewModelScope.launch { scheduleRepository.clearAll(groupId) } } fun clearSelectedPeriod() { val state = _uiState.value val schedule = state.schedule ?: return val weekStart = state.weekStart ?: return val period = schedule.periods.firstOrNull { it.weekStart == weekStart } ?: return viewModelScope.launch { scheduleRepository.clearPeriod(schedule.groupId, period) } } } data class ScheduleUiState( val noGroup: Boolean = false, val isRefreshing: Boolean = false, val isSyncing: Boolean = false, val schedule: Schedule? = null, val weekStart: LocalDate? = null, val dayDate: LocalDate? = null, val todayDate: LocalDate? = null )