package com.fabledsword.minstrel.nav

import androidx.compose.runtime.staticCompositionLocalOf
import com.fabledsword.minstrel.models.AlbumRef
import com.fabledsword.minstrel.models.ArtistRef
import com.fabledsword.minstrel.models.PlaylistRef
import javax.inject.Inject
import javax.inject.Singleton

/**
 * In-memory hand-off for detail-screen "seed" data — the lightweight
 * Ref the caller already has when navigating to AlbumDetail /
 * ArtistDetail / PlaylistDetail. The detail VM peeks the seed on
 * init so the AppBar header (title / cover / counts) renders
 * immediately, before the network round-trip completes.
 *
 * Mirrors Flutter's go_router `extra:` parameter pattern. Bounded
 * per-bucket via insertion-order LRU so back/forward navigation
 * doesn't grow unbounded.
 */
@Singleton
class DetailSeedCache @Inject constructor() {
    private val albums = lru<AlbumRef>(MAX_ENTRIES)
    private val artists = lru<ArtistRef>(MAX_ENTRIES)
    private val playlists = lru<PlaylistRef>(MAX_ENTRIES)

    @Synchronized fun stashAlbum(ref: AlbumRef) { albums[ref.id] = ref }
    @Synchronized fun stashArtist(ref: ArtistRef) { artists[ref.id] = ref }
    @Synchronized fun stashPlaylist(ref: PlaylistRef) { playlists[ref.id] = ref }

    @Synchronized fun peekAlbum(id: String): AlbumRef? = albums[id]
    @Synchronized fun peekArtist(id: String): ArtistRef? = artists[id]
    @Synchronized fun peekPlaylist(id: String): PlaylistRef? = playlists[id]

    private companion object {
        private const val MAX_ENTRIES = 32
        private const val LOAD_FACTOR = 0.75f
        private fun <V> lru(max: Int): MutableMap<String, V> =
            object : LinkedHashMap<String, V>(max, LOAD_FACTOR, true) {
                override fun removeEldestEntry(eldest: Map.Entry<String, V>) = size > max
            }
    }
}

/**
 * CompositionLocal carrying the app's [DetailSeedCache]. Provided
 * at the [com.fabledsword.minstrel.MainActivity] root so any screen
 * can stash a seed before calling `navController.navigate(...)`.
 */
val LocalDetailSeedCache = staticCompositionLocalOf<DetailSeedCache> {
    error("DetailSeedCache not provided — wrap content in CompositionLocalProvider")
}
