package app.closer.ui.wheel

import android.util.Log
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.PaddingValues
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.height
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.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import app.closer.ui.components.CloserHeartLoader
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Surface
import androidx.compose.material3.TextButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import app.closer.ui.components.CelebrationOverlay
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
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 androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.closer.core.navigation.AppRoute
import app.closer.data.remote.FirestoreWheelAnswerDataSource
import app.closer.data.remote.WheelRevealDoc
import app.closer.domain.usecase.GameSessionManager
import app.closer.ui.components.StatusGlyph
import app.closer.ui.theme.CloserPalette
import app.closer.ui.theme.closerBackgroundBrush
import app.closer.ui.theme.closerCardColor
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

// ── ViewModel ──────────────────────────────────────────────────────────────────

enum class WheelRevealPhase { LOADING, WAITING, REVEAL, ERROR }

/** One prompt with both partners' answers, ready to render side by side. */
data class WheelRevealItem(
    val questionText: String,
    val myDisplay: String,
    val partnerDisplay: String
)

data class WheelCompleteUiState(
    val phase: WheelRevealPhase = WheelRevealPhase.LOADING,
    val categoryName: String = "",
    val partnerName: String = "Your partner",
    val items: List<WheelRevealItem> = emptyList(),
    val navigateTo: String? = null,
    val error: String? = null
)

@HiltViewModel
class WheelCompleteViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val gameSessionManager: GameSessionManager,
    private val answerDataSource: FirestoreWheelAnswerDataSource
) : ViewModel() {

    private val sessionId: String = savedStateHandle["sessionId"] ?: ""

    private val _uiState = MutableStateFlow(WheelCompleteUiState())
    val uiState: StateFlow<WheelCompleteUiState> = _uiState.asStateFlow()

    private var coupleId: String? = null
    private var userId: String? = null
    private var partnerId: String? = null

    init {
        observe()
    }

    private fun observe() {
        viewModelScope.launch {
            val uid = gameSessionManager.currentUserId
            val couple = if (uid != null) gameSessionManager.getCoupleForUser(uid) else null
            if (uid == null || couple == null) {
                _uiState.update { it.copy(phase = WheelRevealPhase.ERROR, error = "Couldn't load session. Try again.") }
                return@launch
            }
            userId = uid
            coupleId = couple.id
            partnerId = couple.userIds.firstOrNull { it != uid }
            partnerId?.let { pid ->
                runCatching { gameSessionManager.getUser(pid)?.displayName }
                    .getOrNull()
                    ?.takeIf { it.isNotBlank() }
                    ?.let { name -> _uiState.update { it.copy(partnerName = name) } }
            }

            if (sessionId.isBlank()) {
                _uiState.update { it.copy(phase = WheelRevealPhase.ERROR, error = "Session not found. Return to Play.") }
                return@launch
            }
            runCatching {
                answerDataSource.observe(couple.id, sessionId).collect { handle(it) }
            }.onFailure {
                _uiState.update { s -> s.copy(phase = WheelRevealPhase.ERROR, error = "Couldn't load results. Check your connection.") }
            }
        }
    }

    fun retry() {
        _uiState.update { it.copy(phase = WheelRevealPhase.LOADING, error = null) }
        observe()
    }

    private fun handle(doc: WheelRevealDoc) {
        val uid = userId ?: return
        val mine = doc.answersByUser[uid].orEmpty()
        val theirs = partnerId?.let { doc.answersByUser[it] }.orEmpty()

        if (mine.isNotEmpty() && theirs.isNotEmpty()) {
            val items = doc.questions.map { q ->
                WheelRevealItem(
                    questionText = q.text,
                    myDisplay = mine.firstOrNull { it.questionId == q.id }?.display ?: "—",
                    partnerDisplay = theirs.firstOrNull { it.questionId == q.id }?.display ?: "—"
                )
            }
            _uiState.update {
                it.copy(phase = WheelRevealPhase.REVEAL, categoryName = doc.categoryName, items = items)
            }
            // Both have answered — release the one-game lock so a new game can start.
            finishSession()
        } else {
            _uiState.update {
                it.copy(phase = WheelRevealPhase.WAITING, categoryName = doc.categoryName)
            }
        }
    }

    /** Both answered — mark this user done; session auto-completes once both sides recorded. */
    private fun finishSession() {
        val cId = coupleId ?: return
        if (sessionId.isBlank()) return
        viewModelScope.launch {
            gameSessionManager.markUserComplete(sessionId, cId)
                .onFailure { Log.d(TAG, "finishSession no-op: ${it.message}") }
        }
    }

    /** Force-end the game from the waiting screen (partner never played). */
    fun abandon() {
        val cId = coupleId ?: return
        viewModelScope.launch {
            gameSessionManager.abandonSession(cId)
                .onFailure { Log.d(TAG, "abandon no-op: ${it.message}") }
            _uiState.update { it.copy(navigateTo = AppRoute.PLAY) }
        }
    }

    fun onNavigated() = _uiState.update { it.copy(navigateTo = null) }

    companion object {
        private const val TAG = "WheelCompleteViewModel"
    }
}

