package top.yeij.cyrene.data.local

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.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

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

class PreferencesDataStore(private val context: Context) {

    companion object {
        private val KEY_TOKEN = stringPreferencesKey("jwt_token")
        private val KEY_REFRESH_TOKEN = stringPreferencesKey("refresh_token")
        private val KEY_BASE_URL = stringPreferencesKey("base_url")
        private val KEY_THEME = stringPreferencesKey("theme_mode")
        private val KEY_WAKE_WORD = stringPreferencesKey("wake_word")
        private val KEY_USERNAME = stringPreferencesKey("username")
        private val KEY_CLIENT_ID = stringPreferencesKey("client_id")
        private val KEY_DEVICE_NAME = stringPreferencesKey("device_name")
        private val KEY_CURRENT_SESSION_ID = stringPreferencesKey("current_session_id")
        private val KEY_DASHSCOPE_API_KEY = stringPreferencesKey("dashscope_api_key")
        private val KEY_DASHSCOPE_ENDPOINT = stringPreferencesKey("dashscope_endpoint")
        private val KEY_DASHSCOPE_MODEL = stringPreferencesKey("dashscope_model")
        private val KEY_LAST_CLEARED_TIMESTAMP = stringPreferencesKey("last_cleared_timestamp")
        private val KEY_PROFILE_USER_ID = stringPreferencesKey("profile_user_id")
        private val KEY_PROFILE_NICKNAME = stringPreferencesKey("profile_nickname")
        private val KEY_PROFILE_IS_ADMIN = stringPreferencesKey("profile_is_admin")
        private val KEY_PROFILE_CREATED_AT = stringPreferencesKey("profile_created_at")
        private val KEY_AUTO_SCREEN_CONTEXT = booleanPreferencesKey("auto_screen_context")
        private val KEY_TYPING_INDICATOR_STYLE = stringPreferencesKey("typing_indicator_style")
        private val KEY_ENTER_TO_SEND = booleanPreferencesKey("enter_to_send")
        private val KEY_ROOT_KEEPALIVE = booleanPreferencesKey("root_keepalive")
        private val KEY_THEME_COLOR = stringPreferencesKey("theme_color")
    }

    val typingIndicatorStyle: Flow<String> = context.dataStore.data.map { it[KEY_TYPING_INDICATOR_STYLE] ?: "bubble" }

    suspend fun saveTypingIndicatorStyle(style: String) {
        context.dataStore.edit { it[KEY_TYPING_INDICATOR_STYLE] = style }
    }

    val enterToSend: Flow<Boolean> = context.dataStore.data.map { it[KEY_ENTER_TO_SEND] ?: false }

    suspend fun saveEnterToSend(enabled: Boolean) {
        context.dataStore.edit { it[KEY_ENTER_TO_SEND] = enabled }
    }

    val rootKeepAlive: Flow<Boolean> = context.dataStore.data.map { it[KEY_ROOT_KEEPALIVE] ?: false }

    suspend fun saveRootKeepAlive(enabled: Boolean) {
        context.dataStore.edit { it[KEY_ROOT_KEEPALIVE] = enabled }
    }

    val themeColor: Flow<String> = context.dataStore.data.map { it[KEY_THEME_COLOR] ?: "pink" }

    suspend fun saveThemeColor(color: String) {
        context.dataStore.edit { it[KEY_THEME_COLOR] = color }
    }

    val token: Flow<String?> = context.dataStore.data.map { it[KEY_TOKEN] }
    val refreshToken: Flow<String?> = context.dataStore.data.map { it[KEY_REFRESH_TOKEN] }
    val baseUrl: Flow<String?> = context.dataStore.data.map { it[KEY_BASE_URL] }
    val themeMode: Flow<String?> = context.dataStore.data.map { it[KEY_THEME] }
    val wakeWord: Flow<String?> = context.dataStore.data.map { it[KEY_WAKE_WORD] }
    val username: Flow<String?> = context.dataStore.data.map { it[KEY_USERNAME] }
    val clientId: Flow<String?> = context.dataStore.data.map { it[KEY_CLIENT_ID] }
    val deviceName: Flow<String?> = context.dataStore.data.map { it[KEY_DEVICE_NAME] }
    val currentSessionId: Flow<String?> = context.dataStore.data.map { it[KEY_CURRENT_SESSION_ID] }
    val dashScopeApiKey: Flow<String?> = context.dataStore.data.map { it[KEY_DASHSCOPE_API_KEY] }
    val dashScopeEndpoint: Flow<String?> = context.dataStore.data.map { it[KEY_DASHSCOPE_ENDPOINT] }
    val dashScopeModel: Flow<String?> = context.dataStore.data.map { it[KEY_DASHSCOPE_MODEL] }

