@file:Suppress("TooManyFunctions") // Compose screen + private helper composables

package com.fabledsword.minstrel.requests.ui

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.layout.size
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AssistChip
import androidx.compose.material3.Button
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
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.Disc3
import com.composables.icons.lucide.LibraryBig
import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Music
import com.composables.icons.lucide.Play
import com.composables.icons.lucide.X
import com.fabledsword.minstrel.models.RequestRef
import com.fabledsword.minstrel.models.RequestStatus
import com.fabledsword.minstrel.nav.AlbumDetail
import com.fabledsword.minstrel.shared.UiState
import com.fabledsword.minstrel.nav.ArtistDetail
import com.fabledsword.minstrel.nav.Requests
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.LoadingCentered
import com.fabledsword.minstrel.shared.widgets.MinstrelTopAppBar
import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold

@Composable
fun RequestsScreen(
    navController: NavHostController,
    viewModel: RequestsViewModel = hiltViewModel(),
) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    Scaffold(
        contentWindowInsets = ShellContentWindowInsets,
        modifier = Modifier.fillMaxSize(),
        topBar = {
            MinstrelTopAppBar(
                title = "Your requests",
                navController = navController,
                currentRouteName = Requests::class.qualifiedName,
                onBack = { navController.popBackStack() },
            )
        },
    ) { inner ->
        PullToRefreshScaffold(
            onRefresh = { viewModel.refresh().join() },
            modifier = Modifier.fillMaxSize().padding(inner),
        ) {
            when (val s = state) {
                UiState.Loading -> LoadingCentered()
                UiState.Empty -> EmptyState(
                    title = "Nothing requested yet",
                    body = "Use Discover to ask Lidarr for new music; your " +
                        "requests show up here.",
                )
                is UiState.Error -> ErrorRetry(
                    title = "Couldn't load requests",
                    message = s.message,
                    onRetry = { viewModel.refresh() },
                )
                is UiState.Success -> RequestList(
                    rows = s.data,
                    onCancel = viewModel::cancel,
                    onListen = { id -> navController.navigate(id) },
                )
            }
        }
    }
}

@Composable
private fun RequestList(
    rows: List<RequestRef>,
    onCancel: (String) -> Unit,
    onListen: (Any) -> Unit,
) {
    LazyColumn(modifier = Modifier.fillMaxSize()) {
        items(items = rows, key = { it.id }) { req ->
            RequestRow(
                req = req,
                onCancel = { onCancel(req.id) },
                onListen = req.listenRoute()?.let { route -> { onListen(route) } },
            )
            HorizontalDivider()
        }
    }
}

@Composable
private fun RequestRow(
    req: RequestRef,
    onCancel: () -> Unit,
    onListen: (() -> Unit)?,
) {
    var showCancelConfirm by remember { mutableStateOf(false) }
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp, vertical = 12.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        KindAvatar(kind = req.kind)
        RequestRowBody(req = req, modifier = Modifier.weight(1f))
        RequestRowAction(
            req = req,
            onListen = onListen,
            onAskCancel = { showCancelConfirm = true },
        )
    }
    if (showCancelConfirm) {
        CancelConfirmDialog(
            displayName = req.displayName,
            onConfirm = {
                showCancelConfirm = false
                onCancel()
            },
            onDismiss = { showCancelConfirm = false },
        )
    }
}

@Composable
private fun RequestRowBody(req: RequestRef, modifier: Modifier = Modifier) {
    Column(modifier = modifier) {
        Text(
            text = req.displayName,
            style = MaterialTheme.typography.bodyLarge,
            color = MaterialTheme.colorScheme.onSurface,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
        )
        Row(
            modifier = Modifier.padding(top = 4.dp),
            horizontalArrangement = Arrangement.spacedBy(6.dp),
        ) {
            StatusPill(status = req.status)
            KindPill(label = req.kind)
        }
        val progress = req.ingestProgressText()
        if (progress != null) {
            Text(
                text = progress,
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                modifier = Modifier.padding(top = 4.dp),
            )
        }
        if (req.status == RequestStatus.REJECTED && !req.notes.isNullOrEmpty()) {
            Text(
                text = req.notes,
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                modifier = Modifier.padding(top = 4.dp),
                maxLines = 2,
                overflow = TextOverflow.Ellipsis,
            )
        }
    }
}

