@file:Suppress("TooManyFunctions") // Compose screen + tab helpers + skeleton helpers

package com.fabledsword.minstrel.library.ui

import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryScrollableTabRow
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import com.fabledsword.minstrel.history.ui.HistoryTab
import com.fabledsword.minstrel.library.widgets.AlbumCard
import com.fabledsword.minstrel.library.widgets.ArtistCard
import com.fabledsword.minstrel.likes.ui.LikedTab
import com.fabledsword.minstrel.quarantine.ui.HiddenTab
import com.fabledsword.minstrel.models.AlbumRef
import com.fabledsword.minstrel.models.ArtistRef
import com.fabledsword.minstrel.nav.AlbumDetail
import com.fabledsword.minstrel.nav.ArtistDetail
import com.fabledsword.minstrel.nav.Library
import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Shuffle
import com.fabledsword.minstrel.shared.UiState
import com.fabledsword.minstrel.shared.widgets.ShellContentWindowInsets
import com.fabledsword.minstrel.shared.widgets.EmptyState
import com.fabledsword.minstrel.shared.widgets.ErrorRetry
import com.fabledsword.minstrel.shared.widgets.MinstrelTopAppBar
import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold
import com.fabledsword.minstrel.shared.widgets.SkeletonAlbumTile
import com.fabledsword.minstrel.shared.widgets.SkeletonArtistTile

/**
 * Library tab. Five-tab TabBar (Artists / Albums / History / Liked /
 * Hidden) matching `flutter_client/lib/library/library_screen.dart`.
 *
 * Artists + Albums are wired against the existing LibraryViewModel
 * (cache-first reads of cached_artists / cached_albums). The other
 * three tabs render placeholder EmptyStates pointing at the upcoming
 * data-layer phases:
 *   - History → Phase 9 (server-side /api/me/history wiring)
 *   - Liked   → Phase 8 (likes write path + cached_likes hydration)
 *   - Hidden  → Phase 10 (quarantine flag/unflag UI lives in Admin slice
 *               but the user-side "my hidden tracks" view comes here)
 */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LibraryScreen(
    navController: NavHostController,
    viewModel: LibraryViewModel = hiltViewModel(),
) {
    val tabs = LIBRARY_TABS
    // HorizontalPager owns the active-tab state — the TabRow reads
    // pagerState.currentPage and animateScrollToPage drives it on tap,
    // so swipe and tap stay in sync.
    val pagerState = rememberPagerState(pageCount = { tabs.size })
    val scope = rememberCoroutineScope()

    Scaffold(
        contentWindowInsets = ShellContentWindowInsets,
        modifier = Modifier.fillMaxSize(),
        topBar = {
            Column {
                MinstrelTopAppBar(
                    title = "Library",
                    navController = navController,
                    currentRouteName = Library::class.qualifiedName,
                    actions = {
                        IconButton(onClick = viewModel::shuffleAll) {
                            Icon(
                                imageVector = Lucide.Shuffle,
                                contentDescription = "Shuffle all",
                                tint = MaterialTheme.colorScheme.onSurface,
                            )
                        }
                    },
                )
                PrimaryScrollableTabRow(
                    selectedTabIndex = pagerState.currentPage,
                    edgePadding = 16.dp,
                ) {
                    tabs.forEachIndexed { index, label ->
                        Tab(
                            selected = pagerState.currentPage == index,
                            onClick = { scope.launch { pagerState.animateScrollToPage(index) } },
                            text = { Text(label) },
                        )
                    }
                }
            }
        },
    ) { inner ->
        HorizontalPager(
            state = pagerState,
            modifier = Modifier.fillMaxSize().padding(inner),
        ) { page ->
            when (page) {
                TAB_ARTISTS -> ArtistsTab(viewModel = viewModel, navController = navController)
                TAB_ALBUMS -> AlbumsTab(viewModel = viewModel, navController = navController)
                TAB_HISTORY -> HistoryTab(
                    onNavigateToAlbum = { id -> navController.navigate(AlbumDetail(id)) },
                    onNavigateToArtist = { id -> navController.navigate(ArtistDetail(id)) },
                )
                TAB_LIKED -> LikedTab(navController = navController)
                TAB_HIDDEN -> HiddenTab()
            }
        }
    }
}

