package eu.gaudian.translator.view.vocabulary

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation.NavController
import eu.gaudian.translator.R
import eu.gaudian.translator.model.Language
import eu.gaudian.translator.model.VocabularyItem
import eu.gaudian.translator.ui.theme.semanticColors
import eu.gaudian.translator.utils.findActivity
import eu.gaudian.translator.view.composable.AppButton
import eu.gaudian.translator.view.composable.ComponentDefaults
import eu.gaudian.translator.view.vocabulary.card.VocabularyExerciseCard
import eu.gaudian.translator.viewmodel.LanguageViewModel

/**
 * Represents the different types of exercises available.
 * This enum can be expanded with new exercise types.
 */
enum class VocabularyExerciseType {
    GUESSING,
    SPELLING,
    MULTIPLE_CHOICE,
    WORD_JUMBLE
}

/**
 * A sealed interface to represent the state of an exercise.
 * Each exercise type will have its own state implementation.
 */
sealed interface VocabularyExerciseState {
    val item: VocabularyItem
    val isRevealed: Boolean
    val isCorrect: Boolean?
    val isSwitched: Boolean

    data class Guessing(
        override val item: VocabularyItem,
        override val isRevealed: Boolean = false,
        override val isCorrect: Boolean? = null,
        override val isSwitched: Boolean = false,
    ) : VocabularyExerciseState

    data class Spelling(
        override val item: VocabularyItem,
        val userAnswer: String = "",
        override val isRevealed: Boolean = false,
        override val isCorrect: Boolean? = null,
        override val isSwitched: Boolean = false,
    ) : VocabularyExerciseState

    data class MultipleChoice(
        override val item: VocabularyItem,
        val options: List<String>,
        val selectedAnswer: String? = null,
        override val isRevealed: Boolean = false,
        override val isCorrect: Boolean? = null,
        override val isSwitched: Boolean = false,
    ) : VocabularyExerciseState

    data class WordJumble(
        override val item: VocabularyItem,
        val jumbledLetters: List<Pair<Char, Int>>, // Pair of Char and a unique ID for stability
        val assembledWord: List<Pair<Char, Int>> = emptyList(),
        override val isRevealed: Boolean = false,
        override val isCorrect: Boolean? = null,
        override val isSwitched: Boolean = false,
    ) : VocabularyExerciseState
}

/**
 * A generic renderer for exercises. It takes an ExerciseState
 * and renders the appropriate UI for that state.
 */
@Composable
fun VocabularyExerciseRenderer(
    state: VocabularyExerciseState,
    onAction: (VocabularyExerciseAction) -> Unit,
    navController: NavController
) {
    when (state) {
        is VocabularyExerciseState.Guessing -> GuessingExercise(state, navController)
        is VocabularyExerciseState.Spelling -> SpellingExercise(state, navController)
        is VocabularyExerciseState.MultipleChoice -> MultipleChoiceExercise(state, onAction)
        is VocabularyExerciseState.WordJumble -> WordJumbleExercise(state, onAction)
    }
}





sealed interface VocabularyExerciseAction {
    data object Reveal : VocabularyExerciseAction
    data class Submit(val answer: Any) : VocabularyExerciseAction
    data object Next : VocabularyExerciseAction
    data class UpdateWordJumble(val assembledWord: List<Pair<Char, Int>>) : VocabularyExerciseAction
}

@Composable
fun GuessingExercise(
    state: VocabularyExerciseState.Guessing,
    navController: NavController,
) {

    VocabularyExerciseCard(
        vocabularyItem = state.item,
        isFlipped = state.isRevealed,
        navController = navController,
        switchOrder = state.isSwitched,
    )
}



@Composable
fun SpellingExercise(
    state: VocabularyExerciseState.Spelling,
    navController: NavController,
) {

    VocabularyExerciseCard(
        vocabularyItem = state.item,
        isFlipped = state.isRevealed,
        userSpellingAnswer = state.userAnswer,
        isUserSpellingCorrect = state.isCorrect,
        navController = navController,
        switchOrder = state.isSwitched,
    )
}



