package com.atridad.magiccounter.ui.screens

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.input.pointer.PointerInputScope
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.zIndex
import java.util.Collections
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Flag
import androidx.compose.material.icons.filled.Remove
import androidx.compose.material.icons.filled.Shield
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.atridad.magiccounter.ui.state.GameState
import com.atridad.magiccounter.ui.state.PlayerState
import com.atridad.magiccounter.ui.theme.CustomIcons
import androidx.compose.ui.graphics.luminance
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch

@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
@Composable
/**
 * Game screen hosting all player panels.
 *
 * - state: immutable state used to bootstrap the in-memory counters
 * - onProgress: called with a snapshot of the latest state after any user interaction
 * - onWinner: called once when a winner is determined, with (winnerId, finalState)
 * - onStop: called when the game is manually stopped
 * - onDelete: called when the game is deleted
 * - matchName: name of the match to display in header
 * - startedAtEpochMs: timestamp when the match started
 */
fun GameScreen(
    modifier: Modifier = Modifier,
    state: GameState,
    matchName: String = "Game",
    startedAtEpochMs: Long = System.currentTimeMillis(),
    onProgress: ((GameState) -> Unit)? = null,
    onWinner: ((Int, GameState) -> Unit)? = null,
    onStop: ((GameState) -> Unit)? = null,
    onDelete: (() -> Unit)? = null
) {
    val lifeTotals = remember { mutableStateMapOf<Int, Int>() }
    val poisonTotals = remember { mutableStateMapOf<Int, Int>() }

    val commanderDamages = remember { mutableStateMapOf<Int, MutableMap<Int, Int>>() }
    val eliminated = remember { mutableStateMapOf<Int, Boolean>() }
    val gameLocked = remember { mutableStateOf(false) }
    val showStopConfirm = remember { mutableStateOf(false) }
    var commanderSheetPlayer by remember { mutableStateOf<PlayerState?>(null) }
    val sheetState = rememberModalBottomSheetState()
    var elapsedSeconds by remember { mutableLongStateOf(0L) }
    val uiPlayers = remember { mutableStateListOf<PlayerState>() }

    LaunchedEffect(state.players) {
        uiPlayers.clear()
        uiPlayers.addAll(state.players)
    }

    LaunchedEffect(state.stopped, gameLocked.value) {
        if (!state.stopped && !gameLocked.value) {
            while (true) {
                elapsedSeconds = (System.currentTimeMillis() - startedAtEpochMs) / 1000
                delay(1000L)
            }
        }
    }

    state.players.forEach { p ->
        lifeTotals.putIfAbsent(p.id, p.life)
        poisonTotals.putIfAbsent(p.id, p.poison)
        commanderDamages.putIfAbsent(p.id, p.commanderDamages.toMutableMap())

        val isEliminated = p.scooped ||
            p.life <= 0 ||
            p.poison >= 10 ||
            p.commanderDamages.values.any { it >= 21 }
        eliminated.putIfAbsent(p.id, isEliminated)
    }

    val savedWinnerId = state.winnerPlayerId
    if (savedWinnerId != null && !gameLocked.value) {
        gameLocked.value = true
    }

    fun checkElimination(playerId: Int) {
        val life = lifeTotals[playerId] ?: state.startingLife
        if (life <= 0) {
            eliminated[playerId] = true
            return
        }
        val poison = poisonTotals[playerId] ?: 0
        if (poison >= 10) {
            eliminated[playerId] = true
            return
        }
        val fromMap: Map<Int, Int> = commanderDamages[playerId] ?: emptyMap()
        if (fromMap.values.any { it >= 21 }) {
            eliminated[playerId] = true
        }
    }

    fun snapshotState(winnerId: Int? = null): GameState = state.copy(
        players = uiPlayers.map { p ->
            PlayerState(
                id = p.id,
                name = p.name,
                life = lifeTotals[p.id] ?: p.life,
                poison = poisonTotals[p.id] ?: p.poison,
                commanderDamages = commanderDamages[p.id]?.toMap() ?: p.commanderDamages,
                scooped = eliminated[p.id] == true
            )
        },
        stopped = winnerId != null || state.stopped,
        winnerPlayerId = winnerId ?: state.winnerPlayerId
    )

    fun formatTime(totalSeconds: Long): String {
        val hours = totalSeconds / 3600
        val minutes = (totalSeconds % 3600) / 60
        val seconds = totalSeconds % 60
        return if (hours > 0) {
            String.format("%02d:%02d:%02d", hours, minutes, seconds)
        } else {
            String.format("%02d:%02d", minutes, seconds)
        }
    }

    val aliveCount = state.players.count { eliminated[it.id] != true }
    val currentWinnerId: Int? = state.winnerPlayerId ?: if (aliveCount == 1) {
        state.players.firstOrNull { eliminated[it.id] != true }?.id
    } else null

    val winnerName = currentWinnerId?.let { id ->
        state.players.find { it.id == id }?.name
    }

    if (currentWinnerId != null && !gameLocked.value && state.winnerPlayerId == null) {
        gameLocked.value = true
        onWinner?.invoke(currentWinnerId, snapshotState(winnerId = currentWinnerId))
    }

    if ((state.stopped || state.winnerPlayerId != null) && !gameLocked.value) {
        gameLocked.value = true
    }

    Column(modifier = modifier) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 16.dp, vertical = 12.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = matchName,
                style = MaterialTheme.typography.headlineSmall,
                fontWeight = FontWeight.Bold,
                color = MaterialTheme.colorScheme.onSurface,
                modifier = Modifier.weight(1f)
            )

            Surface(
                color = when {
                    gameLocked.value && currentWinnerId != null -> Color(0xFF2E7D32).copy(alpha = 0.2f)
                    state.stopped -> MaterialTheme.colorScheme.errorContainer
                    else -> MaterialTheme.colorScheme.primaryContainer
                },
                shape = RoundedCornerShape(16.dp),
                modifier = Modifier.padding(horizontal = 8.dp)
            ) {
                Text(
                    text = when {
                        state.stopped -> "Stopped"
                        else -> formatTime(elapsedSeconds)
                    },
                    style = MaterialTheme.typography.labelLarge,
                    fontWeight = FontWeight.Bold,
                    color = when {
                        gameLocked.value && currentWinnerId != null -> Color(0xFF2E7D32)
                        state.stopped -> MaterialTheme.colorScheme.onErrorContainer
                        else -> MaterialTheme.colorScheme.onPrimaryContainer
                    },
                    modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp)
                )
            }

            if (state.stopped) {
                IconButton(onClick = { onDelete?.invoke() }) {
                    Icon(
                        Icons.Default.Delete,
                        contentDescription = "Delete game",
                        tint = MaterialTheme.colorScheme.error
                    )
                }
            } else {
                IconButton(onClick = { showStopConfirm.value = true }) {
                    Icon(
                        CustomIcons.Stop(MaterialTheme.colorScheme.error),
                        contentDescription = "Stop game"
                    )
                }
            }
        }

        if (currentWinnerId != null && winnerName != null) {
            Surface(
                color = Color(0xFF2E7D32).copy(alpha = 0.15f),
                shape = RoundedCornerShape(12.dp),
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp, vertical = 8.dp)
            ) {
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp),
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.Center
                ) {
                    Icon(
                        imageVector = Icons.Default.Flag,
                        contentDescription = "Winner",
                        tint = Color(0xFF2E7D32),
                        modifier = Modifier.size(24.dp)
                    )
                    Spacer(modifier = Modifier.width(12.dp))
                    Text(
                        text = "$winnerName Wins!",
                        style = MaterialTheme.typography.titleLarge,
                        fontWeight = FontWeight.Bold,
                        color = Color(0xFF2E7D32)
                    )
                }
            }
        }

        val listState = rememberLazyListState()
        var draggingItemIndex by remember { mutableStateOf<Int?>(null) }
        var draggingItemOffset by remember { mutableFloatStateOf(0f) }
        val haptics = LocalHapticFeedback.current

        LazyColumn(
            state = listState,
            modifier = Modifier.weight(1f),
            contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            itemsIndexed(uiPlayers, key = { _, item -> item.id }) { index, player ->
                val accent = seatAccentColor(index, MaterialTheme.colorScheme)
                val perPlayerCommander: Map<Int, Int> = commanderDamages[player.id]?.toMap() ?: emptyMap()

                val isDragging = index == draggingItemIndex
                val currentItemIndex by rememberUpdatedState(index)

                Box(
                    modifier = Modifier
                        .then(if (isDragging) Modifier else Modifier.animateItem())
                        .zIndex(if (isDragging) 1f else 0f)
                        .graphicsLayer {
                            translationY = if (isDragging) draggingItemOffset else 0f
                            scaleX = if (isDragging) 1.05f else 1f
                            scaleY = if (isDragging) 1.05f else 1f
                            shadowElevation = if (isDragging) 8.dp.toPx() else 0f
                        }
                        .pointerInput(player.id) {
                            detectDragGesturesAfterShortPress(
                                onDragStart = {
                                    haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                                    draggingItemIndex = currentItemIndex
                                    draggingItemOffset = 0f
                                },
                                onDrag = { change, dragAmount ->
                                    change.consume()
                                    draggingItemOffset += dragAmount.y

                                    val currentIndex = currentItemIndex
                                    val currentInfo = listState.layoutInfo.visibleItemsInfo.find { it.index == currentIndex }
                                    if (currentInfo != null) {
                                        val currentCenter = currentInfo.offset + currentInfo.size / 2 + draggingItemOffset
                                        val targetItem = listState.layoutInfo.visibleItemsInfo.find {
                                            it.index != currentIndex &&
                                            currentCenter > it.offset &&
                                            currentCenter < (it.offset + it.size)
                                        }

                                        if (targetItem != null) {
                                            val targetIndex = targetItem.index
                                            if (currentIndex < uiPlayers.size && targetIndex < uiPlayers.size) {
                                                Collections.swap(uiPlayers, currentIndex, targetIndex)
                                                draggingItemIndex = targetIndex
                                                draggingItemOffset -= (targetItem.offset - currentInfo.offset)
                                            }
                                        }
                                    }
                                },
                                onDragEnd = {
                                    draggingItemIndex = null
                                    draggingItemOffset = 0f
                                    onProgress?.invoke(snapshotState())
                                }
                            )
                        }
                ) {
                    PlayerCard(
                        player = player,
                        allPlayers = state.players,
                        life = lifeTotals[player.id] ?: state.startingLife,
                        onLifeChange = { new ->
                            if (gameLocked.value) return@PlayerCard
                            lifeTotals[player.id] = new
                            checkElimination(player.id)
                            onProgress?.invoke(snapshotState())
                        },
                        poison = poisonTotals[player.id] ?: 0,
                        onPoisonChange = {
                            if (!gameLocked.value) {
                                poisonTotals[player.id] = it
                                checkElimination(player.id)
                                onProgress?.invoke(snapshotState())
                            }
                        },
                        trackPoison = state.trackPoison,
                        trackCommanderDamage = state.trackCommanderDamage,
                        commanderDamages = perPlayerCommander,
                        onCommanderTap = {
                            commanderSheetPlayer = player
                        },
                        accentColor = accent,
                        isEliminated = eliminated[player.id] == true,
                        isWinner = currentWinnerId == player.id,
                        onScoop = {
                            if (!gameLocked.value) {
                                eliminated[player.id] = true
                                onProgress?.invoke(snapshotState())
                            }
                        }
                    )
                }
            }
        }

        if (showStopConfirm.value) {
            AlertDialog(
                onDismissRequest = { showStopConfirm.value = false },
                title = { Text("Stop Game?") },
                text = { Text("Are you sure you want to stop this game? This will end the current session.") },
                confirmButton = {
                    TextButton(
                        onClick = {
                            val stoppedState = snapshotState().copy(stopped = true)
                            onStop?.invoke(stoppedState)
                            showStopConfirm.value = false
                        }
                    ) { Text("Stop Game") }
                },
                dismissButton = {
                    TextButton(onClick = { showStopConfirm.value = false }) { Text("Cancel") }
                }
            )
        }

        if (commanderSheetPlayer != null) {
            val targetPlayer = commanderSheetPlayer!!
            ModalBottomSheet(
                onDismissRequest = { commanderSheetPlayer = null },
                sheetState = sheetState
            ) {
                CommanderDamageSheet(
                    targetPlayer = targetPlayer,
                    allPlayers = state.players,
                    commanderDamages = commanderDamages[targetPlayer.id]?.toMap() ?: emptyMap(),
                    onDamageChange = { fromId, newDamage ->
                        if (!gameLocked.value) {
                            val oldDamage = commanderDamages[targetPlayer.id]?.get(fromId) ?: 0
                            val damageDelta = newDamage - oldDamage

                            val newMap = (commanderDamages[targetPlayer.id] ?: mutableMapOf()).toMutableMap()
                            newMap[fromId] = newDamage.coerceAtLeast(0)
                            commanderDamages[targetPlayer.id] = newMap

                            val currentLife = lifeTotals[targetPlayer.id] ?: state.startingLife
                            lifeTotals[targetPlayer.id] = currentLife - damageDelta

                            checkElimination(targetPlayer.id)
                            onProgress?.invoke(snapshotState())
                        }
                    },
                    onDismiss = { commanderSheetPlayer = null }
                )
            }
        }
    }
}