// ── Screen ─────────────────────────────────────────────────────────────────────

@Composable
fun WheelCompleteScreen(
    sessionId: String,
    onNavigate: (String) -> Unit = {},
    viewModel: WheelCompleteViewModel = hiltViewModel()
) {
    val state by viewModel.uiState.collectAsState()

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

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(closerBackgroundBrush())
    ) {
        when (state.phase) {
            WheelRevealPhase.LOADING -> CloserHeartLoader(
                modifier = Modifier.align(Alignment.Center)
            )
            WheelRevealPhase.WAITING -> WheelWaitingContent(
                partnerName = state.partnerName,
                onHome = { onNavigate(AppRoute.PLAY) },
                onAbandon = viewModel::abandon
            )
            WheelRevealPhase.REVEAL -> WheelRevealContent(
                categoryName = state.categoryName,
                partnerName = state.partnerName,
                items = state.items,
                onSpinAgain = { onNavigate(AppRoute.CATEGORY_PICKER) },
                onHome = { onNavigate(AppRoute.PLAY) }
            )
            WheelRevealPhase.ERROR -> WheelErrorContent(
                message = state.error ?: "Something went wrong.",
                onRetry = viewModel::retry,
                onHome = { onNavigate(AppRoute.PLAY) }
            )
        }

        var wheelCelebrate by remember { mutableStateOf(false) }
        var wheelCelebrated by remember { mutableStateOf(false) }
        LaunchedEffect(state.phase) {
            if (state.phase == WheelRevealPhase.REVEAL && !wheelCelebrated) {
                wheelCelebrated = true
                wheelCelebrate = true
            }
        }
        CelebrationOverlay(visible = wheelCelebrate, onFinished = { wheelCelebrate = false })
    }
}

@Composable
private fun WheelWaitingContent(
    partnerName: String,
    onHome: () -> Unit,
    onAbandon: () -> Unit = {}
) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .safeDrawingPadding()
            .navigationBarsPadding()
            .padding(horizontal = 28.dp, vertical = 40.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Spacer(Modifier.weight(1f))

        StatusGlyph(
            icon = Icons.Filled.Check,
            tint = CloserPalette.PurpleDeep,
            container = CloserPalette.PurpleMist,
            size = 82.dp,
            iconSize = 40.dp
        )
        Text(
            text = "Your answers are in!",
            style = MaterialTheme.typography.headlineMedium.copy(fontWeight = FontWeight.SemiBold),
            color = MaterialTheme.colorScheme.onSurface,
            textAlign = TextAlign.Center
        )
        Text(
            text = "We'll reveal how you each answered as soon as $partnerName finishes.",
            style = MaterialTheme.typography.bodyLarge,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            textAlign = TextAlign.Center
        )
        Spacer(Modifier.height(4.dp))
        CloserHeartLoader(size = 48.dp)

        Spacer(Modifier.weight(1f))

        OutlinedButton(
            onClick = onHome,
            modifier = Modifier
                .fillMaxWidth()
                .heightIn(min = 56.dp),
            shape = RoundedCornerShape(18.dp)
        ) {
            Text("Back to Play")
        }
        TextButton(onClick = onAbandon) {
            Text(
                "End this game",
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
        }
    }
}