@Composable
fun MultipleChoiceExercise(
    state: VocabularyExerciseState.MultipleChoice,
    onAction: (VocabularyExerciseAction) -> Unit
) {
    val activity = LocalContext.current.findActivity()
    val languageViewModel: LanguageViewModel = hiltViewModel(viewModelStoreOwner = activity)
    var languageFirst by remember { mutableStateOf<Language?>(null) }
    var languageSecond by remember { mutableStateOf<Language?>(null) }

    LaunchedEffect(state.item.languageFirstId, state.item.languageSecondId) {
        languageFirst = languageViewModel.getLanguageById(state.item.languageFirstId ?: 0)
        languageSecond = languageViewModel.getLanguageById(state.item.languageSecondId ?: 0)
    }

    val correctAnswer = if (state.isSwitched) state.item.wordFirst else state.item.wordSecond
    val promptLanguage = if (state.isSwitched) languageSecond else languageFirst
    val targetLanguage = if (state.isSwitched) languageFirst else languageSecond

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.SpaceBetween
    ) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Text(
                text = stringResource(R.string.label_translate_from_2d, promptLanguage?.name ?: ""),
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
            Text(
                text = if (state.isSwitched) state.item.wordSecond else state.item.wordFirst,
                style = MaterialTheme.typography.displaySmall,
                textAlign = TextAlign.Center,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
            Text(
                text = stringResource(R.string.to_d, targetLanguage?.name ?: ""),
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                modifier = Modifier.padding(top = 8.dp)
            )
        }

        Column(
            modifier = Modifier.fillMaxWidth(),
            verticalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            state.options.forEach { option ->
                val isSelected = state.selectedAnswer == option
                val isCorrectOption = option == correctAnswer

                val buttonColors = when {
                    // After reveal: show correct as filled CorrectButton, wrong selected as filled WrongButton
                    state.isRevealed && isCorrectOption -> ButtonDefaults.buttonColors(
                        containerColor = MaterialTheme.semanticColors.success,
                        contentColor = MaterialTheme.semanticColors.onSuccess
                    )
                    state.isRevealed && isSelected && !isCorrectOption -> ButtonDefaults.buttonColors(
                        containerColor = MaterialTheme.semanticColors.wrong,
                        contentColor = MaterialTheme.semanticColors.onWrong
                    )
                    // Before reveal: keep neutral outlined look until selection
                    !state.isRevealed && isSelected && isCorrectOption -> ButtonDefaults.buttonColors(
                        containerColor = MaterialTheme.semanticColors.success.copy(alpha = 0.85f),
                        contentColor = MaterialTheme.semanticColors.onSuccess
                    )
                    !state.isRevealed && isSelected && !isCorrectOption -> ButtonDefaults.buttonColors(
                        containerColor = MaterialTheme.semanticColors.wrong.copy(alpha = 0.85f),
                        contentColor = MaterialTheme.semanticColors.onWrong
                    )
                    else -> ButtonDefaults.outlinedButtonColors()
                }

                val borderColor = when {
                    state.isRevealed -> Color.Transparent
                    isSelected && !isCorrectOption -> MaterialTheme.colorScheme.error
                    isSelected && isCorrectOption -> MaterialTheme.semanticColors.success
                    else -> MaterialTheme.colorScheme.outline
                }

                AppButton(
                    onClick = { if (!state.isRevealed) onAction(VocabularyExerciseAction.Submit(option)) },
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(50.dp),
                    colors = buttonColors,
                    border = BorderStroke(1.dp, borderColor)
                ) {
                    val textColor = when {
                        state.isRevealed && isCorrectOption -> MaterialTheme.semanticColors.onSuccess
                        state.isRevealed && isSelected && !isCorrectOption -> MaterialTheme.semanticColors.onWrong
                        !state.isRevealed && isSelected && isCorrectOption -> MaterialTheme.semanticColors.onSuccess
                        !state.isRevealed && isSelected && !isCorrectOption -> MaterialTheme.semanticColors.onWrong
                        else -> MaterialTheme.colorScheme.onSurfaceVariant
                    }
                    Text(option, color = textColor)
                }
            }

            // Optional textual feedback when an option was selected
            if (state.selectedAnswer != null && !state.isRevealed) {
                val wasCorrect = state.selectedAnswer == correctAnswer
                val msg = if (wasCorrect) stringResource(R.string.text_correct_em) else stringResource(R.string.label_wrong)
                val color = if (wasCorrect) MaterialTheme.semanticColors.success else MaterialTheme.colorScheme.error
                Text(text = msg, color = color, style = MaterialTheme.typography.bodyMedium)
            }
        }
    }
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun MultipleChoiceExercisePreview() {
    val vocabularyItem = VocabularyItem(
        id = 1,
        languageFirstId = 1,
        languageSecondId = 2,
        wordFirst = "Hello",
        wordSecond = "Hola"
    )
    val state = VocabularyExerciseState.MultipleChoice(
        item = vocabularyItem,
        options = listOf("Hola", "Bonjour", "Hallo", "Ciao"),
        selectedAnswer = "Hola",
        isRevealed = true,
        isCorrect = true,
        isSwitched = false
    )
    MultipleChoiceExercise(state = state, onAction = {})
}



