package com.atridad.magiccounter.ui.screens

import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.BorderStroke
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.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.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
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.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.Button
import androidx.compose.material3.AlertDialog
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.graphics.vector.ImageVector
import androidx.compose.ui.graphics.graphicsLayer
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

@OptIn(ExperimentalFoundationApi::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
 */
fun GameScreen(
    modifier: Modifier = Modifier,
    state: GameState,
    onProgress: ((GameState) -> Unit)? = null,
    onWinner: ((Int, GameState) -> Unit)? = null,
    onStop: ((GameState) -> Unit)? = null,
    onDelete: (() -> Unit)? = null
) {
    // Local editable state per player
    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>() }
    // Tracks whether the game has ended. When true, inputs are frozen and the winner is highlighted.
    val gameLocked = remember { mutableStateOf(false) }
    
    // State for stop game confirmation
    val showStopConfirm = remember { mutableStateOf(false) }

    // Initialize
    state.players.forEach { p ->
        lifeTotals.putIfAbsent(p.id, p.life)
        poisonTotals.putIfAbsent(p.id, p.poison)
        commanderDamages.putIfAbsent(p.id, p.commanderDamages.toMutableMap())
        eliminated.putIfAbsent(p.id, p.scooped)
    }

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

    fun snapshotState(): GameState = state.copy(
        players = state.players.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
            )
        }
    )

    Column(modifier = modifier.padding(12.dp)) {
        // Game status and action buttons
        Row(
            modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) { 
            // Game status
            Text(
                text = if (state.stopped) "Game Stopped" else "Game Active",
                style = MaterialTheme.typography.titleMedium,
                color = if (state.stopped) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary
            )
            
            // Action buttons (stop/delete)
            if (state.stopped) {
                // Show delete button for stopped games
                IconButton(
                    onClick = { onDelete?.invoke() }
                ) {
                    Icon(
                        Icons.Default.Delete,
                        contentDescription = "Delete game",
                        tint = MaterialTheme.colorScheme.error
                    )
                }
            } else {
                // Show stop button for active games
                IconButton(
                    onClick = { showStopConfirm.value = true }
                ) {
                    Icon(
                        CustomIcons.Stop(MaterialTheme.colorScheme.error),
                        contentDescription = "Stop game"
                    )
                }
            }
        }

        // Lock game when only one active player remains or game is stopped
        val aliveCount = state.players.count { eliminated[it.id] != true }
        val currentWinnerId: Int? = if (aliveCount == 1) {
            state.players.first { eliminated[it.id] != true }.id
        } else null

        if (currentWinnerId != null && !gameLocked.value) {
            gameLocked.value = true
            onWinner?.invoke(currentWinnerId, snapshotState())
        }
        
        // If game is stopped, lock it
        if (state.stopped && !gameLocked.value) {
            gameLocked.value = true
        }
        
        val displayPlayers = state.players.sortedBy { eliminated[it.id] == true }

        LazyColumn(
            modifier = Modifier.weight(1f),
            contentPadding = PaddingValues(4.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            itemsIndexed(displayPlayers, key = { _, item -> item.id }) { index, player ->
                val accent = seatAccentColor(index, MaterialTheme.colorScheme)
                val perPlayerCommander: Map<Int, Int> = commanderDamages[player.id]?.toMap() ?: emptyMap()
                PlayerCard(
                    player = player,
                    gameState = state,
                    opponents = state.players.map { it.id }.filter { it != player.id },
                    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
                            onProgress?.invoke(snapshotState())
                        }
                    },
                    trackPoison = state.trackPoison,
                    trackCommanderDamage = state.trackCommanderDamage,
                    commanderDamages = perPlayerCommander,
                    onCommanderDamageChange = { fromId, dmg ->
                        if (!gameLocked.value) {
                            val newMap = (commanderDamages[player.id] ?: mutableMapOf()).toMutableMap()
                            newMap[fromId] = dmg
                            commanderDamages[player.id] = newMap
                            checkElimination(player.id)
                            onProgress?.invoke(snapshotState())
                        }
                    },
                    rotation = 0f,
                    accentColor = accent,
                    isEliminated = eliminated[player.id] == true,
                    isWinner = currentWinnerId == player.id,
                    onScoop = {
                        if (!gameLocked.value) {
                            eliminated[player.id] = true
                            onProgress?.invoke(snapshotState())
                        }
                    }
                )
            }
        }
        
        // Stop game confirmation dialog
        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") } 
                }
            )
        }
    }
}

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
}