@Composable
private fun WheelRevealContent(
    categoryName: String,
    partnerName: String,
    items: List<WheelRevealItem>,
    onSpinAgain: () -> Unit,
    onHome: () -> Unit
) {
    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            .safeDrawingPadding()
            .navigationBarsPadding(),
        contentPadding = PaddingValues(horizontal = 20.dp, vertical = 24.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        item {
            Column(
                modifier = Modifier.fillMaxWidth(),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                StatusGlyph(
                    icon = Icons.Filled.Check,
                    tint = CloserPalette.PurpleDeep,
                    container = CloserPalette.PurpleMist,
                    size = 72.dp,
                    iconSize = 34.dp
                )
                Text(
                    text = "Here's how you each answered",
                    style = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.SemiBold),
                    color = MaterialTheme.colorScheme.onSurface,
                    textAlign = TextAlign.Center
                )
                if (categoryName.isNotBlank()) {
                    Text(
                        text = categoryName,
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
                Spacer(Modifier.height(4.dp))
            }
        }

        items(items) { item ->
            WheelRevealRow(item = item, partnerName = partnerName)
        }

        item {
            Spacer(Modifier.height(8.dp))
            Button(
                onClick = onSpinAgain,
                modifier = Modifier
                    .fillMaxWidth()
                    .heightIn(min = 56.dp),
                shape = RoundedCornerShape(18.dp),
                colors = ButtonDefaults.buttonColors(containerColor = CloserPalette.PurpleDeep)
            ) {
                Text("Spin again", color = Color.White)
            }
            Spacer(Modifier.height(10.dp))
            OutlinedButton(
                onClick = onHome,
                modifier = Modifier
                    .fillMaxWidth()
                    .heightIn(min = 56.dp),
                shape = RoundedCornerShape(18.dp)
            ) {
                Text("Back to Play")
            }
        }
    }
}

@Composable
private fun WheelRevealRow(item: WheelRevealItem, partnerName: String) {
    Card(
        modifier = Modifier.fillMaxWidth(),
        shape = RoundedCornerShape(18.dp),
        colors = CardDefaults.cardColors(containerColor = closerCardColor(alpha = 0.9f)),
        elevation = CardDefaults.cardElevation(3.dp)
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            Text(
                text = item.questionText,
                style = MaterialTheme.typography.titleSmall.copy(fontWeight = FontWeight.SemiBold),
                color = MaterialTheme.colorScheme.onSurface
            )
            AnswerBlock(label = "You", text = item.myDisplay, accent = CloserPalette.PurpleDeep)
            AnswerBlock(label = partnerName, text = item.partnerDisplay, accent = CloserPalette.PinkAccentDeep)
        }
    }
}

@Composable
private fun AnswerBlock(label: String, text: String, accent: Color) {
    Surface(
        modifier = Modifier.fillMaxWidth(),
        shape = RoundedCornerShape(12.dp),
        color = accent.copy(alpha = 0.08f)
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp),
            horizontalArrangement = Arrangement.spacedBy(10.dp)
        ) {
            Surface(
                shape = RoundedCornerShape(999.dp),
                color = accent.copy(alpha = 0.16f)
            ) {
                Text(
                    text = label,
                    modifier = Modifier.padding(horizontal = 8.dp, vertical = 2.dp),
                    style = MaterialTheme.typography.labelSmall,
                    color = accent,
                    fontWeight = FontWeight.SemiBold,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis
                )
            }
            Text(
                text = text,
                style = MaterialTheme.typography.bodyMedium,
                color = MaterialTheme.colorScheme.onSurface
            )
        }
    }
}

@Composable
private fun WheelErrorContent(
    message: String,
    onRetry: () -> Unit,
    onHome: () -> Unit
) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .safeDrawingPadding()
            .navigationBarsPadding()
            .padding(horizontal = 28.dp, vertical = 40.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Spacer(Modifier.weight(1f))
        Text(
            text = "Couldn't load results",
            style = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.SemiBold),
            color = MaterialTheme.colorScheme.onSurface,
            textAlign = TextAlign.Center
        )
        Text(
            text = message,
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            textAlign = TextAlign.Center
        )
        Spacer(Modifier.weight(1f))
        Button(
            onClick = onRetry,
            modifier = Modifier.fillMaxWidth().heightIn(min = 56.dp),
            shape = RoundedCornerShape(18.dp),
            colors = ButtonDefaults.buttonColors(containerColor = CloserPalette.PurpleDeep)
        ) {
            Text("Try again", color = Color.White)
        }
        OutlinedButton(
            onClick = onHome,
            modifier = Modifier.fillMaxWidth().heightIn(min = 56.dp),
            shape = RoundedCornerShape(18.dp)
        ) {
            Text("Back to Play")
        }
    }
}

@Preview
@Composable
fun WheelRevealPreview() {
    Box(Modifier.background(Color(0xFFFFFBFE))) {
        WheelRevealContent(
            categoryName = "Trust",
            partnerName = "Sam",
            items = listOf(
                WheelRevealItem(
                    questionText = "When did you last feel truly seen by me?",
                    myDisplay = "When you noticed I was off last Tuesday.",
                    partnerDisplay = "At dinner on Friday."
                ),
                WheelRevealItem(
                    questionText = "Cozy night in or night out?",
                    myDisplay = "Cozy night in",
                    partnerDisplay = "Cozy night in"
                )
            ),
            onSpinAgain = {},
            onHome = {}
        )
    }
}
