package com.fabledsword.minstrel.playlists.widgets

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.ListMusic
import com.composables.icons.lucide.Lucide
import com.fabledsword.minstrel.models.PlaylistRef
import com.fabledsword.minstrel.nav.LocalDetailSeedCache
import com.fabledsword.minstrel.shared.widgets.CoverTile
import com.fabledsword.minstrel.shared.widgets.PlayCircleButton
import com.fabledsword.minstrel.theme.FabledSwordFlatTokens

/**
 * One playlist tile. Sized to match `AlbumCard` (176dp wide, 144dp
 * square cover) so they line up in the Home Playlists carousel.
 * Mirrors `flutter_client/lib/playlists/widgets/playlist_card.dart`.
 *
 * System playlists carry a small "For You" / "Discover" / etc. label
 * subtitle under the name (substituting for the artist-name line on
 * AlbumCard).
 *
 * [onPlay] is an opt-in play-overlay handler. When non-null, a 44dp
 * circular play button is overlaid at the bottom-right of the cover.
 * [playEnabled] disables the overlay (50% alpha + ignore taps) — Home
 * uses it for system playlists in offline mode (their server-side
 * shuffle endpoint is unreachable) and for empty playlists.
 *
 * [greyed] dims the whole tile (it can't be reliably played offline) while
 * keeping it tappable — the detail screen is the escape hatch for shuffling
 * whatever subset is cached. Greyed always disables the play overlay too.
 */
@Composable
fun PlaylistCard(
    playlist: PlaylistRef,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    onPlay: (suspend () -> Unit)? = null,
    playEnabled: Boolean = true,
    greyed: Boolean = false,
) {
    val seedCache = LocalDetailSeedCache.current
    Surface(
        modifier = modifier
            .width(176.dp)
            .alpha(if (greyed) GREYED_ALPHA else 1f) // dimmed, still clickable
            .clickable {
                seedCache.stashPlaylist(playlist)
                onClick()
            },
        color = Color.Transparent,
    ) {
        Column(modifier = Modifier.padding(horizontal = 8.dp)) {
            PlaylistCardCover(
                playlist = playlist,
                onPlay = onPlay,
                playEnabled = playEnabled && !greyed,
            )
            Spacer(Modifier.height(8.dp))
            Text(
                text = playlist.name,
                style = MaterialTheme.typography.titleSmall,
                color = MaterialTheme.colorScheme.onSurface,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
            )
            Text(
                text = subtitleFor(playlist),
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
            )
        }
    }
}

/**
 * 144dp cover with the system-variant pill (top-start) and play
 * overlay (bottom-end) stacked on top. Pulled out of [PlaylistCard]
 * to keep that composable under detekt's 60-line LongMethod cap.
 */
@Composable
private fun PlaylistCardCover(
    playlist: PlaylistRef,
    onPlay: (suspend () -> Unit)?,
    playEnabled: Boolean,
) {
    CoverTile(
        url = playlist.coverUrl,
        contentDescription = playlist.name,
        size = 144.dp,
        fallback = {
            Icon(
                imageVector = Lucide.ListMusic,
                contentDescription = null,
                tint = MaterialTheme.colorScheme.onSurfaceVariant,
                modifier = Modifier.size(56.dp),
            )
        },
        overlay = {
            if (playlist.isSystem) {
                VariantPill(
                    label = systemLabelFor(playlist.systemVariant),
                    modifier = Modifier
                        .align(Alignment.TopStart)
                        .padding(6.dp),
                )
            }
            if (onPlay != null) {
                PlayCircleButton(
                    onPlay = onPlay,
                    enabled = playEnabled,
                    modifier = Modifier
                        .align(Alignment.BottomEnd)
                        .padding(6.dp),
                )
            }
        },
    )
}

/** Small label chip overlaid on a system playlist's cover. */
@Composable
private fun VariantPill(label: String, modifier: Modifier = Modifier) {
    if (label.isEmpty()) return
    Surface(
        modifier = modifier,
        shape = RoundedCornerShape(FabledSwordFlatTokens.radiusSm),
        color = MaterialTheme.colorScheme.primary.copy(alpha = PILL_BG_ALPHA),
    ) {
        Text(
            text = label,
            modifier = Modifier.padding(horizontal = 8.dp, vertical = 2.dp),
            style = MaterialTheme.typography.labelSmall,
            color = MaterialTheme.colorScheme.onPrimary,
        )
    }
}

private const val PILL_BG_ALPHA = 0.85f
private const val GREYED_ALPHA = 0.45f

private fun subtitleFor(playlist: PlaylistRef): String = when {
    playlist.trackCount > 0 -> "${playlist.trackCount} tracks"
    playlist.isSystem -> systemLabelFor(playlist.systemVariant)
    else -> " "
}

private fun systemLabelFor(variant: String?): String = when (variant) {
    "for_you" -> "For You"
    "discover" -> "Discover"
    "songs_like_artist" -> "Songs like…"
    "deep_cuts" -> "Deep cuts"
    "rediscover" -> "Rediscover"
    "new_for_you" -> "New for you"
    "on_this_day" -> "On this day"
    "first_listens" -> "First listens"
    null -> ""
    else -> variant.replace('_', ' ').replaceFirstChar { it.uppercase() }
}