private fun seatAccentColor(index: Int, scheme: androidx.compose.material3.ColorScheme): Color = when (index % 6) {
    0 -> scheme.primary
    1 -> scheme.tertiary
    2 -> scheme.secondary
    3 -> scheme.error
    4 -> scheme.primaryContainer
    else -> scheme.tertiaryContainer
}

/**
 * Tracks delta changes for displaying temporary indicators.
 */
class DeltaTrackerState {
    var delta by mutableIntStateOf(0)
    var resetJob: Job? = null

    fun addDelta(amount: Int, scope: kotlinx.coroutines.CoroutineScope) {
        delta += amount
        resetJob?.cancel()
        resetJob = scope.launch {
            delay(2000L)
            delta = 0
        }
    }

    fun reset() {
        resetJob?.cancel()
        delta = 0
    }
}

@Composable
fun rememberDeltaTracker(): DeltaTrackerState {
    return remember { DeltaTrackerState() }
}

/**
 * Delta indicator that shows accumulated change amount.
 * Uses absolute positioning so it doesn't affect layout.
 */
@Composable
private fun DeltaIndicator(
    delta: Int,
    modifier: Modifier = Modifier
) {
    Box(modifier = modifier) {
        AnimatedVisibility(
            visible = delta != 0,
            enter = fadeIn() + scaleIn(),
            exit = fadeOut() + scaleOut()
        ) {
            Text(
                text = if (delta > 0) "+$delta" else "$delta",
                style = MaterialTheme.typography.labelSmall,
                fontWeight = FontWeight.Bold,
                color = if (delta > 0) Color(0xFF4CAF50) else Color(0xFFF44336),
                modifier = Modifier.alpha(0.85f)
            )
        }
    }
}

