package com.fabledsword.minstrel.player.ui

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import com.composables.icons.lucide.ArrowDown
import com.composables.icons.lucide.ArrowLeft
import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Trash2
import com.fabledsword.minstrel.models.TrackRef
import com.fabledsword.minstrel.shared.widgets.EmptyState
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun QueueScreen(
    navController: NavHostController,
    viewModel: PlayerViewModel = hiltViewModel(),
) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    val likedTrackIds by viewModel.likedTrackIds.collectAsStateWithLifecycle()
    Scaffold(
        modifier = Modifier.fillMaxSize(),
        topBar = {
            TopAppBar(
                title = {
                    Column {
                        Text("Queue")
                        if (state.queue.isNotEmpty()) {
                            Text(
                                text = queueSummary(state.queue),
                                style = MaterialTheme.typography.bodySmall,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                        }
                    }
                },
                navigationIcon = {
                    IconButton(onClick = { navController.popBackStack() }) {
                        Icon(Lucide.ArrowLeft, contentDescription = "Back")
                    }
                },
                actions = {
                    if (state.queue.isNotEmpty()) {
                        IconButton(onClick = viewModel::clearQueue) {
                            Icon(Lucide.Trash2, contentDescription = "Clear queue")
                        }
                    }
                },
            )
        },
    ) { inner ->
        Box(modifier = Modifier.fillMaxSize().padding(inner)) {
            if (state.queue.isEmpty()) {
                EmptyState(
                    title = "Queue is empty",
                    body = "Pick a track from the library and it'll show up here.",
                )
            } else {
                QueueList(
                    tracks = state.queue,
                    currentIndex = state.queueIndex,
                    likedTrackIds = likedTrackIds,
                    onJumpTo = viewModel::seekToIndex,
                    onToggleLike = viewModel::toggleLikeTrack,
                    onMove = viewModel::moveInQueue,
                    onRemove = viewModel::removeFromQueue,
                )
            }
        }
    }
}

@Suppress("LongParameterList") // Compose list wiring — layout + queue callbacks, not logic.
@Composable
private fun QueueList(
    tracks: List<TrackRef>,
    currentIndex: Int,
    likedTrackIds: Set<String>,
    onJumpTo: (Int) -> Unit,
    onToggleLike: (String) -> Unit,
    onMove: (Int, Int) -> Unit,
    onRemove: (Int) -> Unit,
) {
    val listState = rememberLazyListState(
        initialFirstVisibleItemIndex = currentIndex.coerceIn(0, tracks.lastIndex),
    )
    val scope = rememberCoroutineScope()

    // Follow the now-playing row as the track auto-advances, but only while it's
    // near the visible window — if the user has scrolled away to browse, leave
    // them there (the pill offers the way back). Parity with the web queue.
    LaunchedEffect(currentIndex) {
        if (currentIndex < 0) return@LaunchedEffect
        val visible = listState.layoutInfo.visibleItemsInfo
        val first = visible.firstOrNull()?.index ?: 0
        val last = visible.lastOrNull()?.index ?: 0
        if (currentIndex in (first - 1)..(last + 1)) {
            listState.animateScrollToItem(currentIndex)
        }
    }

    val currentVisible by remember {
        derivedStateOf {
            listState.layoutInfo.visibleItemsInfo.any { it.index == currentIndex }
        }
    }

    Box(modifier = Modifier.fillMaxSize()) {
        LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
            itemsIndexed(items = tracks, key = { _, track -> track.id }) { index, track ->
                QueueRow(
                    track = track,
                    index = index,
                    queueSize = tracks.size,
                    isCurrent = index == currentIndex,
                    liked = track.id in likedTrackIds,
                    onClick = { onJumpTo(index) },
                    onToggleLike = { onToggleLike(track.id) },
                    onRemove = { onRemove(index) },
                    onMove = onMove,
                )
                HorizontalDivider()
            }
        }
        JumpToCurrentPill(
            visible = currentIndex >= 0 && !currentVisible,
            onClick = {
                scope.launch { listState.animateScrollToItem(currentIndex.coerceAtLeast(0)) }
            },
            modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = 16.dp),
        )
    }
}

@Composable
private fun JumpToCurrentPill(
    visible: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    AnimatedVisibility(visible = visible, modifier = modifier) {
        FilledTonalButton(onClick = onClick) {
            Icon(Lucide.ArrowDown, contentDescription = null, modifier = Modifier.size(18.dp))
            Spacer(modifier = Modifier.width(6.dp))
            Text("Jump to current")
        }
    }
}


/** "N tracks · 12 min" header summary. */
private fun queueSummary(tracks: List<TrackRef>): String {
    val minutes = tracks.sumOf { it.durationSec } / SECONDS_PER_MINUTE
    val length = if (minutes >= MINUTES_PER_HOUR) {
        "${minutes / MINUTES_PER_HOUR}h ${minutes % MINUTES_PER_HOUR}m"
    } else {
        "$minutes min"
    }
    val noun = if (tracks.size == 1) "track" else "tracks"
    return "${tracks.size} $noun · $length"
}

private const val SECONDS_PER_MINUTE = 60
private const val MINUTES_PER_HOUR = 60
