package org.zaine.management.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.zaine.management.data.BackendRepository
import org.zaine.management.data.NetworkResult
import org.zaine.management.data.api.EveningCheckinRequest
import org.zaine.management.data.api.MorningCheckinRequest
import javax.inject.Inject

data class MorningUiState(
    val sleepHours: String = "",
    val fajr: Boolean = false,
    val quran: Boolean = false,
    val exercise: Boolean = false,
    val note: String = "",
    val loading: Boolean = false,
    val error: String? = null,
    val saved: Boolean = false
)

data class EveningUiState(
    val duties: Boolean = false,
    val zikr: Boolean = false,
    val salah: Boolean = false,
    val reflection: String = "",
    val loading: Boolean = false,
    val error: String? = null,
    val saved: Boolean = false
)

@HiltViewModel
class MorningViewModel @Inject constructor(
    private val repository: BackendRepository
) : ViewModel() {
    private val _state = MutableStateFlow(MorningUiState())
    val state: StateFlow<MorningUiState> = _state.asStateFlow()

    fun setSleepHours(value: String) = update { copy(sleepHours = value) }
    fun setFajr(value: Boolean) = update { copy(fajr = value) }
    fun setQuran(value: Boolean) = update { copy(quran = value) }
    fun setExercise(value: Boolean) = update { copy(exercise = value) }
    fun setNote(value: String) = update { copy(note = value) }

    fun submit() {
        val current = _state.value
        val sleepHours = current.sleepHours.toDoubleOrNull()
        if (sleepHours == null) {
            update { copy(error = "Enter sleep hours as a number") }
            return
        }
        viewModelScope.launch {
            update { copy(loading = true, error = null) }
            val request = MorningCheckinRequest(
                sleepHours = sleepHours,
                fajr = current.fajr,
                quran = current.quran,
                exercise = current.exercise,
                note = current.note.ifBlank { null }
            )
            when (val result = repository.submitMorning(request)) {
                is NetworkResult.Success -> update { copy(loading = false, saved = true) }
                is NetworkResult.Error -> update { copy(loading = false, error = result.message) }
                NetworkResult.Loading -> Unit
            }
        }
    }

    private fun update(block: MorningUiState.() -> MorningUiState) {
        _state.value = _state.value.block()
    }
}

@HiltViewModel
class EveningViewModel @Inject constructor(
    private val repository: BackendRepository
) : ViewModel() {
    private val _state = MutableStateFlow(EveningUiState())
    val state: StateFlow<EveningUiState> = _state.asStateFlow()

    fun setDuties(value: Boolean) = update { copy(duties = value) }
    fun setZikr(value: Boolean) = update { copy(zikr = value) }
    fun setSalah(value: Boolean) = update { copy(salah = value) }
    fun setReflection(value: String) = update { copy(reflection = value) }

    fun submit() {
        val current = _state.value
        viewModelScope.launch {
            update { copy(loading = true, error = null) }
            val request = EveningCheckinRequest(
                duties = current.duties,
                zikr = current.zikr,
                salah = current.salah,
                reflection = current.reflection.ifBlank { null },
            )
            when (val result = repository.submitEvening(request)) {
                is NetworkResult.Success -> update { copy(loading = false, saved = true) }
                is NetworkResult.Error -> update { copy(loading = false, error = result.message) }
                NetworkResult.Loading -> Unit
            }
        }
    }

    private fun update(block: EveningUiState.() -> EveningUiState) {
        _state.value = _state.value.block()
    }
}