/**
 * Custom delta input dialog.
 */
@Composable
private fun CustomDeltaDialog(
    isIncreasing: Boolean,
    onDismiss: () -> Unit,
    onConfirm: (Int) -> Unit
) {
    var inputText by remember { mutableStateOf("") }

    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text("Enter Amount") },
        text = {
            Column {
                Text(
                    text = if (isIncreasing) "Enter the amount to add" else "Enter the amount to subtract",
                    style = MaterialTheme.typography.bodyMedium
                )
                OutlinedTextField(
                    value = inputText,
                    onValueChange = { inputText = it.filter { c -> c.isDigit() } },
                    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
                    singleLine = true,
                    modifier = Modifier.padding(top = 8.dp)
                )
            }
        },
        confirmButton = {
            TextButton(
                onClick = {
                    val amount = inputText.toIntOrNull()
                    if (amount != null && amount > 0) {
                        onConfirm(if (isIncreasing) amount else -amount)
                    }
                    onDismiss()
                }
            ) {
                Text(if (isIncreasing) "Add" else "Subtract")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    )
}

/**
 * Commander damage bottom sheet content
 */
@Composable
private fun CommanderDamageSheet(
    targetPlayer: PlayerState,
    allPlayers: List<PlayerState>,
    commanderDamages: Map<Int, Int>,
    onDamageChange: (fromId: Int, newDamage: Int) -> Unit,
    onDismiss: () -> Unit
) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        Text(
            text = "Commander Damage to ${targetPlayer.name}",
            style = MaterialTheme.typography.titleLarge,
            fontWeight = FontWeight.Bold,
            modifier = Modifier.padding(bottom = 16.dp)
        )

        allPlayers.filter { it.id != targetPlayer.id }.forEach { attacker ->
            val damage = commanderDamages[attacker.id] ?: 0
            CommanderDamageRow(
                attackerName = attacker.name,
                damage = damage,
                onDamageChange = { newDamage -> onDamageChange(attacker.id, newDamage) }
            )
            Spacer(modifier = Modifier.height(12.dp))
        }

        TextButton(
            onClick = onDismiss,
            modifier = Modifier.align(Alignment.End)
        ) {
            Text("Done")
        }

        Spacer(modifier = Modifier.height(32.dp))
    }
}

