package dev.ulfrx.recipe.ui.screens.auth

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dev.ulfrx.recipe.auth.AuthBrowser
import dev.ulfrx.recipe.auth.AuthLoginResult
import dev.ulfrx.recipe.auth.AuthSession
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.StringResource
import recipe.composeapp.generated.resources.Res
import recipe.composeapp.generated.resources.auth_error_cancelled
import recipe.composeapp.generated.resources.auth_error_network
import recipe.composeapp.generated.resources.auth_error_unknown

/**
 * Immutable UI state for [LoginScreen]. The [errorKey] is a Compose Resources
 * [StringResource] handle, not a translated string — the screen resolves it via
 * `stringResource(...)` so the ViewModel stays platform/locale agnostic.
 */
data class LoginScreenState(
    val isLoading: Boolean = false,
    val errorKey: StringResource? = null,
)

/**
 * Wraps [AuthSession] to drive the LoginScreen. The screen owns the
 * Lokksmith [AuthBrowser] (via `rememberAuthFlowLauncher` + [dev.ulfrx.recipe.auth.ComposeAuthBrowser])
 * and hands it in on click — the ViewModel never touches Compose or Lokksmith directly.
 *
 * Returns the launched [Job] from [onSignInClick] so tests can deterministically await
 * completion without dragging a TestDispatcher into commonTest.
 */
class LoginViewModel(
    private val authSession: AuthSession,
) : ViewModel() {
    private val _state = MutableStateFlow(LoginScreenState())
    val state: StateFlow<LoginScreenState> = _state.asStateFlow()

    fun onSignInClick(browser: AuthBrowser): Job {
        // Clear any previous inline error and enter the loading state before suspending —
        // contract from UI-SPEC: tapping the button again clears stale error text.
        _state.value = LoginScreenState(isLoading = true, errorKey = null)
        return viewModelScope.launch {
            val result = authSession.login(browser)
            _state.value =
                LoginScreenState(
                    isLoading = false,
                    errorKey = result.toErrorKeyOrNull(),
                )
        }
    }

    private fun AuthLoginResult.toErrorKeyOrNull(): StringResource? =
        when (this) {
            AuthLoginResult.Success -> null
            AuthLoginResult.Cancelled -> Res.string.auth_error_cancelled
            AuthLoginResult.NetworkError -> Res.string.auth_error_network
            is AuthLoginResult.Failed -> Res.string.auth_error_unknown
        }
}
