package com.tomhempel.rbarometer

import android.content.Context
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.util.concurrent.atomic.AtomicReference

/**
 * Resolves UI strings from API translations (synced from the website).
 * Falls back to bundled German defaults for app UI strings when the server
 * has not yet synced translations for the source language.
 */
object LanguageManager {
    /** Global app UI strings from GET ?translations=1 */
    private var apiTranslations: Map<String, Map<String, String>> = emptyMap()
    /** Questionnaire-specific strings from GET ?id=... */
    private var questionnaireTranslations: Map<String, Map<String, String>> = emptyMap()
    private val bundledGermanDefaults = AtomicReference<Map<String, String>?>(null)

    fun setApiTranslations(translations: Map<String, Map<String, String>>) {
        apiTranslations = translations
    }

    fun setQuestionnaireTranslations(translations: Map<String, Map<String, String>>) {
        questionnaireTranslations = translations
    }

    fun clearQuestionnaireTranslations() {
        questionnaireTranslations = emptyMap()
    }

    fun warmBundledDefaults(context: Context) {
        if (bundledGermanDefaults.get() != null) return
        bundledGermanDefaults.set(loadBundledGermanDefaults(context))
    }

    fun getTextFormatted(languageId: String, key: String, vararg args: Any): String {
        val raw = getText(languageId, key)
        return String.format(raw, *args)
    }

    fun getText(languageCode: String, id: String): String {
        val lang = apiLanguageCode(languageCode)
        val fromQuestionnaire = questionnaireTranslations[lang]?.get(id)
        val fromApi = apiTranslations[lang]?.get(id)
        val fromQuestionnaireDe = questionnaireTranslations["de"]?.get(id)
        val fromApiDe = apiTranslations["de"]?.get(id)
        val fromBundledDe = bundledGermanDefaults.get()?.get(id)

        val raw = when {
            !fromQuestionnaire.isNullOrBlank() -> fromQuestionnaire
            !fromApi.isNullOrBlank() -> fromApi
            !fromQuestionnaireDe.isNullOrBlank() -> fromQuestionnaireDe
            !fromApiDe.isNullOrBlank() -> fromApiDe
            !fromBundledDe.isNullOrBlank() -> fromBundledDe
            else -> id
        }
        return injectDynamicValues(raw)
    }

    /** Returns the first key that resolves to translated text (not equal to the key itself). */
    fun resolvedText(languageCode: String, vararg keys: String?): String {
        for (key in keys) {
            if (key.isNullOrBlank()) continue
            val text = getText(languageCode, key)
            if (text != key) return text
        }
        return keys.filterNot { it.isNullOrBlank() }.lastOrNull()?.let { getText(languageCode, it) } ?: ""
    }

    private fun apiLanguageCode(languageCode: String): String = when (languageCode) {
        "GERMAN" -> "de"
        "ENGLISH" -> "en"
        "FRENCH" -> "fr"
        "ROMANIAN" -> "ro"
        "ARABIC" -> "ar"
        "POLISH" -> "pl"
        "TURKISH" -> "tr"
        "UKRAINIAN" -> "uk"
        "RUSSIAN" -> "ru"
        "SPANISH" -> "es"
        "CHINESE" -> "zh"
        "FARSI" -> "fa"
        else -> languageCode.lowercase()
    }

    private fun loadBundledGermanDefaults(context: Context): Map<String, String> {
        return runCatching {
            context.assets.open("bundled_german_defaults.json").bufferedReader().use { reader ->
                val type = object : TypeToken<Map<String, String>>() {}.type
                Gson().fromJson<Map<String, String>>(reader, type) ?: emptyMap()
            }
        }.getOrDefault(emptyMap())
    }

    private fun injectDynamicValues(text: String): String = text
}