/**
 * Single row in commander damage sheet
 */
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun CommanderDamageRow(
    attackerName: String,
    damage: Int,
    onDamageChange: (Int) -> Unit
) {
    val deltaTracker = rememberDeltaTracker()
    val scope = rememberCoroutineScope()
    val haptics = LocalHapticFeedback.current
    var showCustomDeltaDialog by remember { mutableStateOf(false) }
    var isIncreasing by remember { mutableStateOf(true) }

    val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5f
    val redColor = if (isDarkTheme) Color(0xFFEF9A9A) else Color(0xFFC62828)
    val greenColor = if (isDarkTheme) Color(0xFFA5D6A7) else Color(0xFF2E7D32)

    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Text(
            text = attackerName,
            style = MaterialTheme.typography.titleMedium
        )
        Row(verticalAlignment = Alignment.CenterVertically) {
            Box(contentAlignment = Alignment.Center) {
                CounterIconButtonWithLongPress(
                    icon = Icons.Default.Remove,
                    contentDescription = "decrease damage",
                    onClick = {
                        val newDamage = (damage - 1).coerceAtLeast(0)
                        onDamageChange(newDamage)
                        deltaTracker.addDelta(-1, scope)
                    },
                    onLongPress = {
                        haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                        isIncreasing = false
                        showCustomDeltaDialog = true
                    },
                    buttonColor = redColor
                )
                if (deltaTracker.delta < 0) {
                    DeltaIndicator(
                        delta = deltaTracker.delta,
                        modifier = Modifier
                            .align(Alignment.TopCenter)
                            .offset(y = (-18).dp)
                    )
                }
            }
            Text(
                text = damage.toString(),
                style = MaterialTheme.typography.headlineSmall,
                fontWeight = FontWeight.Bold,
                modifier = Modifier.padding(horizontal = 16.dp),
                textAlign = TextAlign.Center
            )
            Box(contentAlignment = Alignment.Center) {
                CounterIconButtonWithLongPress(
                    icon = Icons.Default.Add,
                    contentDescription = "increase damage",
                    onClick = {
                        onDamageChange(damage + 1)
                        deltaTracker.addDelta(1, scope)
                    },
                    onLongPress = {
                        haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                        isIncreasing = true
                        showCustomDeltaDialog = true
                    },
                    buttonColor = greenColor
                )
                if (deltaTracker.delta > 0) {
                    DeltaIndicator(
                        delta = deltaTracker.delta,
                        modifier = Modifier
                            .align(Alignment.TopCenter)
                            .offset(y = (-18).dp)
                    )
                }
            }
        }
    }

    if (showCustomDeltaDialog) {
        CustomDeltaDialog(
            isIncreasing = isIncreasing,
            onDismiss = { showCustomDeltaDialog = false },
            onConfirm = { delta ->
                val newDamage = (damage + delta).coerceAtLeast(0)
                onDamageChange(newDamage)
                deltaTracker.addDelta(delta, scope)
            }
        )
    }
}

