package eu.gaudian.translator.view.exercises

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
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.Row
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
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.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
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.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import eu.gaudian.translator.R
import eu.gaudian.translator.model.CategorizationQuestion
import eu.gaudian.translator.model.Language
import eu.gaudian.translator.model.ListeningComprehensionQuestion
import eu.gaudian.translator.model.MatchingPairsQuestion
import eu.gaudian.translator.model.VocabularyTestQuestion
import eu.gaudian.translator.model.WordOrderQuestion
import eu.gaudian.translator.utils.TextToSpeechHelper
import eu.gaudian.translator.utils.findActivity
import eu.gaudian.translator.view.composable.AppButton
import eu.gaudian.translator.view.composable.AppIcons
import eu.gaudian.translator.view.composable.AppOutlinedTextField
import eu.gaudian.translator.viewmodel.SettingsViewModel
import kotlinx.coroutines.launch
import java.util.Locale

@Composable
fun WordChip(text: String, isSelected: Boolean, onClick: () -> Unit, enabled: Boolean = true) {
    AppButton(
        onClick = onClick,
        enabled = enabled,
        shape = RoundedCornerShape(16.dp),
        colors = ButtonDefaults.buttonColors(
            containerColor = if (isSelected) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface,
            contentColor = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurface
        ),
        border = BorderStroke(2.dp, if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.outline)
    ) {
        Text(text)
    }
}

@Composable
@Preview
fun WordChipPreview() {
    WordChip(
        text = stringResource(R.string.text_sample_word),
        isSelected = false,
        onClick = {}
    )
}

@Composable
fun FillInTheBlankQuestionUi(
    question: eu.gaudian.translator.model.FillInTheBlankQuestion,
    selectedAnswer: String,
    onAnswerSelect: (String) -> Unit,
    isLocked: Boolean
) {
    val correct = question.correctAnswer
    val firstLetter = correct.firstOrNull()?.toString() ?: ""
    val placeholder = if (firstLetter.isNotBlank()) firstLetter + "_".repeat((correct.length - 1).coerceAtLeast(1)) else "_".repeat(correct.length.coerceAtLeast(1))

    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        if (question.hintBaseForm.isNotBlank()) {
            Text(stringResource(R.string.hint, question.hintBaseForm))
        }
        if (question.hintOptions.isNotEmpty()) {
            FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
                question.hintOptions.forEach { option ->
                    WordChip(text = option, isSelected = false, onClick = { if (!isLocked) onAnswerSelect(option) }, enabled = !isLocked)
                }
            }
        }
        AppOutlinedTextField(
            value = selectedAnswer,
            onValueChange = onAnswerSelect,
            placeholder = { Text(placeholder) },
            label = { Text(stringResource(R.string.label_your_answer)) },
            modifier = Modifier.fillMaxWidth(),
            enabled = !isLocked,
            singleLine = true
        )
    }
}

@Suppress("HardCodedStringLiteral")
@Composable
@Preview
fun FillInTheBlankQuestionUiPreview() {
    val question = eu.gaudian.translator.model.FillInTheBlankQuestion(
        id = 1,
        name = "The capital of France is ___.",
        correctAnswer = "Paris",
        hintBaseForm = "City in Europe",
        hintOptions = listOf("Berlin", "Madrid", "Paris", "Rome")
    )
    var selectedAnswer by remember { mutableStateOf("") }
    FillInTheBlankQuestionUi(
        question = question,
        selectedAnswer = selectedAnswer,
        onAnswerSelect = {
            @Suppress("AssignedValueIsNeverRead")
            selectedAnswer = it
        },
        isLocked = false)
}

