package com.fabledsword.minstrel.settings.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.fabledsword.minstrel.api.ErrorCopy
import com.fabledsword.minstrel.settings.data.MeRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

data class PasswordUiState(
    val current: String = "",
    val next: String = "",
    val confirm: String = "",
    val isChanging: Boolean = false,
    val message: String? = null,
)

/**
 * Backs the password-change card in Settings. Three-field form
 * (current / new / confirm) with client-side new==confirm check
 * before hitting [MeRepository.changePassword]. Inline status text
 * for both success and error.
 */
@HiltViewModel
class PasswordViewModel @Inject constructor(
    private val repository: MeRepository,
) : ViewModel() {

    private val internal = MutableStateFlow(PasswordUiState())
    val state: StateFlow<PasswordUiState> = internal.asStateFlow()

    fun setCurrent(value: String) = internal.update { it.copy(current = value, message = null) }
    fun setNext(value: String) = internal.update { it.copy(next = value, message = null) }
    fun setConfirm(value: String) = internal.update { it.copy(confirm = value, message = null) }

    fun change() {
        val s = internal.value
        val validationError: String? = when {
            s.isChanging -> "" // sentinel: silent no-op
            s.current.isEmpty() || s.next.isEmpty() -> "All fields required."
            s.next != s.confirm -> "New passwords do not match."
            else -> null
        }
        if (validationError != null) {
            if (validationError.isNotEmpty()) {
                internal.update { it.copy(message = validationError) }
            }
            return
        }
        viewModelScope.launch {
            internal.update { it.copy(isChanging = true, message = null) }
            try {
                repository.changePassword(current = s.current, next = s.next)
                internal.update {
                    PasswordUiState(message = "Password changed.")
                }
            } catch (
                @Suppress("TooGenericExceptionCaught") e: Throwable,
            ) {
                internal.update {
                    it.copy(
                        isChanging = false,
                        message = ErrorCopy.fromThrowable(e),
                    )
                }
            }
        }
    }
}
