package com.fabledsword.minstrel.player.output

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.stateIn
import javax.inject.Inject

/**
 * NowPlaying-scoped projection over [OutputPickerController]. The
 * controller is the long-lived Hilt singleton (its MediaRouter
 * callback must not churn with screen lifecycle); this ViewModel is
 * a thin lens over its [OutputPickerController.routesState] Flow
 * plus the sheet's visibility state.
 *
 * Sheet open/close are forwarded to the controller's discovery
 * toggle so active MediaRouter discovery only runs while the sheet
 * is actually visible.
 */
@HiltViewModel
class OutputPickerViewModel @Inject constructor(
    private val controller: OutputPickerController,
    private val activeUpnpHolder: ActiveUpnpHolder,
) : ViewModel() {

    val routes: StateFlow<RouteSnapshot> = controller.routesState
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(STOP_TIMEOUT_MS),
            initialValue = controller.routesState.value,
        )

    val activeUpnp: StateFlow<ActiveUpnp?> = activeUpnpHolder.active
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(STOP_TIMEOUT_MS), null)

    private val sheetVisibleInternal = MutableStateFlow(false)
    val sheetVisible: StateFlow<Boolean> = sheetVisibleInternal.asStateFlow()

    fun onChipTapped() {
        sheetVisibleInternal.value = true
        controller.upgradeDiscovery()
    }

    fun onSheetDismissed() {
        sheetVisibleInternal.value = false
        controller.downgradeDiscovery()
    }

    fun onRouteSelected(route: OutputRoute) {
        controller.select(route)
        sheetVisibleInternal.value = false
        controller.downgradeDiscovery()
    }

    private companion object {
        // SharingStarted timeout so quick screen-orientation changes
        // don't tear down + re-subscribe the controller's Flow.
        const val STOP_TIMEOUT_MS = 5_000L
    }
}
