package eu.gaudian.translator.view.exercises

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
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.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.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
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.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import eu.gaudian.translator.R
import eu.gaudian.translator.model.CategorizationQuestion
import eu.gaudian.translator.model.Exercise
import eu.gaudian.translator.model.FillInTheBlankQuestion
import eu.gaudian.translator.model.ListeningComprehensionQuestion
import eu.gaudian.translator.model.MatchingPairsQuestion
import eu.gaudian.translator.model.MultipleChoiceQuestion
import eu.gaudian.translator.model.TrueFalseQuestion
import eu.gaudian.translator.model.VocabularyTestQuestion
import eu.gaudian.translator.model.WordOrderQuestion
import eu.gaudian.translator.ui.theme.ThemePreviews
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.AppIcons
import eu.gaudian.translator.view.composable.ComponentDefaults
import eu.gaudian.translator.view.vocabulary.ExerciseProgressIndicator
import eu.gaudian.translator.viewmodel.AnswerResult
import eu.gaudian.translator.viewmodel.ExerciseSessionState
import eu.gaudian.translator.viewmodel.ExerciseViewModel
import eu.gaudian.translator.viewmodel.VocabularyViewModel


@Composable
fun ExerciseSessionScreen(
    navController: NavController,
) {
    val activity = LocalContext.current.findActivity()
    val vocabularyViewModel: VocabularyViewModel = hiltViewModel(viewModelStoreOwner = activity)
    val exerciseViewModel: ExerciseViewModel = hiltViewModel(viewModelStoreOwner = activity)

    val sessionState by exerciseViewModel.exerciseSessionState.collectAsState()

    var showVocabulary by remember { mutableStateOf(true) }
    var vocabularyChecked by remember { mutableStateOf(false) }

    LaunchedEffect(sessionState) {
        if (!vocabularyChecked && sessionState != null) {
            val vocabIds = sessionState?.exercise?.associatedVocabularyIds
            if (!vocabIds.isNullOrEmpty()) {
                vocabularyViewModel.filterByIds(vocabIds)
                showVocabulary = true
            } else {
                showVocabulary = false
            }
            vocabularyChecked = true
        }
    }

    DisposableEffect(Unit) {
        onDispose {
            exerciseViewModel.closeExercise()
            vocabularyViewModel.clearFilter()
        }
    }

    val currentSession = sessionState
    if (currentSession == null) {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            CircularProgressIndicator()
        }
        return
    }

    if (currentSession.isExerciseFinished) {
        GenericResultScreen(
            score = currentSession.correctAnswers,
            wrongAnswers = currentSession.wrongAnswers,
            totalItems = currentSession.questions.size,
            onFinish = {
                exerciseViewModel.closeExercise()
                navController.popBackStack()
            }
        )
        return
    }

    if (showVocabulary) {
        ExerciseVocabularyScreen(
            onStartExercise = {
                vocabularyViewModel.clearFilter()
                @Suppress("AssignedValueIsNeverRead")
                showVocabulary = false
            },
            navController = navController
        )
    } else {
        ExerciseQuestionScreen(
            state = currentSession,
            onAnswerSelect = { answer -> exerciseViewModel.selectAnswer(answer) },
            onCheckClick = { exerciseViewModel.checkAnswer() },
            onContinueClick = { exerciseViewModel.nextQuestion() },
            onCloseClick = {
                navController.popBackStack()
            },
            navController =navController
        )
    }
}

@Suppress("HardCodedStringLiteral")
@ThemePreviews
@Composable
fun ExerciseQuestionScreenPreview() {
    val sampleQuestion = TrueFalseQuestion(id = 1, name = "Is the sky blue?", correctAnswer = true)
    val sampleState = ExerciseSessionState(
        exercise = Exercise(id = "1", title = "Sample Exercise", questions = listOf(1)),
        questions = listOf(sampleQuestion),
        currentQuestionIndex = 0,
        correctAnswers = 0,
        wrongAnswers = 0,
        selectedAnswer = null,
        answerResult = AnswerResult.UNCHECKED
    )
    ExerciseQuestionScreen(
        state = sampleState,
        onAnswerSelect = {},
        onCheckClick = {},
        onContinueClick = {},
        onCloseClick = {},
        navController = rememberNavController()
    )
}