@Composable
fun WordJumbleExercise(
    state: VocabularyExerciseState.WordJumble,
    onAction: (VocabularyExerciseAction) -> Unit
) {
    val activity = LocalContext.current.findActivity()
    val languageViewModel: LanguageViewModel = hiltViewModel(viewModelStoreOwner = activity)
    var languageFirst by remember { mutableStateOf<Language?>(null) }
    var languageSecond by remember { mutableStateOf<Language?>(null) }

    LaunchedEffect(state.item.languageFirstId, state.item.languageSecondId) {
        languageFirst = languageViewModel.getLanguageById(state.item.languageFirstId ?: 0)
        languageSecond = languageViewModel.getLanguageById(state.item.languageSecondId ?: 0)
    }

    val availableLetters = remember(state.jumbledLetters, state.assembledWord) {
        state.jumbledLetters.filterNot { it in state.assembledWord }
    }
    val correctAnswer = if (state.isSwitched) state.item.wordFirst else state.item.wordSecond

    // NEW: Group available letters by character to get counts
    val groupedAvailableLetters = remember(availableLetters) {
        availableLetters
            .groupBy { it.first } // Groups into a Map<Char, List<Pair<Char, Int>>>
            .map { (char, instances) ->
                // Triple stores: 1. The character, 2. Its count, 3. The ID of the first instance for a stable key
                Triple(char, instances.size, instances.first().second)
            }
    }


    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.SpaceBetween
    ) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            val promptLanguage = if (state.isSwitched) languageSecond else languageFirst
            val targetLanguage = if (state.isSwitched) languageFirst else languageSecond

            Text(
                text = stringResource(R.string.label_translate_from_2d, promptLanguage?.name ?: ""),
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )

            Text(
                text = if (state.isSwitched) state.item.wordSecond else state.item.wordFirst,
                style = MaterialTheme.typography.displaySmall,
                textAlign = TextAlign.Center,
                modifier = Modifier.padding(bottom = 8.dp),
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )

            Text(
                text = stringResource(R.string.to_d, targetLanguage?.name ?: ""),
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
        }


        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            FlowRow(
                modifier = Modifier
                    .fillMaxWidth()
                    .defaultMinSize(minHeight = 60.dp)
                    .border(1.dp, MaterialTheme.colorScheme.outline, RoundedCornerShape(8.dp))
                    .padding(8.dp),
                horizontalArrangement = if (state.assembledWord.isEmpty()) Arrangement.Center else Arrangement.spacedBy(8.dp),
                verticalArrangement = if (state.assembledWord.isEmpty()) Arrangement.Center else Arrangement.spacedBy(8.dp)
            ) {
                if (state.assembledWord.isEmpty()) {
                    Text(stringResource(R.string.text_assemble_the_word_here), color = MaterialTheme.colorScheme.onSurfaceVariant)
                } else {
                    state.assembledWord.forEach { (char, id) ->
                        LetterPill(char = char, isDraggable = true, onClick = {
                            val newAssembled = state.assembledWord.toMutableList().apply { remove(Pair(char, id)) }
                            onAction(VocabularyExerciseAction.UpdateWordJumble(newAssembled))
                        })
                    }
                }
            }

            Spacer(Modifier.height(8.dp))
            if (state.isRevealed) {
                val color = if (state.isCorrect == true) Color(0xFF4CAF50) else MaterialTheme.colorScheme.error
                Text(if (state.isCorrect == true) stringResource(R.string.text_correct_em) else stringResource(
                    R.string.correct_answer, correctAnswer
                ), color = color)
            } else {
                Surface(shadowElevation = ComponentDefaults.DefaultElevation) {
                    AppButton(
                        onClick = {
                            val assembledString = state.assembledWord.map { it.first }.joinToString("")
                            onAction(VocabularyExerciseAction.Submit(assembledString))
                        },
                        enabled = state.assembledWord.isNotEmpty(),
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(16.dp)
                            .height(50.dp)
                    ) {
                        Text(stringResource(R.string.text_check), fontWeight = FontWeight.Bold)
                    }
                }
            }

            Spacer(Modifier.height(24.dp))

            // Available letters - UPDATED LOGIC
            LazyRow(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally)
            ) {
                items(groupedAvailableLetters, key = { it.third }) { (char, count, _) ->
                    // This is the action to perform when a letter is clicked
                    val onClickAction = {
                        if (!state.isRevealed) {
                            // Find the first available instance of the clicked character
                            val instanceToMove = availableLetters.first { it.first == char }
                            val newAssembled = state.assembledWord + instanceToMove
                            onAction(VocabularyExerciseAction.UpdateWordJumble(newAssembled))
                        }
                    }

                    // If count is > 1, show the grouped pill. Otherwise, show the original single pill.
                    if (count > 1) {
                        GroupedLetterPill(
                            char = char,
                            count = count,
                            isDraggable = !state.isRevealed,
                            onClick = onClickAction
                        )
                    } else {
                        LetterPill(
                            char = char,
                            isDraggable = !state.isRevealed,
                            onClick = onClickAction
                        )
                    }
                }
            }
        }
    }
}



