package com.ama.core.architecture.util

import android.content.Context
import android.content.SharedPreferences
import android.util.Base64
import com.ama.core.architecture.BaseApp
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.lang.reflect.Type
import java.nio.charset.Charset


class SpUtil private constructor(spFileName: String) {
    companion object {
        private const val DEFAULT_SP_NAME = "VidiDin_Common"



        const val KEY_ACCOUNT = "KEY_ACCOUNT"
        const val KEY_TASK_BEAN = "KEY_TASK_BEAN"


        // Various tasks
        const val KEY_DAILY_SIGN = "KEY_DAILY_SIGN"
        const val KEY_DAILY_WATCH_VIDEO = "KEY_DAILY_WATCH_VIDEO"
        const val KEY_DAILY_WATCH_AD_FOR_GOLD = "KEY_DAILY_WATCH_AD_FOR_GOLD"
        const val KEY_TASK_BOX = "KEY_TASK_BOX"

        const val KEY_NEWBIE_FIRST_WITHDRAW = "KEY_NEWBIE_FIRST_WITHDRAW"
        const val KEY_NEWBIE_ENABLE_NOTIFY = "KEY_NEWBIE_ENABLE_NOTIFY"
        const val KEY_NEWBIE_JOIN_DISCORD = "KEY_NEWBIE_JOIN_DISCORD"






        @Volatile
        private var instance: SpUtil? = null
        fun instance(prefName: String = DEFAULT_SP_NAME): SpUtil {
            return instance ?: synchronized(this) {
                instance ?: SpUtil(prefName).also {
                    instance = it
                }
            }
        }
    }



    val gson: Gson = Gson()
    private val sharedPreferences: SharedPreferences

    init {
        sharedPreferences = BaseApp.appContext().getSharedPreferences(spFileName, Context.MODE_PRIVATE)
    }








    // ----------- 基本数据类型操作 -----------
    fun putString(key: String, value: String?) {
        sharedPreferences.edit().putString(key, value).apply()
    }

    fun getString(key: String, defaultValue: String = ""): String {
        return sharedPreferences.getString(key, defaultValue) ?: defaultValue
    }

    fun putInt(key: String, value: Int) {
        sharedPreferences.edit().putInt(key, value).apply()
    }

    fun getInt(key: String, defaultValue: Int = 0): Int {
        return sharedPreferences.getInt(key, defaultValue)
    }

    fun putBoolean(key: String, value: Boolean) {
        sharedPreferences.edit().putBoolean(key, value).apply()
    }

    fun getBoolean(key: String, defaultValue: Boolean = false): Boolean {
        return sharedPreferences.getBoolean(key, defaultValue)
    }

    fun putLong(key: String, value: Long) {
        sharedPreferences.edit().putLong(key, value).apply()
    }

    fun getLong(key: String, defaultValue: Long = 0L): Long {
        return sharedPreferences.getLong(key, defaultValue)
    }

    fun putFloat(key: String, value: Float) {
        sharedPreferences.edit().putFloat(key, value).apply()
    }

    fun getFloat(key: String, defaultValue: Float = 0f): Float {
        return sharedPreferences.getFloat(key, defaultValue)
    }






    // ----------- 复杂对象 -----------
    fun <T> putObject(key: String, obj: T) {
        try {
            val jsonString = gson.toJson(obj)
            val encryptedData = Base64.encodeToString(jsonString.toByteArray(), Base64.DEFAULT)
            putString(key, encryptedData)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    inline fun <reified T> getObject(key: String, defaultObj: T? = null): T? {
        return try {
            val encryptedData = getString(key)
            if (encryptedData.isBlank()) return defaultObj

            val jsonString = String(Base64.decode(encryptedData, Base64.DEFAULT), Charset.forName("UTF-8"))

            val type = object : TypeToken<T>() {}.type
            gson.fromJson(jsonString, type) ?: defaultObj
        } catch (e: Exception) {
            e.printStackTrace()
            defaultObj
        }
    }


    fun <T> putList(key: String, list: List<T>) {
        try {
            val jsonString = gson.toJson(list)
            val encryptedData = Base64.encodeToString(jsonString.toByteArray(), Base64.DEFAULT)
            putString(key, encryptedData)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    inline fun <reified T> getList(key: String): List<T> {
        return try {
            val encryptedData = getString(key)
            if (encryptedData.isBlank()) return emptyList()

            val jsonString = String(Base64.decode(encryptedData, Base64.DEFAULT))
            val type: Type = object : TypeToken<List<T>>() {}.type
            gson.fromJson<List<T>>(jsonString, type) ?: emptyList()
        } catch (e: Exception) {
            e.printStackTrace()
            emptyList()
        }
    }


    fun <K, V> putMap(key: String, map: Map<K, V>) {
        try {
            val jsonString = gson.toJson(map)
            val encryptedData = Base64.encodeToString(jsonString.toByteArray(), Base64.DEFAULT)
            putString(key, encryptedData)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    inline fun <reified K, reified V> getMap(key: String): Map<K, V> {
        return try {
            val encryptedData = getString(key)
            if (encryptedData.isBlank()) return emptyMap()

            val jsonString = String(Base64.decode(encryptedData, Base64.DEFAULT))
            val type: Type = object : TypeToken<Map<K, V>>() {}.type
            gson.fromJson<Map<K, V>>(jsonString, type) ?: emptyMap()
        } catch (e: Exception) {
            e.printStackTrace()
            emptyMap()
        }
    }




    // ----------- 工具方法 -----------
    fun contains(key: String): Boolean {
        return sharedPreferences.contains(key)
    }

    fun remove(key: String) {
        sharedPreferences.edit().remove(key).apply()
    }

    fun clear() {
        sharedPreferences.edit().clear().apply()
    }

    fun getAllKeys(): Set<String> {
        return sharedPreferences.all.keys
    }


}