@Composable
fun GenericResultScreen(
    score: Int,
    wrongAnswers: Int,
    totalItems: Int,
    onFinish: () -> Unit
) {
    val percentage = if (totalItems > 0) score.toFloat() / totalItems.toFloat() else 0f
    val animatedProgress by androidx.compose.animation.core.animateFloatAsState(
        targetValue = percentage,
        animationSpec = tween(durationMillis = 1200),
        label = "ResultProgressAnimationGeneric"
    )
    Scaffold(
        topBar = {
            androidx.compose.material3.TopAppBar(
                title = { Text(stringResource(R.string.result)) }
            )
        }
    ) { paddingValues ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues)
                .padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.SpaceAround
        ) {
            Column(horizontalAlignment = Alignment.CenterHorizontally) {
                Text(
                    text = stringResource(R.string.exercise_complete),
                    style = MaterialTheme.typography.headlineLarge,
                    fontWeight = FontWeight.Bold
                )
                androidx.compose.foundation.layout.Spacer(modifier = Modifier.height(8.dp))
                Text(
                    text = stringResource(R.string.here_s_how_you_did),
                    style = MaterialTheme.typography.titleMedium,
                    color = MaterialTheme.colorScheme.onSurfaceVariant
                )
            }
            Box(contentAlignment = Alignment.Center, modifier = Modifier.size(220.dp)) {
                CircularProgressIndicator(
                    progress = { animatedProgress },
                    modifier = Modifier.fillMaxSize(),
                    strokeWidth = 16.dp,
                    color = MaterialTheme.colorScheme.primary,
                    trackColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f),
                )
                Text(
                    text = "${(percentage * 100).toInt()}%",
                    style = MaterialTheme.typography.displayMedium,
                    fontWeight = FontWeight.Bold
                )
            }
            androidx.compose.material3.Card(
                modifier = Modifier.fillMaxWidth(),
                colors = androidx.compose.material3.CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface)
            ) {
                Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
                    Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(vertical = 8.dp)) {
                        androidx.compose.material3.Icon(
                            imageVector = AppIcons.CheckCircle,
                            contentDescription = null,
                            tint = MaterialTheme.colorScheme.primary,
                            modifier = Modifier.size(32.dp)
                        )
                        androidx.compose.foundation.layout.Spacer(modifier = Modifier.width(16.dp))
                        Text(text = stringResource(R.string.label_correct), style = MaterialTheme.typography.titleLarge, modifier = Modifier.weight(1f))
                        Text(text = "$score / $totalItems", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary)
                    }
                    androidx.compose.material3.HorizontalDivider()
                    Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(vertical = 8.dp)) {
                        androidx.compose.material3.Icon(
                            imageVector = AppIcons.Error,
                            contentDescription = null,
                            tint = MaterialTheme.colorScheme.error,
                            modifier = Modifier.size(32.dp)
                        )
                        androidx.compose.foundation.layout.Spacer(modifier = Modifier.width(16.dp))
                        Text(text = stringResource(R.string.label_wrong), style = MaterialTheme.typography.titleLarge, modifier = Modifier.weight(1f))
                        Text(text = "$wrongAnswers", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.error)
                    }
                }
            }
            AppButton(
                onClick = onFinish,
                modifier = Modifier
                    .fillMaxWidth()
                    .height(48.dp)
            ) {
                Text(stringResource(R.string.finish))
            }
        }
    }
}

