package de.tsschulz.timeclock.ui.settings

import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import de.tsschulz.timeclock.data.api.InvitationDto
import de.tsschulz.timeclock.data.api.ProfileDto
import de.tsschulz.timeclock.data.api.StateDto
import de.tsschulz.timeclock.data.api.TimeClockApiClient
import de.tsschulz.timeclock.data.api.TimewishDto
import de.tsschulz.timeclock.data.api.WatcherDto
import de.tsschulz.timeclock.data.auth.TokenStore
import de.tsschulz.timeclock.data.settings.SettingsRepository
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 SettingsUiState(
    val loading: Boolean = false,
    val error: String? = null,
    val success: String? = null,
    val profile: ProfileDto? = null,
    val states: List<StateDto> = emptyList(),
    val timewishes: List<TimewishDto> = emptyList(),
    val invites: List<InvitationDto> = emptyList(),
    val watchers: List<WatcherDto> = emptyList(),
    val googleLinkUrl: String? = null,
)

class SettingsViewModel(
    private val repository: SettingsRepository,
) : ViewModel() {
    private val _uiState = MutableStateFlow(SettingsUiState())
    val uiState: StateFlow<SettingsUiState> = _uiState.asStateFlow()

    fun loadPhase5() {
        loadProfile()
    }

    fun loadProfile() = launchLoad {
        copy(profile = repository.getProfile(), states = repository.getStates())
    }

    fun updateProfile(fullName: String, stateId: String?, weekWorkdays: Int, dailyHours: Double, preferredTitleType: Int) = launchMutation("Profil gespeichert") {
        repository.updateProfile(fullName, stateId, weekWorkdays, dailyHours, preferredTitleType)
        loadProfile()
    }

    fun startGoogleLink() {
        viewModelScope.launch {
            _uiState.update { it.copy(loading = true, error = null, googleLinkUrl = null) }
            runCatching { repository.createGoogleLinkUrl() }
                .onSuccess { url -> _uiState.update { it.copy(loading = false, googleLinkUrl = url) } }
                .onFailure { e -> _uiState.update { it.copy(loading = false, error = e.message ?: "Google-Verknüpfung konnte nicht gestartet werden") } }
        }
    }

    fun consumeGoogleLinkUrl() {
        _uiState.update { it.copy(googleLinkUrl = null) }
    }

    fun changePassword(oldPassword: String, newPassword: String, confirmPassword: String) = launchMutation("Passwort geändert") {
        repository.changePassword(oldPassword, newPassword, confirmPassword)
    }

    fun loadTimewishes() = launchLoad {
        copy(timewishes = repository.getTimewishes())
    }

    fun createTimewish(day: Int, wishtype: Int, hours: Double?, startDate: String, endDate: String?) = launchMutation("Zeitwunsch gespeichert") {
        repository.createTimewish(day, wishtype, hours, startDate, endDate)
        loadTimewishes()
    }

    fun deleteTimewish(id: String) = launchMutation("Zeitwunsch gelöscht") {
        repository.deleteTimewish(id)
        loadTimewishes()
    }

    fun loadInvites() = launchLoad {
        copy(invites = repository.getInvites())
    }

    fun sendInvite(email: String) = launchMutation("Einladung gesendet") {
        repository.sendInvite(email)
        loadInvites()
    }

    fun loadWatchers() = launchLoad {
        copy(watchers = repository.getWatchers())
    }

    fun addWatcher(email: String) = launchMutation("Zugriff gespeichert") {
        repository.addWatcher(email)
        loadWatchers()
    }

    fun deleteWatcher(id: String) = launchMutation("Zugriff entfernt") {
        repository.deleteWatcher(id)
        loadWatchers()
    }

    private fun launchLoad(reducer: suspend SettingsUiState.() -> SettingsUiState) {
        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 SettingsViewModel(SettingsRepository(TimeClockApiClient(tokenStore))) as T
        }
    }
}