@Composable
fun WordOrderQuestionUi(
    question: WordOrderQuestion,
    selectedAnswer: List<String>,
    onAnswerSelect: (List<String>) -> Unit,
    isLocked: Boolean
) {
    val baseWords = remember(question.words, question.correctOrder) {
        if (question.words == question.correctOrder) question.words.shuffled() else question.words
    }
    val availableWords = remember(baseWords, selectedAnswer) {
        val selectedCounts = selectedAnswer.groupingBy { it }.eachCount()
        baseWords.filter { word ->
            (selectedCounts[word] ?: 0) < baseWords.count { it == word }
        }
    }

    Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .defaultMinSize(minHeight = 70.dp)
                .clip(RoundedCornerShape(8.dp))
                .border(1.dp, MaterialTheme.colorScheme.outline, RoundedCornerShape(8.dp))
                .padding(8.dp)
        ) {
            if (selectedAnswer.isEmpty()) {
                Text(stringResource(R.string.tap_the_words_below_to_form_the_sentence), color = MaterialTheme.colorScheme.onSurfaceVariant)
            } else {
                FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
                    selectedAnswer.forEachIndexed { index, word ->
                        WordChip(
                            text = word,
                            isSelected = false,
                            enabled = !isLocked,
                            onClick = {
                                val newList = selectedAnswer.toMutableList()
                                newList.removeAt(index)
                                onAnswerSelect(newList)
                            }
                        )
                    }
                }
            }
        }

        // The bank of available words
        FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
            availableWords.forEach { word ->
                WordChip(
                    text = word,
                    isSelected = false,
                    enabled = !isLocked,
                    onClick = { onAnswerSelect(selectedAnswer + word) }
                )
            }
        }
    }
}

@Suppress("HardCodedStringLiteral")
@Composable
@Preview
fun WordOrderQuestionUiPreview() {
    val question = WordOrderQuestion(
        id = 1,
        name = "Form the sentence.",
        words = listOf("the", "quick", "brown", "fox"),
        correctOrder = listOf("the", "quick", "brown", "fox")
    )
    var selectedAnswer by remember { mutableStateOf<List<String>>(emptyList()) }
    WordOrderQuestionUi(
        question = question,
        selectedAnswer = selectedAnswer,
        onAnswerSelect = {
            @Suppress("AssignedValueIsNeverRead")
            selectedAnswer = it
        },
        isLocked = false
    )
}

@Composable
fun MatchingPairsQuestionUi(
    question: MatchingPairsQuestion,
    selectedAnswer: Map<String, String>,
    onAnswerSelect: (Map<String, String>) -> Unit,
    isLocked: Boolean
) {
    var selectedKey by remember { mutableStateOf<String?>(null) }
    val keys = remember(question.pairs) { question.pairs.keys.shuffled() }
    val values = remember(question.pairs) { question.pairs.values.shuffled() }

    // When locked (after check), highlight correct vs incorrect matches
    val correctnessMap = remember(selectedAnswer, question.pairs, isLocked) {
        if (!isLocked) emptyMap()
        else selectedAnswer.mapValues { (k, v) -> question.pairs[k] == v }
    }

    Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
        Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(8.dp)) {
            keys.forEach { key ->
                val isSelected = selectedKey == key || selectedAnswer.containsKey(key)
                val isCorrect = correctnessMap[key]
                val label = if (isLocked && isCorrect == false) "$key ✗" else if (isLocked && isCorrect == true) "$key ✓" else key
                AnswerButton(
                    text = label,
                    isSelected = isSelected,
                    enabled = !isLocked && !selectedAnswer.containsKey(key),
                    onClick = { selectedKey = key }
                )
            }
        }
        Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(8.dp)) {
            values.forEach { value ->
                val isSelected = selectedAnswer.containsValue(value)
                AnswerButton(
                    text = value,
                    isSelected = isSelected,
                    enabled = !isLocked && !isSelected,
                    onClick = {
                        selectedKey?.let { key ->
                            onAnswerSelect(selectedAnswer + (key to value))
                            selectedKey = null
                        }
                    }
                )
            }
        }
    }
}

