@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.VocabularyCategory
import eu.gaudian.translator.model.repository.VocabularyRepository
import eu.gaudian.translator.utils.Log
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

@HiltViewModel
class CategoryViewModel @Inject constructor(
    application: Application,
    private val repository: VocabularyRepository
) : AndroidViewModel(application) {

    val categories: StateFlow<List<VocabularyCategory>> = repository.getAllCategoriesFlow()
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = emptyList()
        )
    private val _showDeleteCategoryDialog = MutableStateFlow(false)
    val showDeleteCategoryDialog: StateFlow<Boolean> = _showDeleteCategoryDialog.asStateFlow()

    private val _showDeleteItemsDialog = MutableStateFlow(false)
    val showDeleteItemsDialog: StateFlow<Boolean> = _showDeleteItemsDialog.asStateFlow()

    private val _showEditCategoryDialog = MutableStateFlow(false)
    val showEditCategoryDialog: StateFlow<Boolean> = _showEditCategoryDialog.asStateFlow()

    private val _navigateBack = MutableStateFlow(false)

    private val _updateUI = MutableStateFlow(false)

    var categoryToDelete: Int = 0
    var categoryVocabularyItemDelete: Int = 0
    var categoryToEdit: Int = 0

    init {
        viewModelScope.launch {
            repository.initializeRepository()
        }
    }

    fun setNavigateBack(navigate: Boolean) {
        _navigateBack.value = navigate
    }

    fun setUpdateUI(update: Boolean) {
        _updateUI.value = update
        Log.d("CategoryViewModel", "Update UI: $update")
    }

    fun getCategoryById(id: Int): Flow<VocabularyCategory?> {
        return categories.map { categoryList ->
            categoryList.firstOrNull { it.id == id }
        }
    }

    fun createCategory(category: VocabularyCategory) {
        viewModelScope.launch {
            repository.saveCategory(category)
        }
    }

    fun updateCategory(category: VocabularyCategory) {
        viewModelScope.launch {
            repository.saveCategory(category)
            setUpdateUI(true)
        }
    }

    fun deleteCategoryById(id: Int) {
        viewModelScope.launch {
            try {
                repository.deleteCategoryById(id)
                setNavigateBack(true)
            } catch (_: Exception) {

            }
        }
    }

    suspend fun calculateNewDictionaries(): Set<Pair<Int, Int>> {
        val allPairs = getAllPossibleDictionariesInt()
        val existingPairs = categories.value.mapNotNull { category ->
            (category as? eu.gaudian.translator.model.VocabularyFilter)?.languagePairs
        }.distinct()
        return allPairs.filterNot { existingPairs.contains(it) }.toSet()
    }

    suspend fun getAllPossibleDictionariesInt(): Set<Pair<Int, Int>> {
        val context = viewModelScope.coroutineContext
        return withContext(context) {
            repository.calcAvailableDictionaries()
        }
    }

    fun setShowDeleteCategoryDialog(show: Boolean, categoryId: Int) {
        _showDeleteCategoryDialog.value = show
        categoryToDelete = categoryId
    }

    fun setShowDeleteItemsDialog(show: Boolean, categoryId: Int) {
        Log.d("CategoryViewModel", "setShowDeleteItemsDialog: $show, categoryId: $categoryId")
        _showDeleteItemsDialog.value = show
        categoryVocabularyItemDelete = categoryId
    }

    fun setShowEditCategoryDialog(show: Boolean, categoryId: Int) {
        _showEditCategoryDialog.value = show
        categoryToEdit = categoryId
    }
}
