@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.model.repository

import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import eu.gaudian.translator.model.grammar.LanguageConfig
import eu.gaudian.translator.utils.Log
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.serialization.json.Json
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Repository for managing language configurations loaded from assets.
 * This is a singleton that can be injected into multiple ViewModels.
 */
@Singleton
class LanguageConfigRepository @Inject constructor(
    @param:ApplicationContext private val context: Context
) {
    private val _configs = MutableStateFlow<Map<String, LanguageConfig>>(emptyMap())
    val configs: StateFlow<Map<String, LanguageConfig>> = _configs.asStateFlow()

    private val jsonParser = Json { ignoreUnknownKeys = true }

    init {
        loadAllConfigs()
    }

    /**
     * Loads all language configuration files from the "language_configs" asset directory.
     */
    private fun loadAllConfigs() {
        try {
            val configFiles = context.assets.list("language_configs") ?: return
            val loadedConfigs = mutableMapOf<String, LanguageConfig>()

            for (fileName in configFiles) {
                if (fileName.endsWith(".json")) {
                    val jsonString = context.assets.open("language_configs/$fileName")
                        .bufferedReader()
                        .use { it.readText() }

                    val config = jsonParser.decodeFromString<LanguageConfig>(jsonString)
                    loadedConfigs[config.language_code] = config
                }
            }
            _configs.value = loadedConfigs
        } catch (e: Exception) {
            Log.e("Failed to load language configs: ${e.message}")
            e.printStackTrace()
        }
    }

    /**
     * Retrieves the configuration for a specific language code.
     *
     * @param langCode The ISO language code (e.g., "de").
     * @return The LanguageConfig for the given code, or null if not found.
     */
    fun getConfigForLanguage(langCode: String): LanguageConfig? {
        Log.d("Fetching config for language: $langCode")
        return _configs.value[langCode]
    }

    /**
     * Retrieves the set of articles for a specific language code.
     *
     * @param langCode The ISO language code (e.g., "de").
     * @return A Set<String> of articles for the given language. Returns an empty set if
     * the language code is not found or if the language has no articles defined.
     */
    fun getArticlesForLanguage(langCode: String): Set<String> {
        return try {
            val config = _configs.value[langCode]
            config?.articles?.toSet() ?: emptySet()
        } catch (e: Exception) {
            Log.e("Error retrieving articles for '$langCode': ${e.message}")
            emptySet()
        }
    }
}