@Suppress("HardCodedStringLiteral")
@Composable
@Preview
fun MatchingPairsQuestionUiPreview() {
    val question = MatchingPairsQuestion(
        id = 1,
        name = "Match the capitals to their countries.",
        pairs = mapOf("France" to "Paris", "Germany" to "Berlin", "Spain" to "Madrid")
    )
    var selectedAnswer by remember { mutableStateOf<Map<String, String>>(emptyMap()) }
    MatchingPairsQuestionUi(
        question = question,
        selectedAnswer = selectedAnswer,
        onAnswerSelect = {
            @Suppress("AssignedValueIsNeverRead")
            selectedAnswer = it
        },
        isLocked = false
    )
}


@Composable
fun ListeningComprehensionQuestionUi(
    question: ListeningComprehensionQuestion,
    selectedAnswer: String,
    onAnswerSelect: (String) -> Unit,
    isLocked: Boolean
) {
    val context = LocalContext.current
    val scope = rememberCoroutineScope()
    val activity = LocalContext.current.findActivity()
    val settingsViewModel: SettingsViewModel = hiltViewModel(viewModelStoreOwner = activity)
    val maskedHint = remember(question.name) {
        val words = question.name.split(" ").filter { it.isNotBlank() }
        if (words.size < 4) "" else {
            val blankCount = (words.size * 0.4).toInt().coerceAtLeast(1)
            val indicesToBlank = words.indices.shuffled().take(blankCount).toSet()
            words.mapIndexed { idx, w -> if (idx in indicesToBlank) "___" else w }
                .joinToString(" ")
        }
    }

    Column(verticalArrangement = Arrangement.spacedBy(16.dp), horizontalAlignment = Alignment.CenterHorizontally) {
        IconButton(
            onClick = {
                scope.launch {
                    val locale = Locale.forLanguageTag(question.languageCode)
                    val language = Language(
                        nameResId = 0,
                        code = locale.language,
                        region = locale.country,
                        name = locale.displayName,
                        englishName = locale.displayName,
                        isCustom = false,
                        isSelected = true
                    )
                    val voice = settingsViewModel.getTtsVoiceForLanguage(language.code, language.region)
                    TextToSpeechHelper.speakOut(context, question.name, language, voice)
                }
            },
            modifier = Modifier.size(80.dp)
        ) {
            Icon(AppIcons.TextToSpeech, contentDescription = stringResource(R.string.listen), modifier = Modifier.fillMaxSize())
        }
        // Do NOT show the full sentence; show a masked hint instead (if available)
        if (maskedHint.isNotBlank()) {
            Text(maskedHint, style = MaterialTheme.typography.bodyMedium)
        }
        AppOutlinedTextField(
            value = selectedAnswer,
            onValueChange = onAnswerSelect,
            label = { Text(stringResource(R.string.type_what_you_hear)) },
            modifier = Modifier.fillMaxWidth(),
            enabled = !isLocked
        )
    }
}

@Suppress("HardCodedStringLiteral")
@Composable
@Preview
fun ListeningComprehensionQuestionUiPreview() {
    val question = ListeningComprehensionQuestion(
        id = 1,
        name = "This is a sample sentence to be spoken.",
        languageCode = "en-US"
    )
    var selectedAnswer by remember { mutableStateOf("") }
    ListeningComprehensionQuestionUi(
        question = question,
        selectedAnswer = selectedAnswer,
        onAnswerSelect = {
            @Suppress("AssignedValueIsNeverRead")
            selectedAnswer = it
        },
        isLocked = false
    )
}