@Composable
fun ExerciseQuestionScreen(
    state: ExerciseSessionState,
    onAnswerSelect: (Any) -> Unit,
    onCheckClick: () -> Unit,
    onContinueClick: () -> Unit,
    onCloseClick: () -> Unit,
    navController: NavController
) {
    val activity = LocalContext.current.findActivity()
    val exerciseViewModel = hiltViewModel<ExerciseViewModel>(viewModelStoreOwner = activity)


    Scaffold(
        topBar = {
            ExerciseProgressIndicator(
                correctAnswers = state.correctAnswers,
                wrongAnswers = state.wrongAnswers,
                totalItems = state.questions.size,
                onClose = onCloseClick
            )
        },
        bottomBar = {
            BottomBar(
                answerResult = state.answerResult,
                onCheckClick = onCheckClick,
                onContinueClick = onContinueClick,
                isCheckEnabled = state.isAnswerSelected(),
                secondaryText = (if (state.answerResult !is AnswerResult.UNCHECKED && state.currentQuestion is TrueFalseQuestion) (state.currentQuestion as TrueFalseQuestion).explanation else null)
            )
        }
    ) { paddingValues ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues)
                .padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(24.dp)
        ) {
            // Context panel shown at the beginning of each exercise
            val ctxTitle = state.exercise.contextTitle
            val ctxText = state.exercise.contextText
            val youtubeUrl = state.exercise.youtubeUrl
            var showContext by remember { mutableStateOf(true) }

            Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
                // Show YouTube video button if this is a YouTube exercise
                if (!youtubeUrl.isNullOrBlank()) {
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.spacedBy(8.dp),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        AppButton(
                            onClick = {
                                // Navigate back to YouTube browser with the saved URL
                                val youtubeUrl = state.exercise.youtubeUrl
                                val sourceLang = state.exercise.sourceLanguage
                                val targetLang = state.exercise.targetLanguage

                                if (youtubeUrl.isNotBlank()) {
                                    exerciseViewModel.restartYouTubeExercise(
                                        youtubeUrl = youtubeUrl,
                                        sourceLanguage = sourceLang,
                                        targetLanguage = targetLang
                                    )
                                    @Suppress("HardCodedStringLiteral")
                                    navController.navigate("youtube_exercise")
                                }
                            },
                            modifier = Modifier.weight(1f)
                        ) {
                            androidx.compose.material3.Icon(
                                imageVector = AppIcons.Play,
                                contentDescription = null,
                                modifier = Modifier.padding(end = 8.dp)
                            )
                            Text(stringResource(R.string.text_watch_video_again))
                        }
                    }
                }

                // Show context if available
                if (!ctxText.isNullOrBlank()) {
                    Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
                        Text(text = ctxTitle?.ifBlank { stringResource(R.string.label_context) } ?: stringResource(R.string.label_context), style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold)
                        AppButton(onClick = { showContext = !showContext }) {
                            Text(if (showContext) stringResource(R.string.hide_context) else stringResource(R.string.show_context))
                        }
                    }
                    if (showContext) {
                        Surface(tonalElevation = 1.dp, shape = RoundedCornerShape(8.dp)) {
                            Text(text = ctxText, modifier = Modifier.padding(12.dp), style = MaterialTheme.typography.bodyMedium)
                        }
                    }
                }
            }
            Text(
                text = stringResource(
                    R.string.text_question_of,
                    state.currentQuestionIndex + 1,
                    state.questions.size
                ),
                style = MaterialTheme.typography.bodyMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
            val headerText = when (state.currentQuestion) {
                is ListeningComprehensionQuestion -> stringResource(id = R.string.type_what_you_hear)
                is WordOrderQuestion -> stringResource(id = R.string.tap_the_words_below_to_form_the_sentence)
                else -> state.currentQuestion.name
            }
            Text(
                text = headerText,
                style = MaterialTheme.typography.headlineMedium,
                fontWeight = FontWeight.Bold
            )

            // Main router for displaying the correct question UI
            when (val question = state.currentQuestion) {
                is TrueFalseQuestion -> TrueFalseQuestionUi(
                    selectedAnswer = state.selectedAnswer as? Boolean,
                    onAnswerSelect = { onAnswerSelect(it) },
                    isLocked = state.answerResult !is AnswerResult.UNCHECKED
                )
                is MultipleChoiceQuestion -> MultipleChoiceQuestionUi(
                    question = question,
                    selectedAnswerIndex = state.selectedAnswer as? Int,
                    onAnswerSelect = { onAnswerSelect(it) },
                    isLocked = state.answerResult !is AnswerResult.UNCHECKED
                )
                is FillInTheBlankQuestion -> FillInTheBlankQuestionUi(
                    question = question,
                    selectedAnswer = state.selectedAnswer as? String ?: "",
                    onAnswerSelect = { onAnswerSelect(it) },
                    isLocked = state.answerResult !is AnswerResult.UNCHECKED
                )
                is WordOrderQuestion -> WordOrderQuestionUi(
                    question = question,
                    selectedAnswer = (state.selectedAnswer as? List<*>)?.filterIsInstance<String>()
                        ?: emptyList(),
                    onAnswerSelect = { onAnswerSelect(it) },
                    isLocked = state.answerResult !is AnswerResult.UNCHECKED
                )
                is MatchingPairsQuestion -> MatchingPairsQuestionUi(
                    question = question,
                    selectedAnswer = (state.selectedAnswer as? Map<*, *>)?.mapNotNull { (k, v) -> (k as? String)?.let { key -> (v as? String)?.let { value -> key to value } } }
                        ?.toMap() ?: emptyMap(),
                    onAnswerSelect = { onAnswerSelect(it) },
                    isLocked = state.answerResult !is AnswerResult.UNCHECKED
                )
                is ListeningComprehensionQuestion -> ListeningComprehensionQuestionUi(
                    question = question,
                    selectedAnswer = state.selectedAnswer as? String ?: "",
                    onAnswerSelect = { onAnswerSelect(it) },
                    isLocked = state.answerResult !is AnswerResult.UNCHECKED
                )
                is CategorizationQuestion -> CategorizationQuestionUi(
                    question = question,
                    selectedAnswer = (state.selectedAnswer as? Map<*, *>)?.mapNotNull { (k, v) -> (k as? String)?.let { key -> (v as? String)?.let { value -> key to value } } }
                        ?.toMap() ?: emptyMap(),
                    onAnswerSelect = { onAnswerSelect(it) },
                    isLocked = state.answerResult !is AnswerResult.UNCHECKED
                )
                is VocabularyTestQuestion -> VocabularyTestQuestionUi(
                    question = question,
                    selectedAnswer = state.selectedAnswer as? String ?: "",
                    onAnswerSelect = { onAnswerSelect(it) },
                    isLocked = state.answerResult !is AnswerResult.UNCHECKED
                )
            }
        }
    }
}

