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

import android.app.Application
import android.speech.tts.TextToSpeech
import android.util.Log
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.example.lexilearn.data.model.MaterialDataModel
import com.example.lexilearn.data.model.QuizQuestion
import com.example.lexilearn.data.model.QuizState
import com.example.lexilearn.data.repository.QuizRepository
import com.example.lexilearn.domain.models.ModelAnswerRead
import com.example.lexilearn.domain.models.ModelSpell
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import java.util.Locale
import kotlin.random.Random

class QuizViewModel(application: Application) : AndroidViewModel(application),
    TextToSpeech.OnInitListener {
    private val quizRepository = QuizRepository()

    private var materialList: List<MaterialDataModel> = emptyList()

    private val _currentQuestion = MutableStateFlow<QuizQuestion?>(null)
    val currentQuestion: StateFlow<QuizQuestion?> = _currentQuestion

    private val _userAnswer = MutableStateFlow<String?>(null)
    val userAnswer: StateFlow<String?> = _userAnswer

    private val _isAnswerCorrect = MutableStateFlow<Boolean?>(null)
    val isAnswerCorrect: StateFlow<Boolean?> = _isAnswerCorrect

    private val _indexQuiz = MutableStateFlow(0)
    val indexQuiz: StateFlow<Int> = _indexQuiz

    // Update indexQuiz saat jawaban benar
    fun incrementIndexQuiz() {
        _indexQuiz.value += 1
    }

    fun loadNewQuestion(material: MaterialDataModel, questionMode: Int, answerMode: Int) {
        _currentQuestion.value = quizRepository.generateQuestion(material, questionMode, answerMode)
    }

    private val _shuffledAnswerLetters = MutableStateFlow<List<ModelAnswerRead>>(emptyList())
    val shuffledAnswerLetters: StateFlow<List<ModelAnswerRead>> = _shuffledAnswerLetters


    private val _questionShuffled = MutableStateFlow<List<ModelSpell>>(emptyList())
    val questionShuffled: StateFlow<List<ModelSpell>> = _questionShuffled

    private val _isButtonVisible = mutableStateOf(false)
    val isButtonVisible: State<Boolean> get() = _isButtonVisible

    fun updateQuestionShuffled(index: Int, newData: ModelSpell) {
        _questionShuffled.value = _questionShuffled.value.mapIndexed { i, item ->
            if (i == index) {
                item.copy(
                    data = newData.data,
                    showCard = true,
                    emp = newData.emp,
                    hasContent = true
                )
            } else {
                item
            }
        }
    }


    fun initMaterialData(material: List<MaterialDataModel>) {
        materialList = material;
    }


    fun randomQuestion() {
        val randomQuestionMode = Random.nextInt(1, 3)

        _currentQuestion.value =
            quizRepository.generateQuestion(materialList[_indexQuiz.value], randomQuestionMode, 2)

        val dataQuest =
            _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
                ModelSpell(
                    id = (_indexQuiz.value * 100) + index + 1,
                    type = true,
                    data = "?",
                    showCard = false
                )
            } ?: emptyList()
        _questionShuffled.value = dataQuest

        val listAnswer =
            _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
                ModelAnswerRead(
                    id = (_indexQuiz.value * 100) + index + 1, // ID unik per pertanyaan
                    data = char.toString()
                )
            } ?: emptyList()
        _shuffledAnswerLetters.value = listAnswer.shuffled()
    }


    private var tts: TextToSpeech? = null
    private val _isTTSInitialized = MutableLiveData(false)
    val isTTSInitialized: LiveData<Boolean> = _isTTSInitialized

    init {
        tts = TextToSpeech(application, this)
        observeData()
    }

    override fun onInit(status: Int) {
        if (status == TextToSpeech.SUCCESS) {
            tts?.language = Locale.ENGLISH
            _isTTSInitialized.value = true
        } else {
            _isTTSInitialized.value = false
        }
    }

    fun speakLetter(letter: String) {
        if (_isTTSInitialized.value == true) {
            tts?.speak(letter, TextToSpeech.QUEUE_FLUSH, null, null)
        }
    }

    fun checkAnswer(answerString: String): Boolean {
        if (answerString == currentQuestion.value?.correctAnswer?.correctWord) {
            return true
        }
        return false
    }

    fun observeData() {
        viewModelScope.launch {
            _questionShuffled.collect { newList ->
                // Lakukan aksi setiap kali data berubah
                var answerString = ""
                newList.forEach { text ->
                    answerString = answerString + text.data
                }
                if (answerString.contains("?") || answerString.isEmpty() || answerString.contains("null")) {
                    _isButtonVisible.value = false
                } else {
                    Log.d("cobaaja", answerString)
                    val checkData = checkAnswer(answerString);
                    if (checkData) {
                        triggerSnackbar("Jawaban Benar")
                        submitAnswer(true)
                        incrementIndexQuiz()
                    } else {
                        submitAnswer(false)
                        triggerSnackbar("Jawaban Salah")
                    }
                    _isButtonVisible.value = true
                }
            }
        }
    }

    private val _snackbarMessage = MutableStateFlow<String?>(null)
    val snackbarMessage: StateFlow<String?> = _snackbarMessage

    fun triggerSnackbar(message: String) {
        _snackbarMessage.value = message
    }

    fun onSnackbarShown() {
        _snackbarMessage.value = null
    }

    override fun onCleared() {
        tts?.stop()
        tts?.shutdown()
        super.onCleared()
    }

    // competition ====================================================================
    private val _quizState = MutableLiveData<QuizState>()
    val quizState: LiveData<QuizState> get() = _quizState

    private val _currentScore = MutableLiveData(0)  // Skor untuk soal saat ini
    val currentScore: LiveData<Int> get() = _currentScore

    private val _totalScore = MutableLiveData(0)  // Total skor sepanjang sesi
    val totalScore: LiveData<Int> get() = _totalScore

    private var questionList = listOf<MaterialDataModel>()
    private var currentQuestionIndex = 0
    private var wrongAttempts = 0
    private var startTime: Long = 0

    // Konstanta untuk scoring
    private val baseScore = 100
    private val safeTime = 5
    private val timePenalty = 3
    private val wrongPenalty = 5
    private val minScore = 50
    private val bonusQuick = 10

    /** 1️⃣ Memulai Kuis **/
    fun startQuiz(materials: List<MaterialDataModel>) {
        if (materials.isNotEmpty()) {
            questionList = materials
            currentQuestionIndex = 0
            _totalScore.value = 0  // Reset skor saat mulai
            _currentScore.value = 0
            wrongAttempts = 0
            startTime = System.currentTimeMillis()
            _quizState.value =
                QuizState.QuestionLoaded(questionList[currentQuestionIndex], _totalScore.value ?: 0)
        } else {
            _quizState.value = QuizState.Error("Tidak ada soal tersedia")
        }
    }

    /** 2️⃣ Dipanggil saat jawaban dikirim **/
    fun submitAnswer(isCorrect: Boolean) {
        val responseTime =
            ((System.currentTimeMillis() - startTime) / 1000).toInt() // Hitung waktu otomatis

        if (isCorrect) {
            val score = calculateScore(responseTime, wrongAttempts)
            _currentScore.value = score
            _totalScore.value = (_totalScore.value ?: 0) + score  // Update total skor
            moveToNextQuestion()
        } else {
            wrongAnswer()
        }
    }

    /** 3️⃣ Dipanggil saat jawaban salah **/
    fun wrongAnswer() {
        wrongAttempts += 1
        _quizState.value = QuizState.AnswerWrong(wrongAttempts)
    }

    /** 4️⃣ Berganti ke soal berikutnya **/
    private fun moveToNextQuestion() {
        if (currentQuestionIndex < questionList.size - 1) {
            currentQuestionIndex++
            wrongAttempts = 0
            startTime = System.currentTimeMillis()
            _quizState.value =
                QuizState.QuestionLoaded(questionList[currentQuestionIndex], _totalScore.value ?: 0)
        } else {
            _quizState.value = QuizState.QuizFinished(_totalScore.value ?: 0)
        }
    }

    /** 🔢 Perhitungan Skor **/
    private fun calculateScore(responseTime: Int, wrongAttempts: Int): Int {
        val penaltyTime = maxOf(0, responseTime - safeTime) * timePenalty
        val penaltyWrong = wrongAttempts * wrongPenalty
        var score = baseScore - penaltyTime - penaltyWrong

        if (responseTime <= 3) {
            score += bonusQuick
        }

        return maxOf(minScore, score)
    }
}