package com.fabledsword.minstrel.shared

import com.fabledsword.minstrel.api.ErrorCopy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.stateIn

private const val SHARE_STOP_TIMEOUT_MS = 5_000L

/**
 * Terminal operator for the cache-first VM idiom: a Flow that maps
 * cache emissions to `UiState.Success` / `UiState.Empty` becomes a
 * subscriber-active StateFlow that starts in [UiState.Loading] and
 * routes any upstream throwable through [ErrorCopy] into
 * [UiState.Error].
 *
 * Replaces the catch + stateIn(viewModelScope, WhileSubscribed,
 * Loading) tail that every cache-first ViewModel writes today.
 */
fun <T> Flow<UiState<T>>.asCacheFirstStateFlow(
    scope: CoroutineScope,
): StateFlow<UiState<T>> = this
    .catch { e -> emit(UiState.Error(ErrorCopy.fromThrowable(e))) }
    .stateIn(
        scope = scope,
        started = SharingStarted.WhileSubscribed(SHARE_STOP_TIMEOUT_MS),
        initialValue = UiState.Loading,
    )