private const val TAB_ARTISTS = 0
private const val TAB_ALBUMS = 1
private const val TAB_HISTORY = 2
private const val TAB_LIKED = 3
private const val TAB_HIDDEN = 4

private val LIBRARY_TABS = listOf("Artists", "Albums", "History", "Liked", "Hidden")

@Composable
private fun ArtistsTab(
    viewModel: LibraryViewModel,
    navController: NavHostController,
) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    PullToRefreshScaffold(onRefresh = { viewModel.refresh().join() }) {
        // Crossfade is keyed on `state::class` (not the whole state)
        // so a refresh that emits a fresh UiState.Success — same kind,
        // new data — doesn't re-fade the entire grid. Only Loading ↔
        // Success ↔ Error ↔ Empty transitions animate; row-level diff
        // is owned by LazyVerticalGrid via its item keys.
        Crossfade(targetState = state::class, label = "library-artists") { _ ->
            when (val s = state) {
                UiState.Loading -> SkeletonArtistsGrid()
                UiState.Empty -> EmptyState(
                    title = "No artists yet",
                    body = "Scan a folder in your server settings to " +
                        "populate the library.",
                )
                is UiState.Error -> ErrorRetry(
                    message = s.message,
                    onRetry = { viewModel.refresh() },
                )
                is UiState.Success -> ArtistsGrid(
                    artists = s.data.artists,
                    onArtistClick = { id -> navController.navigate(ArtistDetail(id)) },
                )
            }
        }
    }
}

@Composable
private fun AlbumsTab(
    viewModel: LibraryViewModel,
    navController: NavHostController,
) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    PullToRefreshScaffold(onRefresh = { viewModel.refresh().join() }) {
        Crossfade(targetState = state::class, label = "library-albums") { _ ->
            when (val s = state) {
                UiState.Loading -> SkeletonAlbumsGrid()
                UiState.Empty -> EmptyState(
                    title = "No albums yet",
                    body = "Scan a folder in your server settings to " +
                        "populate the library.",
                )
                is UiState.Error -> ErrorRetry(
                    message = s.message,
                    onRetry = { viewModel.refresh() },
                )
                is UiState.Success -> AlbumsGrid(
                    albums = s.data.albums,
                    onAlbumClick = { id -> navController.navigate(AlbumDetail(id)) },
                )
            }
        }
    }
}

@Composable
private fun ArtistsGrid(
    artists: List<ArtistRef>,
    onArtistClick: (String) -> Unit,
) {
    LazyVerticalGrid(
        // ArtistCard is 144dp wide; let the grid pack as many per row as
        // the device allows (3 on a typical phone, 5+ on tablets).
        columns = GridCells.Adaptive(minSize = 144.dp),
        contentPadding = PaddingValues(8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
    ) {
        items(items = artists, key = { it.id }) { artist ->
            ArtistCard(artist = artist, onClick = { onArtistClick(artist.id) })
        }
    }
}

@Composable
private fun AlbumsGrid(
    albums: List<AlbumRef>,
    onAlbumClick: (String) -> Unit,
) {
    LazyVerticalGrid(
        // AlbumCard is 176dp wide (144dp cover + 8dp gutters).
        columns = GridCells.Adaptive(minSize = 176.dp),
        contentPadding = PaddingValues(8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
    ) {
        items(items = albums, key = { it.id }) { album ->
            AlbumCard(album = album, onClick = { onAlbumClick(album.id) })
        }
    }
}

private const val SKELETON_GRID_TILES = 12

@Composable
private fun SkeletonArtistsGrid() {
    LazyVerticalGrid(
        columns = GridCells.Adaptive(minSize = 144.dp),
        contentPadding = PaddingValues(8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
        modifier = Modifier.fillMaxSize(),
    ) {
        items(SKELETON_GRID_TILES) { SkeletonArtistTile() }
    }
}

@Composable
private fun SkeletonAlbumsGrid() {
    LazyVerticalGrid(
        columns = GridCells.Adaptive(minSize = 176.dp),
        contentPadding = PaddingValues(8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
        modifier = Modifier.fillMaxSize(),
    ) {
        items(SKELETON_GRID_TILES) { SkeletonAlbumTile() }
    }
}
