package com.a2i.forwarder.store

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.a2i.forwarder.model.BarkServer
import com.a2i.forwarder.model.OFFICIAL_BARK_SERVER
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

private val Context.settingsDataStore: DataStore<Preferences> by preferencesDataStore(name = "a2i_settings")

class SettingsStore(
    private val context: Context,
    scope: CoroutineScope,
) {
    private val ds get() = context.settingsDataStore
    private val json = Json { ignoreUnknownKeys = true; encodeDefaults = true }

    private object K {
        val SERVERS = stringPreferencesKey("servers")
        val CURRENT = stringPreferencesKey("current")
        val ICON_PREFIX = stringPreferencesKey("icon_prefix")
        val FWD = booleanPreferencesKey("forwarding")
        val CODE = booleanPreferencesKey("code")
        val AD = booleanPreferencesKey("ad_filter")
        val SPECIAL = booleanPreferencesKey("special")
        val SKIP_ONGOING = booleanPreferencesKey("skip_ongoing")
        val AD_KW = stringPreferencesKey("ad_keywords")
        // 短信兜底
        val SMS_FALLBACK = booleanPreferencesKey("sms_fallback")
        val SMS_TARGET = stringPreferencesKey("sms_target")
        val SMS_CARRIER = stringPreferencesKey("sms_carrier")
        val SMS_QUOTA = intPreferencesKey("sms_quota")
        val SMS_BALANCE = intPreferencesKey("sms_balance")
        val SMS_SUSPENDED = booleanPreferencesKey("sms_suspended")
        val SMS_LAST_SENT = longPreferencesKey("sms_last_sent")
        // 应用更新
        val UPDATE_CHECK_AUTO = booleanPreferencesKey("update_check_auto")
        val LAST_UPDATE_CHECK = longPreferencesKey("last_update_check")
        val IGNORED_VERSION = stringPreferencesKey("ignored_version")
    }

    private val defaultServers = listOf(
        BarkServer(id = ID_OFFICIAL, name = "Bark 官方", server = OFFICIAL_BARK_SERVER, deviceKey = "")
    )

    private val _servers = MutableStateFlow(defaultServers)
    val servers = _servers.asStateFlow()

    private val _currentServerId = MutableStateFlow(ID_OFFICIAL)
    val currentServer = MutableStateFlow<BarkServer?>(defaultServers.first())

    val iconPrefix = MutableStateFlow(DEFAULT_ICON_PREFIX)
    val forwardingEnabled = MutableStateFlow(true)
    val codeEnabled = MutableStateFlow(true)
    val adFilterEnabled = MutableStateFlow(true)
    val specialEnabled = MutableStateFlow(true)
    val skipOngoing = MutableStateFlow(true)
    val adKeywords = MutableStateFlow<List<String>>(emptyList()) // 用户自定义关键词

    // 短信兜底
    val smsFallbackEnabled = MutableStateFlow(false)
    val smsTargetNumber = MutableStateFlow("")
    val smsCarrier = MutableStateFlow("auto")       // "auto" 或 Carrier.name
    val smsManualQuota = MutableStateFlow(0)         // 手动额度（自动解析失败时回退用）
    val smsBalance = MutableStateFlow(-1)            // 缓存余额，-1=未知
    val smsSuspended = MutableStateFlow(false)       // 余额 ≤5 自动挂起
    val lastSmsSentTime = MutableStateFlow(0L)       // 限频时间戳

    // 应用更新
    val updateCheckEnabled = MutableStateFlow(true)     // 自动检查更新开关
    val lastUpdateCheckTime = MutableStateFlow(0L)      // 上次检查时间戳
    val ignoredVersion = MutableStateFlow("")           // 用户忽略的版本号

    init {
        scope.launch {
            ds.data.collect { p ->
                val list: List<BarkServer> = p[K.SERVERS]
                    ?.let { runCatching { json.decodeFromString<List<BarkServer>>(it) }.getOrNull() }
                    ?: defaultServers
                _servers.value = list
                _currentServerId.value = p[K.CURRENT] ?: ID_OFFICIAL
                currentServer.value = list.firstOrNull { it.id == _currentServerId.value } ?: list.firstOrNull()
                iconPrefix.value = p[K.ICON_PREFIX] ?: DEFAULT_ICON_PREFIX
                forwardingEnabled.value = p[K.FWD] ?: true
                codeEnabled.value = p[K.CODE] ?: true
                adFilterEnabled.value = p[K.AD] ?: true
                specialEnabled.value = p[K.SPECIAL] ?: true
                skipOngoing.value = p[K.SKIP_ONGOING] ?: true
                adKeywords.value = p[K.AD_KW]
                    ?.let { runCatching { json.decodeFromString<List<String>>(it) }.getOrNull() }
                    ?: emptyList()
                // 短信兜底
                smsFallbackEnabled.value = p[K.SMS_FALLBACK] ?: false
                smsTargetNumber.value = p[K.SMS_TARGET] ?: ""
                smsCarrier.value = p[K.SMS_CARRIER] ?: "auto"
                smsManualQuota.value = p[K.SMS_QUOTA] ?: 0
                smsBalance.value = p[K.SMS_BALANCE] ?: -1
                smsSuspended.value = p[K.SMS_SUSPENDED] ?: false
                lastSmsSentTime.value = p[K.SMS_LAST_SENT] ?: 0L
                // 应用更新
                updateCheckEnabled.value = p[K.UPDATE_CHECK_AUTO] ?: true
                lastUpdateCheckTime.value = p[K.LAST_UPDATE_CHECK] ?: 0L
                ignoredVersion.value = p[K.IGNORED_VERSION] ?: ""
            }
        }
    }

    private suspend fun edit(block: (androidx.datastore.preferences.core.MutablePreferences) -> Unit) =
        ds.edit(block)

    private suspend fun saveServers(list: List<BarkServer>) {
        edit { it[K.SERVERS] = json.encodeToString(list) }
        _servers.value = list
        refreshCurrent()
    }

    suspend fun addServer(name: String, server: String, key: String): BarkServer {
        val s = BarkServer(name = name.trim(), server = server.trim().removeSuffix("/"), deviceKey = key.trim())
        saveServers(_servers.value + s)
        if (_servers.value.count { it.id == s.id } == 1 && currentServer.value?.deviceKey.isNullOrBlank()) {
            setCurrent(s.id)
        }
        return s
    }

    suspend fun updateServer(s: BarkServer) = saveServers(_servers.value.map { if (it.id == s.id) s.copy(server = s.server.trim().removeSuffix("/")) else it })

    suspend fun deleteServer(id: String) {
        val list = _servers.value.filterNot { it.id == id }
        saveServers(list)
        if (_currentServerId.value == id) {
            setCurrent(if (list.isEmpty()) "" else list.first().id)
        }
    }

    suspend fun setCurrent(id: String) {
        edit { it[K.CURRENT] = id }
        _currentServerId.value = id
        refreshCurrent()
    }

    private fun refreshCurrent() {
        currentServer.value = _servers.value.firstOrNull { it.id == _currentServerId.value } ?: _servers.value.firstOrNull()
    }

    suspend fun setIconPrefix(v: String) { edit { it[K.ICON_PREFIX] = v }; iconPrefix.value = v }
    suspend fun setForwarding(v: Boolean) { edit { it[K.FWD] = v }; forwardingEnabled.value = v }
    suspend fun setCode(v: Boolean) { edit { it[K.CODE] = v }; codeEnabled.value = v }
    suspend fun setAdFilter(v: Boolean) { edit { it[K.AD] = v }; adFilterEnabled.value = v }
    suspend fun setSpecial(v: Boolean) { edit { it[K.SPECIAL] = v }; specialEnabled.value = v }
    suspend fun setSkipOngoing(v: Boolean) { edit { it[K.SKIP_ONGOING] = v }; skipOngoing.value = v }
    suspend fun setAdKeywords(list: List<String>) {
        edit { it[K.AD_KW] = json.encodeToString(list) }
        adKeywords.value = list
    }

    suspend fun setSmsFallback(v: Boolean) { edit { it[K.SMS_FALLBACK] = v }; smsFallbackEnabled.value = v }
    suspend fun setSmsTargetNumber(v: String) { edit { it[K.SMS_TARGET] = v }; smsTargetNumber.value = v }
    suspend fun setSmsCarrier(v: String) { edit { it[K.SMS_CARRIER] = v }; smsCarrier.value = v }
    suspend fun setSmsManualQuota(v: Int) { edit { it[K.SMS_QUOTA] = v }; smsManualQuota.value = v }
    suspend fun setSmsBalance(v: Int) { edit { it[K.SMS_BALANCE] = v }; smsBalance.value = v }
    suspend fun setSmsSuspended(v: Boolean) { edit { it[K.SMS_SUSPENDED] = v }; smsSuspended.value = v }
    suspend fun setLastSmsSentTime(v: Long) { edit { it[K.SMS_LAST_SENT] = v }; lastSmsSentTime.value = v }

    suspend fun setUpdateCheckEnabled(v: Boolean) { edit { it[K.UPDATE_CHECK_AUTO] = v }; updateCheckEnabled.value = v }
    suspend fun setLastUpdateCheck(v: Long) { edit { it[K.LAST_UPDATE_CHECK] = v }; lastUpdateCheckTime.value = v }
    suspend fun setIgnoredVersion(v: String) { edit { it[K.IGNORED_VERSION] = v }; ignoredVersion.value = v }

    suspend fun snapshot() = ds.data.first()

    companion object {
        const val ID_OFFICIAL = "official"
        const val DEFAULT_ICON_PREFIX = "https://raw.githubusercontent.com/lsxf/a2i/main/icons/"
    }
}
