package app.closer.ui.wheel

import app.closer.ui.theme.closerCardColor
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.Row
import app.closer.domain.model.SessionLength
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import app.closer.ui.theme.CloserPalette
import app.closer.ui.theme.closerBackgroundBrush
import app.closer.ui.theme.closerWheelSegmentColors

@Composable
fun SpinWheelScreen(
    categoryId: String,
    onNavigate: (String) -> Unit = {},
    viewModel: SpinWheelViewModel = hiltViewModel()
) {
    val state by viewModel.uiState.collectAsState()

    LaunchedEffect(state.navigateTo) {
        state.navigateTo?.let {
            onNavigate(it)
            viewModel.onNavigated()
        }
    }

    SpinWheelContent(
        state = state,
        onSpin = viewModel::spin,
        onStart = viewModel::startSession,
        onLengthSelected = viewModel::setLength
    )
}

@Composable
private fun SpinWheelContent(
    state: SpinWheelUiState,
    onSpin: () -> Unit,
    onStart: () -> Unit,
    onLengthSelected: (SessionLength) -> Unit = {}
) {
    val infiniteTransition = rememberInfiniteTransition(label = "wheel")
    val rotation by infiniteTransition.animateFloat(
        initialValue = 0f,
        targetValue = 360f,
        animationSpec = infiniteRepeatable(
            animation = tween(durationMillis = 1200, easing = LinearEasing),
            repeatMode = RepeatMode.Restart
        ),
        label = "wheel_rotation"
    )

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(closerBackgroundBrush()),
        contentAlignment = Alignment.Center
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .safeDrawingPadding()
                .navigationBarsPadding()
                .padding(horizontal = 28.dp, vertical = 32.dp),
            verticalArrangement = Arrangement.spacedBy(28.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Column(
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.spacedBy(10.dp)
            ) {
                Text(
                    text = "Let the prompt find you",
                    style = MaterialTheme.typography.headlineMedium.copy(fontWeight = FontWeight.SemiBold),
                    color = MaterialTheme.colorScheme.onBackground,
                    textAlign = TextAlign.Center,
                    maxLines = 2,
                    overflow = TextOverflow.Ellipsis
                )
                if (state.categoryName.isNotBlank()) {
                    Surface(
                        shape = RoundedCornerShape(999.dp),
                        color = CloserPalette.PurpleMist
                    ) {
                        Text(
                            text = state.categoryName,
                            modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
                            style = MaterialTheme.typography.labelLarge,
                            color = CloserPalette.PurpleDeep,
                            maxLines = 1,
                            overflow = TextOverflow.Ellipsis
                        )
                    }
                }
            }

            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier.weight(1f)
            ) {
                WheelSpinner(
                    isSpinning = state.isSpinning,
                    spunAndReady = state.spunAndReady,
                    rotation = rotation
                )
            }

            Column(
                modifier = Modifier.fillMaxWidth(),
                verticalArrangement = Arrangement.spacedBy(14.dp)
            ) {
                if (!state.isLoading && !state.isSpinning) {
                    WheelLengthChips(
                        selected = state.selectedLength,
                        onSelect = onLengthSelected
                    )
                }
                when {
                    state.error != null -> Text(
                        text = state.error,
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.error,
                        textAlign = TextAlign.Center,
                        modifier = Modifier.fillMaxWidth()
                    )
                    state.spunAndReady -> {
                        Text(
                            text = "${state.selectedLength.count} questions selected",
                            style = MaterialTheme.typography.bodyMedium,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                            textAlign = TextAlign.Center,
                            modifier = Modifier.fillMaxWidth()
                        )
                        Button(
                            onClick = onStart,
                            modifier = Modifier
                                .fillMaxWidth()
                                .heightIn(min = 56.dp),
                            shape = RoundedCornerShape(18.dp),
                            colors = ButtonDefaults.buttonColors(containerColor = CloserPalette.PurpleDeep)
                        ) {
                            Text("Start session", color = MaterialTheme.colorScheme.surface)
                        }
                        OutlinedButton(
                            onClick = onSpin,
                            modifier = Modifier
                                .fillMaxWidth()
                                .heightIn(min = 56.dp),
                            shape = RoundedCornerShape(18.dp),
                            border = BorderStroke(1.dp, CloserPalette.PurpleDeep.copy(alpha = 0.44f)),
                            colors = ButtonDefaults.outlinedButtonColors(
                                contentColor = CloserPalette.PurpleDeep
                            )
                        ) {
                            Text("Spin again")
                        }
                    }
                    state.isLoading -> CircularProgressIndicator(color = CloserPalette.PurpleDeep)
                    else -> {
                        Text(
                            text = "Tap to select ${state.selectedLength.count} questions at random",
                            style = MaterialTheme.typography.bodyMedium,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                            textAlign = TextAlign.Center,
                            modifier = Modifier.fillMaxWidth()
                        )
                        Button(
                            onClick = onSpin,
                            modifier = Modifier
                                .fillMaxWidth()
                                .heightIn(min = 56.dp),
                            shape = RoundedCornerShape(18.dp),
                            colors = ButtonDefaults.buttonColors(containerColor = CloserPalette.PurpleDeep)
                        ) {
                            Text("Spin wheel", color = MaterialTheme.colorScheme.surface)
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun WheelSpinner(
    isSpinning: Boolean,
    spunAndReady: Boolean,
    rotation: Float
) {
    val segmentColors = closerWheelSegmentColors()
    val idleTransition = rememberInfiniteTransition(label = "wheel_idle")
    val idlePulse by idleTransition.animateFloat(
        initialValue = 0.98f,
        targetValue = 1.02f,
        animationSpec = infiniteRepeatable(
            animation = tween(durationMillis = 1400),
            repeatMode = RepeatMode.Reverse
        ),
        label = "wheel_idle_pulse"
    )
    val centerScale by animateFloatAsState(
        targetValue = if (spunAndReady) 1.08f else 1f,
        animationSpec = tween(durationMillis = 220),
        label = "wheel_center_scale"
    )
    val pointerScale by animateFloatAsState(
        targetValue = if (isSpinning) 1.12f else 1f,
        animationSpec = tween(durationMillis = 160),
        label = "wheel_pointer_scale"
    )
    val wheelRingColor = closerCardColor(alpha = 0.84f)

    Box(
        modifier = Modifier
            .size(270.dp)
            .scale(if (isSpinning) 1f else idlePulse),
        contentAlignment = Alignment.Center
    ) {
        Canvas(
            modifier = Modifier
                .size(236.dp)
                .rotate(if (isSpinning) rotation else 0f)
        ) {
            val sweep = 360f / segmentColors.size
            segmentColors.forEachIndexed { index, color ->
                drawArc(
                    color = color,
                    startAngle = -90f + (index * sweep),
                    sweepAngle = sweep,
                    useCenter = true
                )
            }
            drawCircle(
                color = Color.White.copy(alpha = 0.78f),
                radius = size.minDimension * 0.24f
            )
            drawCircle(
                color = wheelRingColor,
                style = Stroke(width = 7.dp.toPx())
            )
        }

        Canvas(
            modifier = Modifier
                .align(Alignment.TopCenter)
                .size(width = 34.dp, height = 28.dp)
                .scale(pointerScale)
        ) {
            val path = Path().apply {
                moveTo(size.width / 2f, size.height)
                lineTo(0f, 0f)
                lineTo(size.width, 0f)
                close()
            }
            drawPath(path = path, color = CloserPalette.PurpleDeep)
        }

        Surface(
            modifier = Modifier
                .size(94.dp)
                .scale(centerScale),
            shape = CircleShape,
            color = if (spunAndReady) CloserPalette.PinkMist else MaterialTheme.colorScheme.surface,
            shadowElevation = 10.dp
        ) {
            Box(contentAlignment = Alignment.Center) {
                Text(
                    text = if (spunAndReady) "Ready" else "Spin",
                    style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.SemiBold),
                    color = CloserPalette.PurpleDeep,
                    textAlign = TextAlign.Center,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis
                )
            }
        }
    }
}

@Composable
private fun WheelLengthChips(
    selected: SessionLength,
    onSelect: (SessionLength) -> Unit
) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        SessionLength.values().forEach { len ->
            Surface(
                onClick = { onSelect(len) },
                modifier = Modifier.weight(1f),
                shape = RoundedCornerShape(12.dp),
                color = if (len == selected) CloserPalette.PurpleDeep else Color.Transparent,
                border = if (len != selected)
                    BorderStroke(1.dp, CloserPalette.PurpleDeep.copy(alpha = 0.4f))
                else null
            ) {
                Text(
                    text = len.label,
                    modifier = Modifier.padding(vertical = 10.dp),
                    style = MaterialTheme.typography.labelMedium,
                    color = if (len == selected) Color.White else CloserPalette.PurpleDeep,
                    textAlign = TextAlign.Center
                )
            }
        }
    }
}

@Preview
@Composable
fun SpinWheelScreenPreview() {
    SpinWheelContent(
        state = SpinWheelUiState(isLoading = false, categoryName = "Trust"),
        onSpin = {},
        onStart = {}
    )
}
