package id.iiyh.inatrading.feature.profile.presentation

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import id.iiyh.inatrading.feature.auth.domain.repository.AuthRepository
import javax.inject.Inject
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 ChangePasswordErrors(
    val oldPassword: String? = null,
    val newPassword: String? = null,
    val confirmPassword: String? = null,
)

data class ChangePasswordUiState(
    val oldPassword: String = "",
    val newPassword: String = "",
    val confirmPassword: String = "",
    val oldPasswordVisible: Boolean = false,
    val newPasswordVisible: Boolean = false,
    val confirmPasswordVisible: Boolean = false,
    val isSaving: Boolean = false,
    val isLoggedOut: Boolean = false,
    val infoMessage: String? = null,
    val errors: ChangePasswordErrors = ChangePasswordErrors(),
)

@HiltViewModel
class ChangePasswordViewModel @Inject constructor(
    private val authRepository: AuthRepository,
) : ViewModel() {

    private val _uiState = MutableStateFlow(ChangePasswordUiState())
    val uiState: StateFlow<ChangePasswordUiState> = _uiState.asStateFlow()

    fun onOldPasswordChange(value: String) {
        _uiState.update {
            it.copy(
                oldPassword = value,
                errors = it.errors.copy(oldPassword = null),
            )
        }
    }

    fun onNewPasswordChange(value: String) {
        _uiState.update {
            it.copy(
                newPassword = value,
                errors = it.errors.copy(newPassword = null, confirmPassword = null),
            )
        }
    }

    fun onConfirmPasswordChange(value: String) {
        _uiState.update {
            it.copy(
                confirmPassword = value,
                errors = it.errors.copy(confirmPassword = null),
            )
        }
    }

    fun toggleOldPasswordVisibility() {
        _uiState.update { it.copy(oldPasswordVisible = !it.oldPasswordVisible) }
    }

    fun toggleNewPasswordVisibility() {
        _uiState.update { it.copy(newPasswordVisible = !it.newPasswordVisible) }
    }

    fun toggleConfirmPasswordVisibility() {
        _uiState.update { it.copy(confirmPasswordVisible = !it.confirmPasswordVisible) }
    }

    fun onSaveClick(successMessage: String) {
        val state = _uiState.value
        val errors = validate(state)
        if (errors != ChangePasswordErrors()) {
            _uiState.update { it.copy(errors = errors) }
            return
        }

        viewModelScope.launch {
            _uiState.update {
                it.copy(
                    isSaving = true,
                    infoMessage = null,
                    errors = ChangePasswordErrors(),
                )
            }
            authRepository.changePassword(
                oldPassword = state.oldPassword,
                newPassword = state.newPassword,
            ).onSuccess {
                authRepository.logout()
                _uiState.update {
                    it.copy(
                        oldPassword = "",
                        newPassword = "",
                        confirmPassword = "",
                        isSaving = false,
                        isLoggedOut = true,
                        infoMessage = successMessage,
                    )
                }
            }.onFailure { error ->
                _uiState.update {
                    it.copy(
                        isSaving = false,
                        infoMessage = error.message ?: "Gagal mengubah kata sandi",
                    )
                }
            }
        }
    }

    fun consumeInfoMessage() {
        _uiState.update { it.copy(infoMessage = null) }
    }

    private fun validate(state: ChangePasswordUiState): ChangePasswordErrors {
        var oldPasswordError: String? = null
        var newPasswordError: String? = null
        var confirmPasswordError: String? = null

        if (state.oldPassword.isBlank()) {
            oldPasswordError = "required"
        }
        if (state.newPassword.isBlank()) {
            newPasswordError = "required"
        } else if (state.newPassword.length < 8) {
            newPasswordError = "min_length"
        } else if (state.newPassword == state.oldPassword) {
            newPasswordError = "must_differ"
        }
        if (state.confirmPassword != state.newPassword) {
            confirmPasswordError = "mismatch"
        }

        return ChangePasswordErrors(
            oldPassword = oldPasswordError,
            newPassword = newPasswordError,
            confirmPassword = confirmPasswordError,
        )
    }
}
