package com.fabledsword.minstrel.settings.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.fabledsword.minstrel.auth.AuthController
import com.fabledsword.minstrel.auth.AuthStore
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.combine
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

data class SettingsState(
    val serverUrl: String = "",
    val username: String = "",
    val isAdmin: Boolean = false,
    val isSigningOut: Boolean = false,
    val signedOut: Boolean = false,
    // M9: account debug flag (admin-set) + this device's local opt-out.
    val diagnosticsEnabledByAdmin: Boolean = false,
    val diagnosticsOptOut: Boolean = false,
)

@HiltViewModel
class SettingsViewModel @Inject constructor(
    private val authController: AuthController,
    private val authStore: AuthStore,
) : ViewModel() {

    private val transient = MutableStateFlow(TransientState())
    private val internal: MutableStateFlow<SettingsState> = MutableStateFlow(SettingsState())
    val state: StateFlow<SettingsState> = internal.asStateFlow()

    init {
        // Compose the user-visible state from the auth observables
        // (so cross-restart rehydration shows the right username) plus
        // the local sign-out spinner. Snapshotting currentUser at
        // construction time would miss the rehydration that arrives
        // microseconds after; collecting it keeps the card live.
        viewModelScope.launch {
            combine(
                authStore.baseUrl,
                authController.currentUser,
                authStore.diagnosticsOptOut,
                transient,
            ) { url, user, optOut, t ->
                SettingsState(
                    serverUrl = url,
                    username = user?.username.orEmpty(),
                    isAdmin = user?.isAdmin == true,
                    isSigningOut = t.isSigningOut,
                    signedOut = t.signedOut,
                    diagnosticsEnabledByAdmin = user?.debugModeEnabled == true,
                    diagnosticsOptOut = optOut,
                )
            }.collect { internal.value = it }
        }
    }

    /** Per-device opt-out of diagnostics while the account flag is on. */
    fun setDiagnosticsOptOut(optOut: Boolean) {
        authStore.setDiagnosticsOptOut(optOut)
    }

    fun signOut() {
        if (transient.value.isSigningOut) return
        viewModelScope.launch {
            transient.update { it.copy(isSigningOut = true) }
            authController.signOut()
            transient.update { it.copy(isSigningOut = false, signedOut = true) }
        }
    }

    fun consumeSignedOut() {
        transient.update { it.copy(signedOut = false) }
    }

    /** Local-only screen state that isn't owned by AuthStore/Controller. */
    private data class TransientState(
        val isSigningOut: Boolean = false,
        val signedOut: Boolean = false,
    )
}
