@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.viewmodel

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import eu.gaudian.translator.model.LanguageModel
import eu.gaudian.translator.model.TranslationHistoryItem
import eu.gaudian.translator.model.repository.ApiRepository
import eu.gaudian.translator.model.repository.DataStoreKeys
import eu.gaudian.translator.model.repository.LanguageRepository
import eu.gaudian.translator.model.repository.dataStore
import eu.gaudian.translator.model.repository.loadObjectList
import eu.gaudian.translator.model.repository.saveObjectList
import eu.gaudian.translator.utils.Log
import eu.gaudian.translator.utils.StatusMessageService
import eu.gaudian.translator.utils.TextToSpeechHelper
import eu.gaudian.translator.utils.TranslationService
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class TranslationViewModel @Inject constructor(
    application: Application,
    private val translationService: TranslationService,
    private val apiRepository: ApiRepository,
    val languageRepository: LanguageRepository
) : AndroidViewModel(application) {

    private val statusMessageService = StatusMessageService


    // For back/forward navigation of history in the UI (like editors)
    private val _historyCursor = MutableStateFlow(-1)

    private val _canGoBack = MutableStateFlow(false)
    val canGoBack: StateFlow<Boolean> get() = _canGoBack

    private val _canGoForward = MutableStateFlow(false)
    val canGoForward: StateFlow<Boolean> get() = _canGoForward

    val historyCursor: StateFlow<Int> get() = _historyCursor

    private val _inputText = MutableStateFlow("")
    val inputText: StateFlow<String> get() = _inputText

    private val _translatedText = MutableStateFlow<String?>(null)
    val translatedText: StateFlow<String?> get() = _translatedText

    private val _translatedVocabulary = MutableStateFlow<String?>(null)
    val translatedVocabulary: StateFlow<String?> get() = _translatedVocabulary

    private val _translationHistory = MutableStateFlow<MutableList<TranslationHistoryItem>>(mutableListOf())
    val translationHistory: StateFlow<MutableList<TranslationHistoryItem>> get() = _translationHistory

    // Explanation support
    private val _showExplanation = MutableStateFlow(false)
    val showExplanation: StateFlow<Boolean> get() = _showExplanation

    private val _explanationText = MutableStateFlow<String?>(null)
    val explanationText: StateFlow<String?> get() = _explanationText

    private val _selectedTranslationModel = MutableStateFlow<LanguageModel?>(null)
    val selectedTranslationModel: StateFlow<LanguageModel?> get() = _selectedTranslationModel

    private val _isTranslating = MutableStateFlow(false)
    val isTranslating: StateFlow<Boolean> get() = _isTranslating

    init {
        viewModelScope.launch {
            apiRepository.getTranslationModel().collect { model ->
                _selectedTranslationModel.value = model
            }
        }
        loadTranslationHistory()
    }

    fun setInputText(text: String) {
        _inputText.value = text
    }

    fun clearInputAndOutputText() {
        _inputText.value = ""
        _translatedText.value = ""
        _explanationText.value = null

    }

    fun setShowExplanation(show: Boolean) {
        _showExplanation.value = show
        if (!show) {
            _explanationText.value = null
        } else {
            // Try to compute explanation if we already have a translation and input
            val source = _inputText.value
            val translated = _translatedText.value
            if (source.isNotBlank() && !translated.isNullOrBlank()) {
                viewModelScope.launch {
                    translationService.explainTranslation(source, translated)
                        .onSuccess { _explanationText.value = it }
                        .onFailure { Log.e("TranslationViewModel", "Explanation failed: ${it.message}") }
                }
            }
        }
    }

    fun toggleExplanation() {
        setShowExplanation(!_showExplanation.value)
    }

    fun translateSentence(sentence: String) {
        val sentenceToTranslate = sentence.ifEmpty { _inputText.value }
        if (sentenceToTranslate.isBlank()) {
            statusMessageService.showSimpleMessage("Please enter a sentence to translate.")
            return
        }

        if (selectedTranslationModel.value == null) {
            Log.e("TranslationViewModel", "Cannot translate because no model is selected.")
            statusMessageService.showSimpleMessage("Cannot translate because no model is selected.")
            return
        }



        viewModelScope.launch {
            _isTranslating.value = true
            _explanationText.value = null

            translationService.translateSentence(sentenceToTranslate)
                .onSuccess { historyItem ->
                    _translatedText.value = historyItem.text
                    // We copy the item to ensure we capture the specific inputs used right now
                    addToTranslationHistory(
                        historyItem.copy(
                            sourceText = sentenceToTranslate,
                            sourceLanguageCode = languageRepository.loadSelectedSourceLanguage().first()?.nameResId,
                            targetLanguageCode = languageRepository.loadSelectedTargetLanguage().first()?.nameResId
                        )
                    )
                    Log.d("TranslationViewModel", "Translation successful: $historyItem")

                    if (_showExplanation.value) {
                        translationService.explainTranslation(sentenceToTranslate, historyItem.text)
                            .onSuccess { explanation ->
                                _explanationText.value = explanation
                            }
                            .onFailure { exception ->
                                Log.e("TranslationViewModel", "Explanation failed: ${exception.message}")
                            }
                    }
                }
                .onFailure { exception ->
                    Log.e("TranslationViewModel", "Translation failed: ${exception.message}")
                    statusMessageService.showErrorMessage("Translation failed: ${exception.message}")
                }

            _isTranslating.value = false
        }
    }

    fun translateVocabulary(word: String) {
        viewModelScope.launch {
            translationService.translateVocabulary(word)
                .onSuccess { historyItem ->
                    _translatedVocabulary.value = historyItem.text
                    Log.d("TranslationViewModel", "Translation successful: $historyItem")
                }
                .onFailure { exception ->
                    Log.e("TranslationViewModel", "Translation failed: ${exception.message}")
                }
        }
    }

    suspend fun getMultipleTranslations(sentence: String, contextPhrase: String? = null): Result<List<String>> {
        return translationService.getMultipleSynonyms(sentence, contextPhrase)
            .also { result ->
                result
                    .onSuccess { translations ->
                        Log.d("TranslationViewModel", "Multiple translations successful: $translations")
                    }
                    .onFailure { exception ->
                        Log.e("TranslationViewModel", "Multiple translations failed: ${exception.message}")
                    }
            }
    }

    fun applyAlternative(originalWord: String, chosenAlternative: String) {
        val source = _inputText.value
        val current = _translatedText.value
        if (source.isBlank() || current.isNullOrBlank()) return

        viewModelScope.launch {
            _isTranslating.value = true
            translationService.rephraseWithAlternative(source, current, originalWord, chosenAlternative)
                .onSuccess { updated ->
                    _translatedText.value = updated
                    if (_showExplanation.value) {
                        translationService.explainTranslation(source, updated)
                            .onSuccess { _explanationText.value = it }
                            .onFailure { Log.e("TranslationViewModel", "Explanation failed: ${it.message}") }
                    }
                }
                .onFailure { ex ->
                    Log.e("TranslationViewModel", "Rephrase with alternative failed: ${ex.message}")
                }
            _isTranslating.value = false
        }
    }

    private fun addToTranslationHistory(item: TranslationHistoryItem) {
        viewModelScope.launch {
            val currentHistory = _translationHistory.value
            val newHistory = currentHistory.toMutableList()
            val lang = languageRepository.loadSelectedTargetLanguage().first()
            val playable = TextToSpeechHelper.isPlayable(getApplication(), lang)

            Log.d("TranslationViewModel", "Adding item to history: $item, item is playable is $playable")

            // Create a new item with updated timestamp and playable status
            // Note: We do NOT pass translatedText here as it was removed from the data class
            val newItem = item.copy(
                sourceText = item.sourceText.ifEmpty { _inputText.value },
                playable = playable,
                timestamp = System.currentTimeMillis()
            )

            newHistory.add(0, newItem)
            _translationHistory.value = newHistory
            _historyCursor.value = if (newHistory.isNotEmpty()) 0 else -1
            updateBackForwardState()
            saveTranslationHistory()
        }
    }

    fun deleteTranslationHistoryItem(item: TranslationHistoryItem) {
        viewModelScope.launch {
            val currentHistory = _translationHistory.value
            val newHistory = currentHistory.toMutableList()
            // We compare IDs or references. Since data class equals works on fields, this should work.
            // If you added an ID field, use that for safer removal.
            if (newHistory.remove(item)) {
                _translationHistory.value = newHistory
                val size = newHistory.size
                _historyCursor.value = if (size == 0) -1 else _historyCursor.value.coerceAtMost(size - 1)
                updateBackForwardState()
                saveTranslationHistory()
                Log.d("TranslationViewModel", "Item deleted from history: $item")
            } else {
                Log.w("TranslationViewModel", "Item not found in history: $item")
            }
        }
    }

    private fun saveTranslationHistory() {
        viewModelScope.launch {
            val history = _translationHistory.value
            getApplication<Application>().dataStore.saveObjectList(DataStoreKeys.TRANSLATION_HISTORY_KEY, history)
        }
    }

    fun clearTranslationHistory() {
        viewModelScope.launch {
            _translationHistory.value = mutableListOf()
            _historyCursor.value = -1
            _inputText.value = ""
            _translatedText.value = ""
            _explanationText.value = null
            updateBackForwardState()
            saveTranslationHistory()
        }
    }

    private fun loadTranslationHistory() {
        viewModelScope.launch {
            val history = getApplication<Application>().dataStore.loadObjectList<TranslationHistoryItem>(DataStoreKeys.TRANSLATION_HISTORY_KEY).first()
            _translationHistory.value = history.toMutableList()
            // Start with a fresh/empty screen; do not preload the last translation
            _historyCursor.value = -1
            _explanationText.value = null
            updateBackForwardState()
        }
    }

    private fun updateBackForwardState() {
        val size = _translationHistory.value.size
        val cursor = _historyCursor.value
        // Allow going back from the "fresh" state (cursor == -1) to the most recent history item
        _canGoBack.value = size > 0 && (cursor == -1 || (cursor < size - 1 && cursor >= 0))
        _canGoForward.value = size > 0 && cursor > 0
    }

    fun goBackInHistory() {
        val size = _translationHistory.value.size
        if (size == 0) return
        val newCursor = (_historyCursor.value + 1).coerceAtMost(size - 1)
        if (newCursor != _historyCursor.value) {
            _historyCursor.value = newCursor
            val item = _translationHistory.value[newCursor]
            applyHistoryItem(item)
        }
    }

    fun goForwardInHistory() {
        val size = _translationHistory.value.size
        if (size == 0) return
        val newCursor = (_historyCursor.value - 1).coerceAtLeast(0)
        if (newCursor != _historyCursor.value) {
            _historyCursor.value = newCursor
            val item = _translationHistory.value[newCursor]
            applyHistoryItem(item)
        }
    }

    fun applyHistoryItem(item: TranslationHistoryItem) {
        // Find the index of this item to set the cursor correctly
        val index = _translationHistory.value.indexOfFirst { it.id == item.id }

        _inputText.value = item.sourceText
        _translatedText.value = item.text
        _explanationText.value = null

        if (index >= 0) {
            _historyCursor.value = index
        }
        updateBackForwardState()
    }
}