    suspend fun saveToken(token: String) {
        context.dataStore.edit { it[KEY_TOKEN] = token }
    }

    suspend fun saveRefreshToken(token: String) {
        context.dataStore.edit { it[KEY_REFRESH_TOKEN] = token }
    }

    suspend fun saveBaseUrl(url: String) {
        context.dataStore.edit { it[KEY_BASE_URL] = url }
    }

    suspend fun saveThemeMode(mode: String) {
        context.dataStore.edit { it[KEY_THEME] = mode }
    }

    suspend fun saveWakeWord(word: String) {
        context.dataStore.edit { it[KEY_WAKE_WORD] = word }
    }

    suspend fun saveUsername(username: String) {
        context.dataStore.edit { it[KEY_USERNAME] = username }
    }

    suspend fun saveDashScopeApiKey(key: String) {
        context.dataStore.edit { it[KEY_DASHSCOPE_API_KEY] = key }
    }

    suspend fun saveDashScopeEndpoint(endpoint: String) {
        context.dataStore.edit { it[KEY_DASHSCOPE_ENDPOINT] = endpoint }
    }

    suspend fun saveDashScopeModel(model: String) {
        context.dataStore.edit { it[KEY_DASHSCOPE_MODEL] = model }
    }

    suspend fun saveClientId(id: String) {
        context.dataStore.edit { it[KEY_CLIENT_ID] = id }
    }

    suspend fun saveDeviceName(name: String) {
        context.dataStore.edit { it[KEY_DEVICE_NAME] = name }
    }

    suspend fun saveCurrentSessionId(id: String) {
        context.dataStore.edit { it[KEY_CURRENT_SESSION_ID] = id }
    }

    val lastClearedTimestamp: Flow<String?> = context.dataStore.data.map { it[KEY_LAST_CLEARED_TIMESTAMP] }

    suspend fun saveLastClearedTimestamp(timestamp: Long) {
        context.dataStore.edit { it[KEY_LAST_CLEARED_TIMESTAMP] = timestamp.toString() }
    }

    // Cached profile for offline / local-first rendering
    val profileUserId: Flow<String?> = context.dataStore.data.map { it[KEY_PROFILE_USER_ID] }
    val profileNickname: Flow<String?> = context.dataStore.data.map { it[KEY_PROFILE_NICKNAME] }
    val profileIsAdmin: Flow<String?> = context.dataStore.data.map { it[KEY_PROFILE_IS_ADMIN] }
    val profileCreatedAt: Flow<String?> = context.dataStore.data.map { it[KEY_PROFILE_CREATED_AT] }

    suspend fun saveProfileCache(userId: String, nickname: String, isAdmin: Boolean, createdAt: String) {
        context.dataStore.edit {
            it[KEY_PROFILE_USER_ID] = userId
            it[KEY_PROFILE_NICKNAME] = nickname
            it[KEY_PROFILE_IS_ADMIN] = isAdmin.toString()
            it[KEY_PROFILE_CREATED_AT] = createdAt
        }
    }

    val autoScreenContext: Flow<Boolean> = context.dataStore.data.map { it[KEY_AUTO_SCREEN_CONTEXT] ?: false }

    suspend fun saveAutoScreenContext(enabled: Boolean) {
        context.dataStore.edit { it[KEY_AUTO_SCREEN_CONTEXT] = enabled }
    }

    suspend fun clearProfileCache() {
        context.dataStore.edit {
            it.remove(KEY_PROFILE_USER_ID)
            it.remove(KEY_PROFILE_NICKNAME)
            it.remove(KEY_PROFILE_IS_ADMIN)
            it.remove(KEY_PROFILE_CREATED_AT)
        }
    }

    suspend fun clearAll() {
        context.dataStore.edit { it.clear() }
    }
}
