package dev.zxq5.chatapp.android.feature.settings

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dev.zxq5.chatapp.android.api.model.InviteRequest
import dev.zxq5.chatapp.android.api.model.QrResponse
import dev.zxq5.chatapp.android.core.error.ApiResult
import dev.zxq5.chatapp.android.data.repository.SettingsRepository
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class SettingsViewModel(private val settingsRepository: SettingsRepository) : ViewModel() {

    private val _is2faEnabled = MutableStateFlow(false)
    val is2faEnabled: StateFlow<Boolean> = _is2faEnabled

    private val _totpQr = MutableStateFlow<QrResponse?>(null)
    val totpQr: StateFlow<QrResponse?> = _totpQr

    private val _totpError = MutableStateFlow<String?>(null)
    val totpError: StateFlow<String?> = _totpError

    private val _settingsError = MutableStateFlow<String?>(null)
    val settingsError: StateFlow<String?> = _settingsError

    private val _isSuccessState = MutableStateFlow<Map<String, Boolean>>(emptyMap())
    val isSuccessState: StateFlow<Map<String, Boolean>> = _isSuccessState

    private val _lastInviteCode = MutableStateFlow<String?>(null)
    val lastInviteCode: StateFlow<String?> = _lastInviteCode

    fun clearMessages() {
        _settingsError.value = null
        _totpError.value = null
    }

    private fun triggerSuccess(key: String) {
        viewModelScope.launch {
            _isSuccessState.value = _isSuccessState.value + (key to true)
            delay(5000)
            _isSuccessState.value = _isSuccessState.value + (key to false)
        }
    }

    fun createInvite(request: InviteRequest) {
        viewModelScope.launch {
            _settingsError.value = null
            when (val result = settingsRepository.createInvite(request)) {
                is ApiResult.Success -> {
                    _lastInviteCode.value = result.data
                    triggerSuccess("invite")
                }
                is ApiResult.HttpError -> _settingsError.value = result.message
                is ApiResult.NetworkError -> _settingsError.value = result.message
            }
        }
    }

    fun fetchTotpStatus() {
        viewModelScope.launch {
            when (val result = settingsRepository.getTotpStatus()) {
                is ApiResult.Success -> _is2faEnabled.value = result.data.isEnabled
                else -> {}
            }
        }
    }

    fun fetchTotpQr(password: String) {
        viewModelScope.launch {
            _totpError.value = null
            when (val result = settingsRepository.getTotpQr(password)) {
                is ApiResult.Success -> {
                    _totpQr.value = result.data
                }
                is ApiResult.HttpError -> {
                    _totpError.value = result.message
                }
                is ApiResult.NetworkError -> {
                    _totpError.value = "Network error: ${result.message}"
                }
            }
        }
    }

    fun confirmTotp(code: String) {
        viewModelScope.launch {
            _totpError.value = null
            when (val result = settingsRepository.confirmTotp(code)) {
                is ApiResult.Success -> {
                    _is2faEnabled.value = true
                    _totpQr.value = null
                    triggerSuccess("2fa")
                }
                is ApiResult.HttpError -> {
                    _totpError.value = result.message
                }
                is ApiResult.NetworkError -> {
                    _totpError.value = "Network error: ${result.message}"
                }
            }
        }
    }

    fun disableTotp(password: String, totpCode: String) {
        viewModelScope.launch {
            _totpError.value = null
            when (val result = settingsRepository.disableTotp(password, totpCode)) {
                is ApiResult.Success -> {
                    _is2faEnabled.value = false
                    triggerSuccess("2fa")
                }
                is ApiResult.HttpError -> _totpError.value = result.message
                is ApiResult.NetworkError -> _totpError.value = "Network error: ${result.message}"
            }
        }
    }

    fun changePassword(old: String, new: String) {
        viewModelScope.launch {
            clearMessages()
            when (val result = settingsRepository.changePassword(old, new)) {
                is ApiResult.Success -> {
                    triggerSuccess("password")
                }
                is ApiResult.HttpError -> _settingsError.value = result.message
                is ApiResult.NetworkError -> _settingsError.value = "Network error: ${result.message}"
            }
        }
    }

    fun updateDisplayName(name: String?) {
        viewModelScope.launch {
            clearMessages()
            if (settingsRepository.updateDisplayName(name)) {
                triggerSuccess("display_name")
            } else {
                _settingsError.value = "Failed to update display name"
            }
        }
    }

    fun updateUsername(username: String) {
        viewModelScope.launch {
            clearMessages()
            when (val result = settingsRepository.updateUsername(username)) {
                is ApiResult.Success -> {
                    triggerSuccess("username")
                }
                is ApiResult.HttpError -> _settingsError.value = result.message
                is ApiResult.NetworkError -> _settingsError.value = "Network error: ${result.message}"
            }
        }
    }

    fun deleteAccount(password: String, totpCode: String?, onLogout: () -> Unit) {
        viewModelScope.launch {
            clearMessages()
            when (val result = settingsRepository.deleteAccount(password, totpCode)) {
                is ApiResult.Success -> {
                    _isSuccessState.value = _isSuccessState.value + ("delete" to true)
                    delay(3000)
                    onLogout()
                }
                is ApiResult.HttpError -> _settingsError.value = result.message
                is ApiResult.NetworkError -> _settingsError.value = "Network error: ${result.message}"
            }
        }
    }

    fun logout() {
        settingsRepository.logout()
    }
}