@Composable
fun CategorizationQuestionUi(
    question: CategorizationQuestion,
    selectedAnswer: Map<String, String>,
    onAnswerSelect: (Map<String, String>) -> Unit,
    isLocked: Boolean
) {
    val unassignedItems = remember(question.items, selectedAnswer) {
        question.items.filter { !selectedAnswer.containsKey(it) }
    }

    val correctnessMap = remember(selectedAnswer, isLocked) {
        if (!isLocked) emptyMap() else question.items.associateWith { item ->
            val chosen = selectedAnswer[item]
            val correct = question.correctMapping[item]
            chosen != null && chosen == correct
        }
    }

    Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            question.categories.forEach { category ->
                Column(
                    modifier = Modifier
                        .weight(1f)
                        .background(
                            MaterialTheme.colorScheme.surfaceVariant,
                            RoundedCornerShape(8.dp)
                        )
                        .padding(8.dp),
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.spacedBy(4.dp)
                ) {
                    Text(category, fontWeight = FontWeight.Bold)
                    selectedAnswer.filterValues { it == category }.keys.forEach { item ->
                        val isCorrect = correctnessMap[item]
                        val suffix = if (isLocked) {
                            if (isCorrect == true) " ✓" else if (isCorrect == false) " ✗" else ""
                        } else ""
                        Text(item + suffix, style = MaterialTheme.typography.bodySmall)
                    }
                }
            }
        }

        if (unassignedItems.isNotEmpty() && !isLocked) {
            var expandedItem by remember { mutableStateOf<String?>(null) }
            Text(stringResource(R.string.text_assign_these_items_2d), style = MaterialTheme.typography.labelLarge)
            LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                items(unassignedItems) { item ->
                    Box {
                        WordChip(
                            text = item,
                            isSelected = false,
                            enabled = !isLocked,
                            onClick = { expandedItem = item }
                        )
                        DropdownMenu(
                            expanded = expandedItem == item,
                            onDismissRequest = { expandedItem = null }
                        ) {
                            question.categories.forEach { category ->
                                DropdownMenuItem(
                                    text = { Text(category) },
                                    onClick = {
                                        onAnswerSelect(selectedAnswer + (item to category))
                                        expandedItem = null
                                    }
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}

@Suppress("HardCodedStringLiteral")
@Composable
@Preview
fun CategorizationQuestionUiPreview() {
    val question = CategorizationQuestion(
        id = 1,
        name = "Sort these items into categories.",
        items = listOf("Apple", "Banana", "Carrot", "Broccoli"),
        categories = listOf("Fruit", "Vegetable"),
        correctMapping = mapOf("Apple" to "Fruit", "Banana" to "Fruit", "Carrot" to "Vegetable", "Broccoli" to "Vegetable")
    )
    var selectedAnswer by remember { mutableStateOf<Map<String, String>>(emptyMap()) }
    CategorizationQuestionUi(
        question = question,
        selectedAnswer = selectedAnswer,
        onAnswerSelect = {
            @Suppress("AssignedValueIsNeverRead")
            selectedAnswer = it
        },
        isLocked = false
    )
}


@Composable
fun VocabularyTestQuestionUi(
    question: VocabularyTestQuestion,
    selectedAnswer: String,
    onAnswerSelect: (String) -> Unit,
    isLocked: Boolean
) {
    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        Text(
            text = stringResource(R.string.translate_the_following_d, question.languageDirection),
            style = MaterialTheme.typography.bodyMedium
        )
        AppOutlinedTextField(
            value = selectedAnswer,
            onValueChange = onAnswerSelect,
            label = { Text(stringResource(R.string.label_your_translation)) },
            modifier = Modifier.fillMaxWidth(),
            enabled = !isLocked,
            singleLine = true
        )
    }
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun VocabularyTestQuestionUiPreview() {
    val question = VocabularyTestQuestion(
        id = 1,
        name = "Hello",
        correctAnswer = "Hola",
        languageDirection = "English to Spanish"
    )
    var selectedAnswer by remember { mutableStateOf("") }
    VocabularyTestQuestionUi(
        question = question,
        selectedAnswer = selectedAnswer,
        onAnswerSelect = {
            @Suppress("AssignedValueIsNeverRead")
            selectedAnswer = it
        },
        isLocked = false)
}