package dev.ulfrx.recipe.user

import dev.ulfrx.recipe.auth.AuthSession
import dev.ulfrx.recipe.auth.AuthState
import dev.ulfrx.recipe.shared.dto.User
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

/**
 * Owns the current authenticated user as observable state.
 *
 * Subscribes to [AuthSession.state] for life: when auth flips to
 * [AuthState.Authenticated] it fetches `/me` via [fetchUser] once and emits
 * the result through [currentUser]. On [AuthState.Unauthenticated] it clears
 * [currentUser] so screens drop back to the login gate cleanly.
 *
 * The fetch is a `suspend () -> User` lambda rather than a wrapped gateway:
 * one consumer, one impl, no interface needed. When Phase 4 introduces a
 * SyncEngine with local + remote sources, extract the seam then.
 */
class UserRepository(
    private val authSession: AuthSession,
    private val fetchUser: suspend () -> User,
    scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default),
) {
    private val _currentUser = MutableStateFlow<User?>(null)
    val currentUser: StateFlow<User?> = _currentUser.asStateFlow()

    init {
        scope.launch {
            authSession.state
                .collect { state ->
                    when (state) {
                        is AuthState.Authenticated -> {
                            if (_currentUser.value == null) {
                                runCatching { fetchUser() }
                                    .onSuccess { user -> _currentUser.value = user }
                            }
                        }

                        AuthState.Unauthenticated -> {
                            _currentUser.value = null
                        }

                        AuthState.Loading -> {
                            Unit
                        }
                    }
                }
        }
    }

    suspend fun refresh() {
        runCatching { fetchUser() }
            .onSuccess { user -> _currentUser.value = user }
    }
}
