package de.softwareapp_hb.privateqrscanner.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import de.softwareapp_hb.privateqrscanner.AppContainer
import de.softwareapp_hb.privateqrscanner.domain.ScanRecord
import de.softwareapp_hb.privateqrscanner.i18n.AppLocaleCatalog
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

data class AppUiState(
    val historyEnabled: Boolean = false,
    val warningsEnabled: Boolean = true,
    val scanFeedbackEnabled: Boolean = true,
    val useCaseView: UseCaseView = UseCaseView.default,
    val appLanguageTag: String = AppLocaleCatalog.SYSTEM_STORAGE_TAG,
    val history: List<ScanRecord> = emptyList(),
    val searchQuery: String = ""
)

class AppViewModel(
    private val container: AppContainer
) : ViewModel() {

    private data class SettingsState(
        val historyEnabled: Boolean,
        val warningsEnabled: Boolean,
        val scanFeedbackEnabled: Boolean,
        val useCaseView: UseCaseView,
        val appLanguageTag: String
    )

    private val query = MutableStateFlow("")

    private val settingsState = combine(
        container.settingsRepository.historyEnabled,
        container.settingsRepository.warningsEnabled,
        container.settingsRepository.scanFeedbackEnabled,
        container.settingsRepository.useCaseView,
        container.settingsRepository.appLanguageTag
    ) { historyEnabled, warningsEnabled, scanFeedbackEnabled, useCaseView, appLanguageTag ->
        SettingsState(
            historyEnabled = historyEnabled,
            warningsEnabled = warningsEnabled,
            scanFeedbackEnabled = scanFeedbackEnabled,
            useCaseView = useCaseView,
            appLanguageTag = appLanguageTag
        )
    }

    val uiState: StateFlow<AppUiState> = combine(
        settingsState,
        container.scanRepository.observeHistory(),
        query
    ) { settings, history, q ->
        AppUiState(
            historyEnabled = settings.historyEnabled,
            warningsEnabled = settings.warningsEnabled,
            scanFeedbackEnabled = settings.scanFeedbackEnabled,
            useCaseView = settings.useCaseView,
            appLanguageTag = settings.appLanguageTag,
            history = if (q.isBlank()) history else history.filter {
                it.content.contains(q, ignoreCase = true) || it.type.contains(q, ignoreCase = true)
            },
            searchQuery = q
        )
    }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), AppUiState())

    fun setQuery(value: String) {
        query.value = value
    }

    fun setHistoryEnabled(enabled: Boolean, clearHistoryIfDisabled: Boolean) {
        viewModelScope.launch {
            container.settingsRepository.setHistoryEnabled(enabled)
            if (!enabled && clearHistoryIfDisabled) {
                container.scanRepository.clearAll()
            }
        }
    }

    fun setWarningsEnabled(enabled: Boolean) {
        viewModelScope.launch {
            container.settingsRepository.setWarningsEnabled(enabled)
        }
    }

    fun setScanFeedbackEnabled(enabled: Boolean) {
        viewModelScope.launch {
            container.settingsRepository.setScanFeedbackEnabled(enabled)
        }
    }

    fun setUseCaseView(useCaseView: UseCaseView) {
        viewModelScope.launch {
            container.settingsRepository.setUseCaseView(useCaseView)
        }
    }

    fun setAppLanguageTag(languageTag: String) {
        viewModelScope.launch {
            container.settingsRepository.setAppLanguageTag(languageTag)
        }
    }

    fun deleteHistoryItem(id: Long) {
        viewModelScope.launch {
            container.scanRepository.deleteById(id)
        }
    }

    fun clearHistory() {
        viewModelScope.launch {
            container.scanRepository.clearAll()
        }
    }

    class Factory(private val container: AppContainer) : ViewModelProvider.Factory {
        @Suppress("UNCHECKED_CAST")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return AppViewModel(container) as T
        }
    }
}