/**
 * Player panel with counters and actions.
 */
@Composable
private fun PlayerCard(
    player: PlayerState,
    allPlayers: List<PlayerState>,
    life: Int,
    onLifeChange: (Int) -> Unit,
    poison: Int,
    onPoisonChange: (Int) -> Unit,
    trackPoison: Boolean,
    trackCommanderDamage: Boolean,
    commanderDamages: Map<Int, Int>,
    onCommanderTap: () -> Unit,
    accentColor: Color,
    isEliminated: Boolean,
    isWinner: Boolean,
    onScoop: () -> Unit
) {
    val targetContainer = if (isEliminated) MaterialTheme.colorScheme.errorContainer else MaterialTheme.colorScheme.surfaceVariant
    val containerColor = animateColorAsState(targetValue = targetContainer, label = "eliminationColor")
    val overlayAlpha = animateFloatAsState(targetValue = if (isEliminated) 1f else 0f, label = "overlayAlpha")
    val controlsEnabled = !isEliminated && !isWinner

    Card(
        modifier = Modifier
            .padding(4.dp)
            .fillMaxWidth(),
        elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
        colors = CardDefaults.cardColors(containerColor = containerColor.value),
        border = BorderStroke(3.dp, if (isWinner) Color(0xFF2E7D32) else accentColor)
    ) {
        Box(modifier = Modifier.fillMaxSize()) {
            Column(
                modifier = Modifier
                    .padding(12.dp)
                    .alpha(if (isEliminated) 0.45f else 1f),
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.SpaceBetween,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Text(
                        player.name,
                        style = MaterialTheme.typography.headlineSmall,
                        color = if (isWinner) Color(0xFF2E7D32) else accentColor
                    )
                    TextButton(onClick = onScoop, enabled = controlsEnabled) {
                        Icon(Icons.Default.Flag, contentDescription = "Scoop")
                        Text("Scoop")
                    }
                }

                BigLifeRow(value = life, onChange = onLifeChange, enabled = controlsEnabled)

                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.Center,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    if (trackPoison) {
                        PoisonCounter(
                            value = poison,
                            onChange = onPoisonChange,
                            enabled = controlsEnabled
                        )
                    }

                    if (trackPoison && trackCommanderDamage) {
                        Spacer(modifier = Modifier.width(16.dp))
                    }

                    if (trackCommanderDamage) {
                        CommanderDamageButton(
                            totalDamage = commanderDamages.values.sum(),
                            onClick = onCommanderTap,
                            enabled = controlsEnabled
                        )
                    }
                }
            }

            if (isEliminated) {
                Column(
                    modifier = Modifier
                        .align(Alignment.Center)
                        .alpha(overlayAlpha.value),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Icon(
                        CustomIcons.Skull(MaterialTheme.colorScheme.error),
                        contentDescription = "Player eliminated",
                        modifier = Modifier.size(48.dp)
                    )
                    Text(
                        text = "ELIMINATED",
                        fontSize = 16.sp,
                        color = MaterialTheme.colorScheme.error,
                        style = MaterialTheme.typography.labelMedium
                    )
                }
            }
        }
    }
}