@Composable
fun TrueFalseQuestionUi(selectedAnswer: Boolean?, onAnswerSelect: (Boolean) -> Unit, isLocked: Boolean) {
    Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
        AnswerButton(
            text = stringResource(R.string.text_true),
            isSelected = selectedAnswer == true,
            onClick = { onAnswerSelect(true) },
            enabled = !isLocked
        )
        AnswerButton(
            text = stringResource(R.string.text_false),
            isSelected = selectedAnswer == false,
            onClick = { onAnswerSelect(false) },
            enabled = !isLocked
        )
    }
}

@Composable
fun MultipleChoiceQuestionUi(
    question: MultipleChoiceQuestion,
    selectedAnswerIndex: Int?,
    onAnswerSelect: (Int) -> Unit,
    isLocked: Boolean
) {
    Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
        question.options.forEachIndexed { index, text ->
            AnswerButton(
                text = text,
                isSelected = selectedAnswerIndex == index,
                onClick = { onAnswerSelect(index) },
                enabled = !isLocked
            )
        }
    }
}

@Composable
fun AnswerButton(text: String, isSelected: Boolean, onClick: () -> Unit, enabled: Boolean) {
    AppButton(
        onClick = onClick,
        modifier = Modifier
            .fillMaxWidth()
            .defaultMinSize(minHeight = 52.dp),
        enabled = enabled,
        shape = RoundedCornerShape(12.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, fontSize = 16.sp, fontWeight = FontWeight.SemiBold)
    }
}

@Composable
fun BottomBar(answerResult: AnswerResult, onCheckClick: () -> Unit, onContinueClick: () -> Unit, isCheckEnabled: Boolean, secondaryText: String? = null) {
    val isResultVisible = answerResult !is AnswerResult.UNCHECKED

    Box(contentAlignment = Alignment.BottomCenter) {
        if (!isResultVisible) {
            Surface(shadowElevation = ComponentDefaults.DefaultElevation) {
                AppButton(
                    onClick = onCheckClick,
                    enabled = isCheckEnabled,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp)
                        .height(50.dp)
                ) {
                    Text(stringResource(R.string.text_check), fontWeight = FontWeight.Bold)
                }
            }
        }

        // Animated Correct/Incorrect Result View
        AnimatedVisibility(
            visible = isResultVisible,
            enter = slideInVertically(initialOffsetY = { it }, animationSpec = tween(300)),
            exit = slideOutVertically(targetOffsetY = { it }, animationSpec = tween(300))
        ) {
            val backgroundColor = if (answerResult is AnswerResult.CORRECT) MaterialTheme.semanticColors.successContainer else MaterialTheme.colorScheme.errorContainer
            val contentColor = if (answerResult is AnswerResult.CORRECT) MaterialTheme.semanticColors.onSuccessContainer else MaterialTheme.colorScheme.onErrorContainer

            Surface(
                color = backgroundColor,
                modifier = Modifier.fillMaxWidth()
            ) {
                Row(
                    modifier = Modifier
                        .padding(horizontal = 24.dp, vertical = 16.dp)
                        .defaultMinSize(minHeight = 80.dp),
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.SpaceBetween
                ) {
                    Column(modifier = Modifier.weight(1f)) {
                        Text(
                            text = if (answerResult is AnswerResult.CORRECT) stringResource(R.string.text_correct_em) else stringResource(
                                R.string.text_incorrect_em
                            ),
                            color = contentColor,
                            style = MaterialTheme.typography.headlineSmall,
                            fontWeight = FontWeight.Bold
                        )
                        if (answerResult is AnswerResult.INCORRECT) {
                            Text(
                                text = answerResult.feedback,
                                color = contentColor,
                                style = MaterialTheme.typography.bodyMedium,
                                fontWeight = FontWeight.SemiBold
                            )
                        } else if (!secondaryText.isNullOrBlank()) {
                            Text(
                                text = secondaryText,
                                color = contentColor,
                                style = MaterialTheme.typography.bodyMedium,
                                fontWeight = FontWeight.SemiBold
                            )
                        }
                    }
                    if (answerResult is AnswerResult.CORRECT) {
                        eu.gaudian.translator.view.composable.CorrectButton(
                            onClick = onContinueClick,
                            text = stringResource(R.string.label_continue)
                        )
                    } else {
                        eu.gaudian.translator.view.composable.WrongButton(
                            onClick = onContinueClick,
                            text = stringResource(R.string.label_continue)
                        )
                    }
                }
            }
        }
    }
}