package com.hyperling.expensetracker

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class ExpenseViewModel (
    private val dao: ExpenseDao,
): ViewModel() {

    private val _sortType = MutableStateFlow(SortType.NAME)
    private val _state = MutableStateFlow(ExpenseState())

    private val _expenses = _sortType
        .flatMapLatest { sortType ->
            when(sortType) {
                SortType.NAME -> dao.selectExpensesName()
                SortType.COST -> dao.selectExpensesCost()
                SortType.RATE -> dao.selectExpensesRate()
            }
        }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())

    val state = combine(_state, _sortType, _expenses) { state, sortType, expenses ->
        state.copy(
            expenses = expenses,
            sortType = sortType
        )
    }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), ExpenseState())

    fun onEvent(event: ExpenseEvent) {
        when(event) {
            is ExpenseEvent.DeleteExpense -> {
                viewModelScope.launch {
                    dao.deleteExpense(event.expense)
                }
            }
            ExpenseEvent.HideDialog -> {
                _state.update { it.copy(
                    isAddingExpense = false
                ) }
            }
            ExpenseEvent.SaveExpense -> {
                val name = state.value.name
                val cost = state.value.cost
                val rate = state.value.rate

                if (name.isBlank()
                    || cost.isBlank()
                    //|| rate.isBlank() # TBD, enable this once Rate is working.
                ) {
                    return
                }

                val expense = Expense(name, cost, rate)

                viewModelScope.launch {
                    dao.upsertExpense(expense)
                }

                _state.update { it.copy(
                    isAddingExpense = false,
                    name = "",
                    cost = "",
                    rate = Rate.MONTHLY,
                ) }
            }
            is ExpenseEvent.SetName -> {
                _state.update { it.copy(
                    name = event.name
                ) }
            }
            is ExpenseEvent.SetCost -> {
                _state.update { it.copy(
                    cost = event.cost
                ) }
            }
            is ExpenseEvent.SetRate -> {
                _state.update { it.copy(
                    rate = event.rate
                ) }
            }
            ExpenseEvent.ShowDialog -> {
                _state.update { it.copy(
                    isAddingExpense = true
                ) }
            }
            is ExpenseEvent.SortExpenses -> {
                _sortType.value = event.sortType
            }
        }
    }
}