@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.viewmodel

import android.app.Application
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import eu.gaudian.translator.model.Language
import eu.gaudian.translator.utils.CorrectionService
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class CorrectionViewModel @Inject constructor(
    application: Application,
    private val correctionService: CorrectionService
) : AndroidViewModel(application) {

    enum class Tone { NONE, FORMAL, CASUAL, COLLOQUIAL, POLITE, PROFESSIONAL, FRIENDLY, ACADEMIC, CREATIVE }

    private val _textFieldValue = MutableStateFlow(TextFieldValue(""))
    val textFieldValue = _textFieldValue.asStateFlow()

    private val _explanation = MutableStateFlow<String?>(null)
    val explanation = _explanation.asStateFlow()

    private val _correctedText = MutableStateFlow<String?>(null)
    val correctedText = _correctedText.asStateFlow()

    private val _isLoading = MutableStateFlow(false)
    val isLoading = _isLoading.asStateFlow()

    private val _error = MutableStateFlow<String?>(null)
    val error = _error.asStateFlow()

    private val _grammarOnly = MutableStateFlow(true)
    val grammarOnly = _grammarOnly.asStateFlow()

    private val _tone = MutableStateFlow(Tone.NONE)
    val tone = _tone.asStateFlow()

    fun setCorrectToneEnabled(enabled: Boolean) {
        _grammarOnly.value = !enabled
        if (!enabled) {
            _tone.value = Tone.NONE
        }
    }

    fun setTone(newTone: Tone) {
        _tone.value = newTone
        if (newTone != Tone.NONE) _grammarOnly.value = false
    }

    fun onInputTextChanged(newValue: TextFieldValue) {
        _textFieldValue.value = newValue
        if (_error.value != null) _error.value = null
    }

    fun performCorrection(language: Language, color : Color) {
        val originalText = _textFieldValue.value.text
        if (originalText.isBlank()) return

        viewModelScope.launch {
            _isLoading.value = true
            _explanation.value = null
            _error.value = null

            val grammarOnly = _grammarOnly.value
            val tone = _tone.value.name.lowercase()

            correctionService.correctText(originalText, language, grammarOnly, if (_tone.value == Tone.NONE) null else tone)
                .onSuccess { response ->
                    val annotatedString = createDiffAnnotatedString(originalText, response.correctedText, color)
                    _textFieldValue.value = TextFieldValue(annotatedString)
                    _explanation.value = response.explanation
                    _correctedText.value = response.correctedText
                }
                .onFailure { exception ->
                    // This block executes only if the result is a failure
                    _error.value = "Correction failed: ${exception.message ?: "Unknown error"}"
                }

            // The loading state is updated once at the end, regardless of outcome
            _isLoading.value = false
        }
    }

    // Clears only the text and related outputs, preserving user-selected options
    fun clearText() {
        _textFieldValue.value = TextFieldValue("")
        _explanation.value = null
        _correctedText.value = null
        _error.value = null
        // Do not touch _grammarOnly or _tone here
    }

    private fun createDiffAnnotatedString(original: String, corrected: String, color : Color): AnnotatedString {
        if (original.trim() == corrected.trim()) {
            return buildAnnotatedString {
                withStyle(style = SpanStyle(background = color, fontWeight = FontWeight.Bold)) {
                    append(corrected)
                }
            }
        } else {
            return buildAnnotatedString {
                val originalWords = original.split(' ')
                val correctedWordsSet = corrected.split(' ').toSet()
                originalWords.forEachIndexed { index, word ->
                    if (word.isNotEmpty()) {
                        if (word in correctedWordsSet) {
                            append(word)
                        } else {
                            withStyle(style = SpanStyle(color = Color.Gray, textDecoration = TextDecoration.LineThrough)) {
                                append(word)
                            }
                        }
                        if (index < originalWords.lastIndex) {
                            append(" ")
                        }
                    }
                }
                append("\n\n")
                withStyle(style = SpanStyle(background = color, fontWeight = FontWeight.Bold)) {
                    append(corrected)
                }
            }
        }
    }
}