/**
 * Styled poison counter with icon like iOS
 */
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun PoisonCounter(
    value: Int,
    onChange: (Int) -> Unit,
    enabled: Boolean
) {
    val deltaTracker = rememberDeltaTracker()
    val scope = rememberCoroutineScope()
    val haptics = LocalHapticFeedback.current
    var showCustomDeltaDialog by remember { mutableStateOf(false) }
    var isIncreasing by remember { mutableStateOf(true) }

    val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5f
    val purpleColor = if (isDarkTheme) Color(0xFFCE93D8) else Color(0xFF7B1FA2)
    val purpleBgAlpha = if (isDarkTheme) 0.25f else 0.12f

    Surface(
        color = purpleColor.copy(alpha = purpleBgAlpha),
        shape = RoundedCornerShape(16.dp)
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(4.dp)
        ) {
            Box(contentAlignment = Alignment.Center) {
                SmallCounterButton(
                    icon = Icons.Default.Remove,
                    contentDescription = "decrease poison",
                    enabled = enabled,
                    onClick = {
                        onChange((value - 1).coerceAtLeast(0))
                        deltaTracker.addDelta(-1, scope)
                    },
                    onLongPress = {
                        haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                        isIncreasing = false
                        showCustomDeltaDialog = true
                    }
                )
                if (deltaTracker.delta < 0) {
                    DeltaIndicator(
                        delta = deltaTracker.delta,
                        modifier = Modifier
                            .align(Alignment.TopCenter)
                            .offset(y = (-16).dp)
                    )
                }
            }

            Column(
                horizontalAlignment = Alignment.CenterHorizontally,
                modifier = Modifier.padding(horizontal = 4.dp)
            ) {
                Icon(
                    CustomIcons.Droplet(purpleColor),
                    contentDescription = "Poison",
                    modifier = Modifier.size(16.dp),
                    tint = purpleColor
                )
                Text(
                    text = value.toString(),
                    style = MaterialTheme.typography.titleLarge,
                    fontWeight = FontWeight.Bold,
                    color = purpleColor
                )
            }

            Box(contentAlignment = Alignment.Center) {
                SmallCounterButton(
                    icon = Icons.Default.Add,
                    contentDescription = "increase poison",
                    enabled = enabled,
                    onClick = {
                        onChange(value + 1)
                        deltaTracker.addDelta(1, scope)
                    },
                    onLongPress = {
                        haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                        isIncreasing = true
                        showCustomDeltaDialog = true
                    }
                )
                if (deltaTracker.delta > 0) {
                    DeltaIndicator(
                        delta = deltaTracker.delta,
                        modifier = Modifier
                            .align(Alignment.TopCenter)
                            .offset(y = (-16).dp)
                    )
                }
            }
        }
    }

    if (showCustomDeltaDialog) {
        CustomDeltaDialog(
            isIncreasing = isIncreasing,
            onDismiss = { showCustomDeltaDialog = false },
            onConfirm = { delta ->
                onChange((value + delta).coerceAtLeast(0))
                deltaTracker.addDelta(delta, scope)
            }
        )
    }
}

