package com.fabledsword.minstrel.player.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.fabledsword.minstrel.likes.data.LikesRepository
import com.fabledsword.minstrel.player.PlayerController
import com.fabledsword.minstrel.player.PlayerUiState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * Thin ViewModel wrapping the singleton [PlayerController] so
 * Composables can `hiltViewModel()` it via the standard Compose
 * pattern. Both MiniPlayer and NowPlayingScreen instantiate one of
 * these; the underlying PlayerController is a process-singleton, so
 * each VM exposes the same `uiState`.
 *
 * Transport methods are thin pass-throughs — the indirection earns
 * its keep by giving testing seams later (a fake PlayerController
 * stub-test for ViewModel-level logic when it grows).
 */
@HiltViewModel
@Suppress("TooManyFunctions") // Thin transport facade — each fun forwards to PlayerController.
class PlayerViewModel @Inject constructor(
    private val controller: PlayerController,
    private val likes: LikesRepository,
) : ViewModel() {

    val uiState: StateFlow<PlayerUiState> = controller.uiState
    val dropEvents: SharedFlow<String> = controller.dropEvents

    /**
     * Reactive set of liked track ids — the set-based pattern the queue
     * (and playlist/album/artist detail) uses to color each row's
     * [com.fabledsword.minstrel.shared.widgets.LikeButton] without a
     * per-row Flow subscription.
     */
    val likedTrackIds: StateFlow<Set<String>> =
        likes.observeLikedTrackIds()
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(SHARE_STOP_TIMEOUT_MS),
                initialValue = emptySet(),
            )

    fun play() = controller.play()
    fun pause() = controller.pause()
    fun seekTo(positionMs: Long) = controller.seekTo(positionMs)
    fun skipToNext() = controller.skipToNext()
    fun skipToPrevious() = controller.skipToPrevious()
    fun seekToIndex(index: Int) = controller.seekToIndex(index)
    fun toggleShuffle() = controller.toggleShuffle()
    fun cycleRepeat() = controller.cycleRepeat()
    fun moveInQueue(from: Int, to: Int) = controller.moveInQueue(from, to)
    fun removeFromQueue(index: Int) = controller.removeFromQueue(index)
    fun clearQueue() = controller.clearQueue()

    fun toggleLikeTrack(trackId: String) {
        val desired = trackId !in likedTrackIds.value
        viewModelScope.launch {
            likes.toggleLike(LikesRepository.ENTITY_TRACK, trackId, desired)
        }
    }
}

private const val SHARE_STOP_TIMEOUT_MS = 5_000L