/**
 * Player panel with counters and actions.
 *
 * - player: immutable player data snapshot.
 * - opponents: list of opponent player ids for commander damage rows.
 * - life/poison: current counter values for this player.
 * - onLifeChange/onPoisonChange: invoked with the new value when a counter is adjusted.
 * - trackPoison/trackCommanderDamage: toggles for which rows are shown.
 * - commanderDamages: map of damage received from opponent id -> damage.
 * - onCommanderDamageChange: callback with (fromId, newDamage).
 * - rotation: visual rotation of the card in degrees.
 * - accentColor: seat accent color used for text and default border.
 * - isEliminated: when true, card is dimmed and inputs disabled.
 * - isWinner: when true, card is highlighted in green and inputs disabled.
 * - onScoop: invoked when the player taps Scoop.
 */
@Composable
private fun PlayerCard(
    player: PlayerState,
    gameState: GameState,
    opponents: List<Int>,
    life: Int,
    onLifeChange: (Int) -> Unit,
    poison: Int,
    onPoisonChange: (Int) -> Unit,
    trackPoison: Boolean,
    trackCommanderDamage: Boolean,
    commanderDamages: Map<Int, Int>,
    onCommanderDamageChange: (fromId: Int, damage: Int) -> Unit,
    rotation: Float,
    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()
            .graphicsLayer { rotationZ = rotation },
        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.titleMedium, 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)

                if (trackPoison) ChipRow(label = "Poison", value = poison, onChange = onPoisonChange, enabled = controlsEnabled)

                if (trackCommanderDamage) {
                    HorizontalDivider()
                    Text("Commander damage", style = MaterialTheme.typography.titleSmall)
                    Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
                        opponents.forEach { fromId ->
                            val value = commanderDamages[fromId] ?: 0
                            ChipRow(label = "From P${fromId + 1}", value = value, onChange = { onCommanderDamageChange(fromId, it) }, enabled = controlsEnabled)
                        }
                    }
                }
            }

            if (isEliminated) {
                // Skull overlay
                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
                    )
                }
            }
        }
    }
}

/**
 * Counter row used for poison and commander damage.
 *
 * - label: row label text
 * - value: current integer value
 * - onChange: callback with the new value after +/- is pressed
 * - enabled: when false, the +/- buttons are disabled
 */
@Composable
private fun ChipRow(
    label: String,
    value: Int,
    onChange: (Int) -> Unit,
    enabled: Boolean = true
) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Text(label)
        Row(verticalAlignment = Alignment.CenterVertically) {
            CounterIconButton(Icons.Default.Remove, "decrement", enabled = enabled) { onChange(value - 1) }
            Text(
                text = value.toString(),
                style = MaterialTheme.typography.titleLarge,
                modifier = Modifier.padding(horizontal = 12.dp),
                textAlign = TextAlign.Center
            )
            CounterIconButton(Icons.Default.Add, "increment", enabled = enabled) { onChange(value + 1) }
        }
    }
}

/**
 * Life total row with number and +/- buttons.
 *
 * - value: current life total
 * - onChange: callback with new life total
 * - enabled: when false, buttons are disabled
 */
@Composable
private fun BigLifeRow(value: Int, onChange: (Int) -> Unit, enabled: Boolean = true) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Text("Life", style = MaterialTheme.typography.titleMedium)
        Row(verticalAlignment = Alignment.CenterVertically) {
            CounterIconButton(Icons.Default.Remove, "decrement life", enabled = enabled) { onChange(value - 1) }
            Text(
                text = value.toString(),
                style = MaterialTheme.typography.displaySmall,
                modifier = Modifier.padding(horizontal = 16.dp),
                textAlign = TextAlign.Center
            )
            CounterIconButton(Icons.Default.Add, "increment life", enabled = enabled) { onChange(value + 1) }
        }
    }
}

/**
 * Icon button used for counters.
 * - icon: vector asset to display
 * - contentDescription: a11y description
 * - enabled: controls click availability
 * - onClick: invoked on press
 */
@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)
    }
}