/**
 * Commander damage button that opens the sheet
 */
@Composable
private fun CommanderDamageButton(
    totalDamage: Int,
    onClick: () -> Unit,
    enabled: Boolean
) {
    val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5f
    val orangeColor = if (isDarkTheme) Color(0xFFFFB74D) else Color(0xFFE65100)
    val orangeBgAlpha = if (isDarkTheme) 0.25f else 0.12f

    Surface(
        onClick = onClick,
        enabled = enabled,
        color = orangeColor.copy(alpha = orangeBgAlpha),
        shape = CircleShape
    ) {
        Column(
            modifier = Modifier.padding(12.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Icon(
                Icons.Default.Shield,
                contentDescription = "Commander damage",
                tint = orangeColor,
                modifier = Modifier.size(20.dp)
            )
            Text(
                text = "CMD",
                style = MaterialTheme.typography.labelSmall,
                fontWeight = FontWeight.Bold,
                color = orangeColor
            )
        }
    }
}

/**
 * Small counter button for poison
 */
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun SmallCounterButton(
    icon: ImageVector,
    contentDescription: String,
    enabled: Boolean,
    onClick: () -> Unit,
    onLongPress: () -> Unit
) {
    val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5f
    val buttonBgColor = if (isDarkTheme)
        MaterialTheme.colorScheme.surfaceVariant
    else
        MaterialTheme.colorScheme.outline.copy(alpha = 0.2f)

    Surface(
        modifier = Modifier
            .size(28.dp)
            .combinedClickable(
                enabled = enabled,
                onClick = onClick,
                onLongClick = onLongPress
            ),
        shape = CircleShape,
        color = buttonBgColor.copy(alpha = if (enabled) 0.8f else 0.38f),
        contentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = if (enabled) 0.7f else 0.38f)
    ) {
        Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
            Icon(
                icon,
                contentDescription = contentDescription,
                modifier = Modifier.size(16.dp)
            )
        }
    }
}

