package com.fabledsword.minstrel.settings.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.fabledsword.minstrel.api.ErrorCopy
import com.fabledsword.minstrel.models.MyProfile
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 ProfileUiState(
    val isLoading: Boolean = true,
    val isSaving: Boolean = false,
    val displayName: String = "",
    val email: String = "",
    val loadedProfile: MyProfile? = null,
    val message: String? = null,
)

/**
 * Backs the Profile card in Settings. Fetches the caller's profile
 * on init via [MeRepository.getProfile]; submit calls
 * [MeRepository.updateProfile] and re-hydrates the form fields from
 * the canonical server response.
 *
 * Errors surface via [ProfileUiState.message] (inline status text
 * below the Save button) rather than snackbar so the card stays
 * self-contained — Settings doesn't host a screen-level Scaffold
 * snackbar for the form cards.
 */
@HiltViewModel
class ProfileViewModel @Inject constructor(
    private val repository: MeRepository,
) : ViewModel() {

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

    init {
        refresh()
    }

    fun setDisplayName(value: String) {
        internal.update { it.copy(displayName = value) }
    }

    fun setEmail(value: String) {
        internal.update { it.copy(email = value) }
    }

    fun refresh() {
        viewModelScope.launch {
            internal.update { it.copy(isLoading = true, message = null) }
            try {
                val profile = repository.getProfile()
                internal.update {
                    it.copy(
                        isLoading = false,
                        loadedProfile = profile,
                        displayName = profile.displayName.orEmpty(),
                        email = profile.email.orEmpty(),
                    )
                }
            } catch (
                @Suppress("TooGenericExceptionCaught") e: Throwable,
            ) {
                internal.update {
                    it.copy(
                        isLoading = false,
                        message = ErrorCopy.fromThrowable(e),
                    )
                }
            }
        }
    }

    fun save() {
        if (internal.value.isSaving) return
        viewModelScope.launch {
            internal.update { it.copy(isSaving = true, message = null) }
            try {
                val updated = repository.updateProfile(
                    displayName = internal.value.displayName.trim(),
                    email = internal.value.email.trim(),
                )
                internal.update {
                    it.copy(
                        isSaving = false,
                        loadedProfile = updated,
                        displayName = updated.displayName.orEmpty(),
                        email = updated.email.orEmpty(),
                        message = "Profile saved.",
                    )
                }
            } catch (
                @Suppress("TooGenericExceptionCaught") e: Throwable,
            ) {
                internal.update {
                    it.copy(
                        isSaving = false,
                        message = ErrorCopy.fromThrowable(e),
                    )
                }
            }
        }
    }
}
