package com.adealink.weparty.config

import com.adealink.frame.base.AppBase
import com.adealink.frame.util.ONE_MINUTE
import com.adealink.frame.util.PackageUtil
import com.adealink.weparty.channel.getChannel
import com.google.gson.annotations.GsonNullable
import com.google.gson.annotations.Must
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import java.lang.reflect.Type
import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.reflect.typeOf

data class GetGlobalConfigReq(
    @SerializedName("configs") val configs: List<String>,
    @SerializedName("seqid") val seqId: Long = System.currentTimeMillis(),
    @SerializedName("versionCode") val versionCode: Int = PackageUtil.getVersionCode(),
    @SerializedName("platform") val platform: String = AppBase.platform,
    @SerializedName("packageName") val packageName: String = PackageUtil.getPackageName(),
    @SerializedName("channel") val channel: String = getChannel(),
)

data class GetGlobalConfigRes(
    @SerializedName("result") val result: GlobalConfigData,
)


data class GlobalConfigData(
    @GsonNullable
    @SerializedName("commonCoinExchangeConsts")
    var currencyConvertConfig: List<CoinExchangeConfig>? = null,
) {
    fun merge(other: GlobalConfigData?) {
        other?.currencyConvertConfig?.let {
            currencyConvertConfig = it
        }
    }

    fun <T> getConfig(config: GlobalConfigType): T? {
        when (config) {
            GlobalConfigType.CURRENCY_CONVERT_CONFIG -> {
                return castToType(currencyConvertConfig, config.clazz)
            }
        }
        return null
    }

    fun <T> getConfig(config: Config<T>): T? {
        return when (config) {
            Config.CoinExchange -> {
                currencyConvertConfig as T
            }

            Config.Domain -> {
                null
            }
        }
    }

}

fun <T> castToType(value: Any?, kType: KType): T? {
    val kClass = kType.classifier as? KClass<*>
    return if (kClass?.isInstance(value) == true) {
        @Suppress("UNCHECKED_CAST")
        value as T
    } else {
        null
    }
}

enum class GlobalConfigType(val value: String, val clazz: KType) {
    //GLOBAL_APPROVING_VERSION(0), //提审配置
    CURRENCY_CONVERT_CONFIG(
        "commonCoinExchangeConsts",
        typeOf<List<CoinExchangeConfig>>()
    ), //货币转化(兑换)配置

    ;

    companion object {
        fun map(value: String): GlobalConfigType? {
            return values().firstOrNull { it.value == value }
        }
    }
}

// 定义数据类
data class DomainConfig(
    @GsonNullable
    @SerializedName("host")
    val host: List<String>? = null,
    @GsonNullable
    @SerializedName("backup_host")
    val backupHost: List<String>? = null,
    @GsonNullable
    @SerializedName("dns")
    val dns: Map<String, String>? = null
)

data class CoinExchangeConfig(
    @Must
    @SerializedName("IDR") val IDR: Double,
    @GsonNullable
    @SerializedName("goldCoin")
    val coin: Double? = null,
    @GsonNullable
    @SerializedName("bean")
    val bean: Double? = null,
    @GsonNullable
    @SerializedName("diamond")
    val diamond: Double? = null
)


// 密封类定义所有可能的配置类型
sealed class Config<out T> {
    abstract val key: String
    abstract val type: Type

    object Domain : Config<DomainConfig>() {
        override val key = "commonBaseAppDomainConsts"
        override val type = object : TypeToken<DomainConfig>() {}.type
    }

    object CoinExchange : Config<List<CoinExchangeConfig>>() {
        override val key = "commonCoinExchangeConsts"
        override val type = object : TypeToken<List<CoinExchangeConfig>>() {}.type
    }
}

const val TAG_GLOBAL_CONFIG = "tag_global_config"
const val GET_CONFIG_TIME_INTERVAL = 15 * ONE_MINUTE