/**
 * Life total row with number and +/- buttons.
 */
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun BigLifeRow(value: Int, onChange: (Int) -> Unit, enabled: Boolean = true) {
    val deltaTracker = rememberDeltaTracker()
    val scope = rememberCoroutineScope()
    val haptics = LocalHapticFeedback.current
    var showCustomDeltaDialog by remember { mutableStateOf(false) }
    var isIncreasing by remember { mutableStateOf(true) }

    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Center
    ) {
        Box(contentAlignment = Alignment.Center) {
            val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5f
            val redColor = if (isDarkTheme) Color(0xFFEF9A9A) else Color(0xFFC62828)
            CounterIconButtonWithLongPress(
                icon = Icons.Default.Remove,
                contentDescription = "decrement life",
                enabled = enabled,
                onClick = {
                    onChange(value - 1)
                    deltaTracker.addDelta(-1, scope)
                },
                onLongPress = {
                    haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                    isIncreasing = false
                    showCustomDeltaDialog = true
                },
                buttonColor = redColor
            )
            if (deltaTracker.delta < 0) {
                DeltaIndicator(
                    delta = deltaTracker.delta,
                    modifier = Modifier
                        .align(Alignment.TopCenter)
                        .offset(y = (-20).dp)
                )
            }
        }
        Text(
            text = value.toString(),
            style = MaterialTheme.typography.displayMedium,
            fontWeight = FontWeight.Bold,
            modifier = Modifier.padding(horizontal = 24.dp),
            textAlign = TextAlign.Center
        )
        Box(contentAlignment = Alignment.Center) {
            val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5f
            val greenColor = if (isDarkTheme) Color(0xFFA5D6A7) else Color(0xFF2E7D32)
            CounterIconButtonWithLongPress(
                icon = Icons.Default.Add,
                contentDescription = "increment life",
                enabled = enabled,
                onClick = {
                    onChange(value + 1)
                    deltaTracker.addDelta(1, scope)
                },
                onLongPress = {
                    haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                    isIncreasing = true
                    showCustomDeltaDialog = true
                },
                buttonColor = greenColor
            )
            if (deltaTracker.delta > 0) {
                DeltaIndicator(
                    delta = deltaTracker.delta,
                    modifier = Modifier
                        .align(Alignment.TopCenter)
                        .offset(y = (-20).dp)
                )
            }
        }
    }

    if (showCustomDeltaDialog) {
        CustomDeltaDialog(
            isIncreasing = isIncreasing,
            onDismiss = { showCustomDeltaDialog = false },
            onConfirm = { delta ->
                onChange(value + delta)
                deltaTracker.addDelta(delta, scope)
            }
        )
    }
}

/**
 * Icon button with long press support for counters.
 */
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun CounterIconButtonWithLongPress(
    icon: ImageVector,
    contentDescription: String,
    enabled: Boolean = true,
    onClick: () -> Unit,
    onLongPress: () -> Unit,
    buttonColor: Color = MaterialTheme.colorScheme.secondaryContainer
) {
    val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5f
    val bgAlpha = if (isDarkTheme) 0.35f else 0.2f

    Surface(
        modifier = Modifier
            .size(48.dp)
            .combinedClickable(
                enabled = enabled,
                onClick = onClick,
                onLongClick = onLongPress
            ),
        shape = CircleShape,
        color = buttonColor.copy(alpha = if (enabled) bgAlpha else bgAlpha * 0.5f),
        contentColor = buttonColor.copy(alpha = if (enabled) 1f else 0.38f)
    ) {
        Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
            Icon(icon, contentDescription = contentDescription)
        }
    }
}

/**
 * Icon button used for counters (legacy, kept for compatibility).
 */
@Composable
private fun CounterIconButton(icon: ImageVector, contentDescription: String, enabled: Boolean = true, onClick: () -> Unit) {
    FilledTonalIconButton(onClick = onClick, enabled = enabled, modifier = Modifier.size(40.dp)) {
        Icon(icon, contentDescription = contentDescription)
    }
}

suspend fun PointerInputScope.detectDragGesturesAfterShortPress(
    onDragStart: (Offset) -> Unit = { },
    onDragEnd: () -> Unit = { },
    onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit
) {
    while (true) {
        val down = awaitPointerEventScope {
            awaitFirstDown(requireUnconsumed = false)
        }

        var dragStarted = false
        try {
            withTimeout(200) {
                awaitPointerEventScope {
                    val downId = down.id
                    while (true) {
                        val event = awaitPointerEvent()
                        val change = event.changes.firstOrNull { it.id == downId }

                        if (change == null || !change.pressed) {
                            throw CancellationException("Up")
                        }

                        val positionChange = change.position - down.position
                        if (positionChange.getDistance() > viewConfiguration.touchSlop) {
                            throw CancellationException("Moved")
                        }
                    }
                }
            }
        } catch (_: TimeoutCancellationException) {
            dragStarted = true
        } catch (_: CancellationException) {
        }

        if (dragStarted) {
            onDragStart(down.position)

            try {
                awaitPointerEventScope {
                    val downId = down.id
                    while (true) {
                        val event = awaitPointerEvent()
                        val change = event.changes.firstOrNull { it.id == downId }

                        if (change == null || !change.pressed) {
                            break
                        }

                        val delta = change.positionChange()
                        if (delta != Offset.Zero) {
                            change.consume()
                            onDrag(change, delta)
                        }
                    }
                }
            } finally {
                onDragEnd()
            }
        }
    }
}
