@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.model

import android.annotation.SuppressLint
import android.content.Context
import eu.gaudian.translator.R
import eu.gaudian.translator.utils.Log
import kotlinx.serialization.Serializable
import java.util.Locale
import kotlin.random.Random

@Serializable
data class Language(
    val code: String, //ISO 639-1 code
    val region: String,
    val nameResId: Int,
    val name: String, //the name is context specific and can differ in various languages -> gets loaded when App starts
    val englishName: String, //to be used internally for requests etc.
    val nativeName: String = englishName, //the native name of the language (e.g., "Deutsch" for German), defaults to englishName for backward compatibility
    val isCustom: Boolean? = false, // there is also an option to add custom languages
    var isSelected: Boolean? = false
) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as Language

        if (code != other.code) return false
        if (region != other.region) return false
        if (nameResId != other.nameResId) return false
        if (name != other.name) return false
        if (englishName != other.englishName) return false
        if (nativeName != other.nativeName) return false
        if (isCustom != other.isCustom) return false
        if (isSelected != other.isSelected) return false

        return true
    }
    @Suppress("unused")
    fun isSameAs(other: Language?): Boolean {
        if (other == null) return false

        if (this.isCustom == true && other.isCustom == true) {
            return this.name.equals(other.name, ignoreCase = true) &&
                    this.code.equals(other.code, ignoreCase = true)
        }
        if (this.isCustom != other.isCustom) {
            return false
        }
        return this.nameResId == other.nameResId
    }

    override fun hashCode(): Int {
        var result = code.hashCode()
        result = 31 * result + region.hashCode()
        result = 31 * result + nameResId
        result = 31 * result + name.hashCode()
        result = 31 * result + englishName.hashCode()
        result = 31 * result + nativeName.hashCode()
        result = 31 * result + (isCustom?.hashCode() ?: 0)
        result = 31 * result + (isSelected?.hashCode() ?: 0)
        return result
    }

}

fun parseLanguagesFromResources(context: Context): List<Language> {
    val languages = mutableListOf<Language>()
    val languageCodes = context.resources.getStringArray(R.array.language_codes)

    Log.d("LanguageParser", "Starting to parse languages from resources")

    languageCodes.forEach { item ->
        val parts = item.split(",")
        if (parts.size == 3) {
            val code = parts[0].lowercase(Locale.getDefault())
            val region = parts[1]
            val nameResId = parts[2].toIntOrNull() ?: 0
            if (nameResId != 0) {
                val localizedName = getCapitalizedName(context, nameResId)
                val englishName = getEnglishName(context, nameResId)
                Log.d("LanguageParser", "Parsed language: $code, $region, $nameResId")
                val nativeName = getNativeName(context, nameResId)
                languages.add(
                    Language(
                        code = code,
                        region = region,
                        nameResId = nameResId,
                        name = localizedName,
                        englishName = englishName,
                        nativeName = nativeName,
                        isCustom = false,
                        isSelected = true
                    )
                )
            } else {
                Log.w("LanguageParser", "Invalid nameResId for language: $code, $region")
            }
        } else {
            Log.e("LanguageParser", "Invalid language code format: $item")
        }
    }

    Log.d("LanguageParser", "Finished parsing languages. Total languages: ${languages.size}")
    return languages
}

@SuppressLint("DiscouragedApi")
private fun getCapitalizedName(context: Context, nameResId: Int): String {
    return try {
        val name = context.getString(
            context.resources.getIdentifier("language_$nameResId", "string", context.packageName)
        )
        name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
    } catch (e: Exception) {
        Log.e("Language", "Resource not found for nameResId: $nameResId", e)
        context.getString(R.string.text_unknown_language)
    }
}

@SuppressLint("AppBundleLocaleChanges", "DiscouragedApi")
private fun getEnglishName(context: Context, nameResId: Int): String {
    return try {
        val resName = "language_$nameResId"
        val id = context.resources.getIdentifier(resName, "string", context.packageName)
        if (id == 0) return context.getString(R.string.text_unknown_language)

        // Use the application context with English locale for resource lookup
        val resources = context.applicationContext.resources
        val configuration = android.content.res.Configuration(resources.configuration)
        configuration.setLocale(Locale.ENGLISH)
        val localizedContext = context.applicationContext.createConfigurationContext(configuration)
        localizedContext.resources.getString(id)
    } catch (e: Exception) {
        Log.e("Language", "Failed to get English name for nameResId: $nameResId", e)
        context.getString(R.string.text_unknown_language)
    }
}

@SuppressLint("DiscouragedApi")
fun getNativeName(context: Context, nameResId: Int): String {

    return try {
        val resName = "native_language_$nameResId"
        val id = context.resources.getIdentifier(resName, "string", context.packageName)
        Log.d("Language", "Native name resource ID for nameResId $nameResId: $id")
        if (id == 0) {
            Log.w("Language", "Native name resource not found for nameResId: $nameResId")
            getEnglishName(context, nameResId)
        } else {

            context.getString(id)
        }
    } catch (e: Exception) {
        Log.e("Language", "Failed to get native name for nameResId: $nameResId", e)
        getEnglishName(context, nameResId)
    }
}

//meant for creating dummies, testing, etc
fun generateRandomLanguage(): Language {
    return Language(
        code = "random",
        region = "",
        nameResId = 0,
        name = "Language "+ Random.nextInt(1000, 9999).toString(),
        englishName = "German",
        nativeName = "Deutsch",
        isCustom = false,
        isSelected = true
    )
}

fun generateSimpleLanguage(name: String): Language {
    return Language(
        code = "random",
        region = "",
        nameResId = 0,
        name = name,
        englishName = "German",
        nativeName = "Deutsch",
        isCustom = false,
        isSelected = true
    )
}