@Composable
private fun LetterPill(char: Char, isDraggable: Boolean, onClick: () -> Unit) {
    Box(
        modifier = Modifier
            .size(48.dp)
            .clip(CircleShape)
            .background(MaterialTheme.colorScheme.primaryContainer)
            .then(if (isDraggable) Modifier.clickable(onClick = onClick) else Modifier)
            .padding(4.dp),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = char.uppercase(),
            style = MaterialTheme.typography.titleLarge,
            color = MaterialTheme.colorScheme.onPrimaryContainer
        )
    }
}

@Composable
private fun GroupedLetterPill(
    char: Char,
    count: Int,
    isDraggable: Boolean,
    onClick: () -> Unit
) {
    Box { // Use a Box to stack the pill and the count badge
        // The base is the standard round letter pill
        LetterPill(char = char, isDraggable = isDraggable, onClick = onClick)

        // This is the count badge, styled and aligned on top
        Box(
            modifier = Modifier
                .align(Alignment.TopStart) // Position in the top-left corner
                .size(20.dp) // Give the badge a fixed circular size
                .background(
                    color = MaterialTheme.colorScheme.secondary,
                    shape = CircleShape
                )
                // Add a small border to make it pop
                .border(1.dp, MaterialTheme.colorScheme.background, CircleShape),
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = count.toString(),
                color = MaterialTheme.colorScheme.onSecondary,
                style = MaterialTheme.typography.labelSmall, // Use a small font style
                textAlign = TextAlign.Center
            )
        }
    }
}