package com.example.lexilearn.ui.views.pQuiz

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
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.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
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.geometry.Rect
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.example.lexilearn.data.model.MaterialDataModel
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.VolumeUp
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.constraintlayout.compose.ConstraintLayout
import com.example.lexilearn.R
import com.example.lexilearn.data.model.QuestionType
import com.example.lexilearn.ui.components.CardQuiz
import com.example.lexilearn.ui.components.DraggableAnswerCard
import com.example.lexilearn.ui.components.FirebaseImage
import com.example.lexilearn.ui.components.GradientQuiz
import com.example.lexilearn.ui.components.MyShadowCard
import com.example.lexilearn.ui.theme.ctextGray
import com.example.lexilearn.ui.theme.ctextWhite
import com.google.accompanist.flowlayout.FlowRow
import com.google.accompanist.flowlayout.MainAxisAlignment
import kotlin.math.roundToInt

@Composable
fun QuizScreen(
    navController: NavController,
    material: MaterialDataModel,
    quizViewModel: QuizViewModel = viewModel()
) {
    val question by quizViewModel.currentQuestion.collectAsState()
    val isButtonVisible by quizViewModel.isButtonVisible
    val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState()
    val isTTSInitialized = quizViewModel.isTTSInitialized.observeAsState(false)
    val snackbarMessage by quizViewModel.snackbarMessage.collectAsState()
    val snackbarHostState = remember { SnackbarHostState() }


    LaunchedEffect(Unit) {
        quizViewModel.loadRandomQuestion(material)
    }
    LaunchedEffect(snackbarMessage) {
        snackbarMessage?.let { message ->
            snackbarHostState.showSnackbar(message)
            quizViewModel.onSnackbarShown()
        }
    }

    var rectColumnAnswer by remember { mutableStateOf(Rect.Zero) }

    val cardSize = remember {
        mutableStateMapOf<Int, Dp>()
    }

    val maxSize = 120.dp

    val minSize = 70.dp
    val dataQuiz by quizViewModel.questionShuffled.collectAsState()
    val listAnswer by quizViewModel.shuffledAnswerLetters.collectAsState()

    val quizXOffset = remember {
        mutableStateMapOf<Int, Float>()
    }

    val quizYOffset = remember {
        mutableStateMapOf<Int, Float>()
    }

    val boxRectDragable = remember {
        mutableStateMapOf<Int, Rect>()
    }

    val boxRectQuiz = remember {
        mutableStateMapOf<Int, Rect>()
    }

    val answerXOffset = remember {
        mutableStateMapOf<Int, Float>()
    }

    val answerYOffset = remember {
        mutableStateMapOf<Int, Float>()
    }

    val boxRectAnswer = remember {
        mutableStateMapOf<Int, Rect>()
    }

    Scaffold(
        snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
    ){innerPadding->
        Surface(modifier = Modifier.fillMaxSize().padding(innerPadding)) {
            GradientQuiz(
                navController = navController,
                headerText = stringResource(id = R.string.spelltitle),
                modifier = Modifier.fillMaxSize()
            ) {
                ConstraintLayout {
                    val buttonRef = createRef()
                    Column(
                        modifier = Modifier.fillMaxSize(),
                        horizontalAlignment = Alignment.CenterHorizontally,
                    ) {
                        Row(
                            modifier = Modifier.fillMaxWidth(),
                            horizontalArrangement = Arrangement.End,
                        ) {
                            Text(
                                "",
                                modifier = Modifier.padding(22.dp),
                                fontWeight = FontWeight.SemiBold,
                                fontSize = 18.sp,
                                color = ctextWhite
                            )
                        }
                        MyShadowCard(
                            modifier = Modifier
                                .padding(12.dp)
                                .fillMaxWidth()
                        ) {
                            Column(
                                modifier = Modifier.fillMaxWidth(),
                                horizontalAlignment = Alignment.CenterHorizontally
                            ) {
                                Spacer(modifier = Modifier.height(12.dp))
                                if (question != null) {
                                    if (question?.questionType == QuestionType.IMAGE) {
                                        FirebaseImage(
                                            path = question!!.question,
                                            contentScale = ContentScale.Crop,
                                            modifier = Modifier.size(160.dp)
                                        )
                                    } else if (question?.questionType == QuestionType.TEXT) {
                                        Text(
                                            text = question!!.question,
                                            fontSize = 20.sp,
                                            fontWeight = FontWeight.Bold,
                                            modifier = Modifier.padding(12.dp)
                                        )
                                    } else if (question?.questionType == QuestionType.AUDIO) {
                                        IconButton(
                                            onClick = {
                                                quizViewModel.speakLetter(question!!.question)
                                            },
                                        ) {
                                            Icon(
                                                imageVector = Icons.Filled.VolumeUp,
                                                contentDescription = "Speaker Icon",
                                                tint = Color.Black,
                                                modifier = Modifier.size(200.dp)
                                            )
                                        }
                                    }
                                }
                                Spacer(modifier = Modifier.height(12.dp))
                                FlowRow(
                                    mainAxisSpacing = 8.dp,
                                    crossAxisSpacing = 8.dp,
                                    mainAxisAlignment = MainAxisAlignment.Center,
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .padding(12.dp)

                                ) {
                                    dataQuiz.forEach { dt ->
                                        val id = dt.id
                                        if (!boxRectDragable.containsKey(id))
                                            boxRectDragable[id] = Rect.Zero
                                        if (!boxRectQuiz.containsKey(id))
                                            boxRectQuiz[id] = Rect.Zero
                                        if (!quizXOffset.containsKey(id))
                                            quizXOffset[id] = 0f
                                        if (!quizYOffset.containsKey(id))
                                            quizYOffset[id] = 0f

                                        CardQuiz(
                                            modifier = Modifier
                                                .padding(vertical = 10.dp)
                                                .size(minSize)
                                                .onGloballyPositioned { coordinates ->
                                                    if (dt.type)
                                                        boxRectQuiz[id] = coordinates.boundsInWindow()
                                                }
                                        ) {
                                            if (dt.type) {
                                                Text(
                                                    text = dt.data,
                                                    color = ctextWhite,
                                                    fontWeight = FontWeight.Bold,
                                                    textAlign = TextAlign.Center,
                                                    modifier = Modifier.fillMaxWidth()
                                                )
                                                if (dt.showCard) {
                                                    DraggableAnswerCard(
                                                        item = dt.data,
                                                        modifier = Modifier
                                                            .offset {
                                                                val xOffset = quizXOffset[id] ?: 0f
                                                                val yOffset = quizYOffset[id] ?: 0f
                                                                IntOffset(
                                                                    xOffset.roundToInt(),
                                                                    yOffset.roundToInt()
                                                                )
                                                            }
                                                            .onGloballyPositioned {
                                                                boxRectDragable[id] =
                                                                    it.boundsInWindow()
                                                            }
                                                            .fillMaxSize()
                                                            .pointerInput(Unit) {
                                                                detectDragGestures(
                                                                    onDrag = { change, dragAmount ->
                                                                        change.consume()
                                                                        quizXOffset[id] =
                                                                            quizXOffset[id]!! + dragAmount.x
                                                                        quizYOffset[id] =
                                                                            quizYOffset[id]!! + dragAmount.y
                                                                    },
                                                                    onDragEnd = {
                                                                        var checkNull = false
                                                                        for ((ind, entry) in boxRectQuiz.entries.withIndex()) {
                                                                            val (key, rect) = entry
                                                                            if (key == id)
                                                                                continue

                                                                            if (dataQuiz[ind].hasContent)
                                                                                continue

                                                                            if (boxRectDragable[id]!!.overlaps(
                                                                                    rect
                                                                                )
                                                                            ) {
                                                                                quizViewModel.updateQuestionShuffled(
                                                                                    ind,
                                                                                    dt
                                                                                )
                                                                                dt.apply {
                                                                                    hasContent = false
                                                                                    showCard = false
                                                                                    data = "?"
                                                                                }
                                                                                checkNull = true
                                                                                quizXOffset[id] = 0f
                                                                                quizYOffset[id] = 0f
                                                                                break
                                                                            }
                                                                        }
                                                                        if (boxRectDragable[id]!!.overlaps(
                                                                                rectColumnAnswer
                                                                            )
                                                                        ) {
                                                                            val emDt = dt.emp
                                                                            if (emDt != null) {
                                                                                dt.apply {
                                                                                    hasContent = false
                                                                                    showCard = false
                                                                                    data = "?"
                                                                                }
                                                                                checkNull = true
                                                                                cardSize[emDt] = maxSize
                                                                                quizXOffset[id] = 0f
                                                                                quizYOffset[id] = 0f
                                                                                dt.data = "?"
                                                                            }
                                                                        }
                                                                        if (!checkNull) {
                                                                            quizXOffset[id] = 0f
                                                                            quizYOffset[id] = 0f
                                                                        }
                                                                    }
                                                                )
                                                            }
                                                    )
                                                }
                                            } else {
                                                Box(modifier = Modifier) {
                                                    Text(
                                                        text = dt.data,
                                                        color = ctextWhite,
                                                        fontSize = 20.sp,
                                                        fontWeight = FontWeight.Bold,
                                                        textAlign = TextAlign.Center,
                                                    )
                                                }
                                            }
                                        }
                                    }
                                }
                                Spacer(modifier = Modifier.height(12.dp))
                            }
                        }
                        Spacer(modifier = Modifier.height(12.dp))
                        Spacer(
                            modifier = Modifier
                                .fillMaxWidth()
                                .height(1.dp)
                                .background(ctextGray)
                        )
                        Spacer(modifier = Modifier.height(12.dp))
                        Column(
                            modifier = Modifier
                                .fillMaxWidth()
                                .heightIn(min = 300.dp)
                                .onGloballyPositioned {
                                    rectColumnAnswer = it.boundsInWindow()
                                },
                        ) {
                            listAnswer.chunked(3).forEach { rowItems ->
                                Row(
                                    modifier = Modifier.fillMaxWidth(),
                                    horizontalArrangement = Arrangement.Center
                                ) {
                                    rowItems.forEach { item ->
                                        val id = item.id
                                        if (!cardSize.containsKey(id))
                                            cardSize[id] = maxSize
                                        if (!boxRectAnswer.containsKey(id))
                                            boxRectAnswer[id] = Rect.Zero
                                        if (!answerXOffset.containsKey(id))
                                            answerXOffset[id] = 0f
                                        if (!answerYOffset.containsKey(id))
                                            answerYOffset[id] = 0f
                                        DraggableAnswerCard(
                                            item = item.data,
                                            modifier = Modifier
                                                .padding(4.dp)
                                                .size(cardSize[id]!!)
                                                .offset {
                                                    IntOffset(
                                                        answerXOffset[id]!!.roundToInt(),
                                                        answerYOffset[id]!!.roundToInt()
                                                    )
                                                }
                                                .onGloballyPositioned { coordinates ->
                                                    boxRectAnswer[id] = coordinates.boundsInWindow()
                                                }
                                                .pointerInput(Unit) {
                                                    detectDragGestures(
                                                        onDrag = { change, dragAmount ->
                                                            change.consume()
                                                            answerXOffset[id] =
                                                                answerXOffset[id]!! + dragAmount.x
                                                            answerYOffset[id] =
                                                                answerYOffset[id]!! + dragAmount.y
                                                            cardSize[id] = minSize
                                                        },
                                                        onDragEnd = {
                                                            var checkNull = false
                                                            for ((ind, entry) in boxRectQuiz.entries.withIndex()) {
                                                                val (_, rect) = entry
                                                                if (dataQuiz[ind].hasContent)
                                                                    continue

                                                                if (boxRectAnswer[id]!!.overlaps(
                                                                        rect
                                                                    )
                                                                ) {
                                                                    cardSize[id] = minSize
                                                                    quizViewModel.updateQuestionShuffled(
                                                                        ind,
                                                                        dataQuiz[ind].copy(
                                                                            data = item.data,
                                                                            showCard = true,
                                                                            emp = id,
                                                                            hasContent = true
                                                                        )
                                                                    )
                                                                    checkNull = true
                                                                    cardSize[id] = 0.dp
                                                                    answerXOffset[id] = 0f
                                                                    answerYOffset[id] = 0f
                                                                    break
                                                                }
                                                            }
                                                            if (!checkNull) {
                                                                cardSize[id] = maxSize
                                                                answerXOffset[id] = 0f
                                                                answerYOffset[id] = 0f
                                                            }
                                                        }
                                                    )
                                                }
                                        )
                                    }
                                }
                            }
                        }
                        Spacer(modifier = Modifier.height(12.dp))
                    }

                }
            }
        }

    }
}