@Composable
private fun RequestRowAction(
    req: RequestRef,
    onListen: (() -> Unit)?,
    onAskCancel: () -> Unit,
) {
    when {
        onListen != null -> OutlinedButton(onClick = onListen) {
            Icon(
                Lucide.Play,
                contentDescription = null,
                modifier = Modifier.size(16.dp).padding(end = 4.dp),
            )
            Text("Listen")
        }
        req.status == RequestStatus.PENDING -> TextButton(onClick = onAskCancel) {
            Icon(Lucide.X, contentDescription = null, modifier = Modifier.padding(end = 4.dp))
            Text("Cancel")
        }
    }
}

@Composable
private fun CancelConfirmDialog(
    displayName: String,
    onConfirm: () -> Unit,
    onDismiss: () -> Unit,
) {
    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text("Cancel request?") },
        text = { Text("Cancel “$displayName”? Lidarr will stop searching for it.") },
        confirmButton = {
            Button(onClick = onConfirm) { Text("Cancel request") }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) { Text("Keep") }
        },
    )
}

@Composable
private fun KindAvatar(kind: String) {
    // Flutter mapping: disc-3 for artist, library-big for album,
    // music for track. Mirrors lib/requests/requests_screen.dart.
    val icon = when (kind) {
        "artist" -> Lucide.Disc3
        "album" -> Lucide.LibraryBig
        "track" -> Lucide.Music
        else -> Lucide.Music
    }
    Icon(
        imageVector = icon,
        contentDescription = null,
        tint = MaterialTheme.colorScheme.onSurfaceVariant,
        modifier = Modifier.size(28.dp),
    )
}

/**
 * Most-specific listenable detail-screen route for a completed
 * request, or null when nothing's been matched / the status isn't
 * completed. Track-level matches resolve to AlbumDetail since the
 * client has no TrackDetail screen.
 */
private fun RequestRef.listenRoute(): Any? = when {
    status != RequestStatus.COMPLETED -> null
    !matchedAlbumId.isNullOrEmpty() -> AlbumDetail(matchedAlbumId)
    !matchedArtistId.isNullOrEmpty() -> ArtistDetail(matchedArtistId)
    else -> null
}

/**
 * "2 albums · 14 tracks ingested" — null when both counts are zero.
 * Singularization matches Flutter ("1 album · 1 track ingested").
 */
private fun RequestRef.ingestProgressText(): String? {
    if (importedAlbumCount == 0 && importedTrackCount == 0) return null
    val parts = buildList {
        if (importedAlbumCount > 0) {
            add(
                "$importedAlbumCount ${if (importedAlbumCount == 1) "album" else "albums"}",
            )
        }
        if (importedTrackCount > 0) {
            add(
                "$importedTrackCount ${if (importedTrackCount == 1) "track" else "tracks"}",
            )
        }
    }
    return "${parts.joinToString(" · ")} ingested"
}

@Composable
private fun StatusPill(status: RequestStatus) {
    val (label, isError) = when (status) {
        RequestStatus.PENDING -> "pending" to false
        RequestStatus.APPROVED -> "approved" to false
        RequestStatus.COMPLETED -> "completed" to false
        RequestStatus.REJECTED -> "rejected" to true
        RequestStatus.FAILED -> "failed" to true
        RequestStatus.UNKNOWN -> "unknown" to false
    }
    val color = if (isError) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary
    AssistChip(
        onClick = {},
        enabled = false,
        label = { Text(label, color = color) },
    )
}

@Composable
private fun KindPill(label: String) {
    AssistChip(
        onClick = {},
        enabled = false,
        label = {
            Text(
                label,
                style = MaterialTheme.typography.labelSmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
            )
        },
    )
}
