package de.tsschulz.timeclock.ui.admin

import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import de.tsschulz.timeclock.data.admin.AdminRepository
import de.tsschulz.timeclock.data.api.HolidayDto
import de.tsschulz.timeclock.data.api.HolidayStateDto
import de.tsschulz.timeclock.data.api.RoleUserDto
import de.tsschulz.timeclock.data.api.TimeClockApiClient
import de.tsschulz.timeclock.data.auth.TokenStore
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

data class AdminUiState(
    val loading: Boolean = false,
    val error: String? = null,
    val success: String? = null,
    val holidayStates: List<HolidayStateDto> = emptyList(),
    val futureHolidays: List<HolidayDto> = emptyList(),
    val pastHolidays: List<HolidayDto> = emptyList(),
    val users: List<RoleUserDto> = emptyList(),
)

class AdminViewModel(
    private val repository: AdminRepository,
) : ViewModel() {
    private val _uiState = MutableStateFlow(AdminUiState())
    val uiState: StateFlow<AdminUiState> = _uiState.asStateFlow()

    fun loadPhase6(isAdmin: Boolean) {
        if (!isAdmin) return
        loadHolidays()
        loadRoles()
    }

    fun loadHolidays() = launchLoad {
        val holidays = repository.getHolidays()
        copy(
            holidayStates = repository.getHolidayStates(),
            futureHolidays = holidays.future,
            pastHolidays = holidays.past,
        )
    }

    fun createHoliday(date: String, hours: Double, description: String, stateIds: List<String>) = launchMutation("Feiertag gespeichert") {
        repository.createHoliday(date, hours, description, stateIds)
        loadHolidays()
    }

    fun deleteHoliday(id: String) = launchMutation("Feiertag gelöscht") {
        repository.deleteHoliday(id)
        loadHolidays()
    }

    fun loadRoles() = launchLoad {
        copy(users = repository.getRoleUsers())
    }

    fun updateUserRole(id: String, role: Int) = launchMutation("Rolle geändert") {
        repository.updateUserRole(id, role)
        loadRoles()
    }

    private fun launchLoad(reducer: suspend AdminUiState.() -> AdminUiState) {
        viewModelScope.launch {
            _uiState.update { it.copy(loading = true, error = null, success = null) }
            runCatching { _uiState.value.reducer() }
                .onSuccess { next -> _uiState.value = next.copy(loading = false, error = null) }
                .onFailure { e -> _uiState.update { it.copy(loading = false, error = e.message ?: "Daten konnten nicht geladen werden") } }
        }
    }

    private fun launchMutation(successMessage: String, block: suspend () -> Unit) {
        viewModelScope.launch {
            _uiState.update { it.copy(loading = true, error = null, success = null) }
            runCatching { block() }
                .onSuccess { _uiState.update { it.copy(success = successMessage) } }
                .onFailure { e -> _uiState.update { it.copy(error = e.message ?: "Aktion fehlgeschlagen") } }
            _uiState.update { it.copy(loading = false) }
        }
    }

    class Factory(private val application: Application) : ViewModelProvider.Factory {
        @Suppress("UNCHECKED_CAST")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            val tokenStore = TokenStore(application)
            return AdminViewModel(AdminRepository(TimeClockApiClient(tokenStore))) as T
        }
    }
}
