package com.nexlab.openclaw.node.data.repository

import android.content.Context
import android.util.Log
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.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton

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

@Singleton
class SettingsRepository(
    private val context: Context
) {
    companion object {
        private val GATEWAY_PROTOCOL = stringPreferencesKey("gateway_protocol")
        private val GATEWAY_IP = stringPreferencesKey("gateway_ip")
        private val GATEWAY_PORT = stringPreferencesKey("gateway_port")
        private val NODE_TOKEN = stringPreferencesKey("node_token")
        private val NODE_ID = stringPreferencesKey("node_id")
        private val AUTO_CONNECT = booleanPreferencesKey("auto_connect")
        private val NOTIFICATIONS_ENABLED = booleanPreferencesKey("notifications_enabled")
        private val SCREENSHOT_QUALITY = intPreferencesKey("screenshot_quality")
    }

    // SharedPreferences for NodeService - read directly
    private fun getSharedPrefs() = context.getSharedPreferences("openclaw_settings", Context.MODE_PRIVATE)
    
    private fun getSharedPrefString(key: String, default: String = "") = 
        getSharedPrefs().getString(key, default) ?: default

    // Read from SharedPreferences first (which NodeService uses), fallback to DataStore
    val gatewayProtocol: Flow<String> = context.dataStore.data.map { preferences ->
        val prefsValue = getSharedPrefString("gateway_protocol")
        if (prefsValue.isNotEmpty()) prefsValue
        else preferences[GATEWAY_PROTOCOL] ?: "WS"
    }

    val gatewayIp: Flow<String> = context.dataStore.data.map { preferences ->
        val prefsValue = getSharedPrefString("gateway_ip")
        if (prefsValue.isNotEmpty()) prefsValue
        else preferences[GATEWAY_IP] ?: ""
    }

    val gatewayPort: Flow<String> = context.dataStore.data.map { preferences ->
        val prefsValue = getSharedPrefString("gateway_port")
        if (prefsValue.isNotEmpty()) prefsValue
        else preferences[GATEWAY_PORT] ?: "18789"
    }

    val gatewayUrl: Flow<String> = context.dataStore.data.map { preferences ->
        val protocol = getSharedPrefString("gateway_protocol", "WS")
        val ip = getSharedPrefString("gateway_ip")
        val port = getSharedPrefString("gateway_port", "18789")
        if (ip.isNotEmpty()) {
            val wsProtocol = if (protocol == "WSS") "wss" else "ws"
            "$wsProtocol://$ip:$port"
        } else {
            preferences[GATEWAY_IP] ?: ""
        }
    }

    val nodeToken: Flow<String> = context.dataStore.data.map { preferences ->
        val prefsValue = getSharedPrefString("node_token")
        if (prefsValue.isNotEmpty()) prefsValue
        else preferences[NODE_TOKEN] ?: ""
    }

    val nodeId: Flow<String> = context.dataStore.data.map { preferences ->
        val prefsValue = getSharedPrefString("node_id")
        if (prefsValue.isNotEmpty()) prefsValue
        else preferences[NODE_ID] ?: "android-node"
    }

    val autoConnect: Flow<Boolean> = context.dataStore.data.map { preferences ->
        preferences[AUTO_CONNECT] ?: false
    }

    val notificationsEnabled: Flow<Boolean> = context.dataStore.data.map { preferences ->
        preferences[NOTIFICATIONS_ENABLED] ?: true
    }

    val screenshotQuality: Flow<Int> = context.dataStore.data.map { preferences ->
        preferences[SCREENSHOT_QUALITY] ?: 80
    }

    suspend fun setGatewayProtocol(protocol: String) {
        context.dataStore.edit { preferences ->
            preferences[GATEWAY_PROTOCOL] = protocol
        }
        // Also save to SharedPreferences for NodeService
        saveDirectToSharedPreferences("gateway_protocol", protocol)
    }

    suspend fun setGatewayIp(ip: String) {
        context.dataStore.edit { preferences ->
            preferences[GATEWAY_IP] = ip
        }
        // Also save to SharedPreferences for NodeService
        saveDirectToSharedPreferences("gateway_ip", ip)
    }

    suspend fun setGatewayPort(port: String) {
        context.dataStore.edit { preferences ->
            preferences[GATEWAY_PORT] = port
        }
        // Also save to SharedPreferences for NodeService
        saveDirectToSharedPreferences("gateway_port", port)
    }

    suspend fun setNodeToken(token: String) {
        context.dataStore.edit { preferences ->
            preferences[NODE_TOKEN] = token
        }
        // Also save to SharedPreferences for NodeService
        saveDirectToSharedPreferences("node_token", token)
    }

    suspend fun setNodeId(id: String) {
        context.dataStore.edit { preferences ->
            preferences[NODE_ID] = id
        }
        // Also save to SharedPreferences for NodeService
        saveDirectToSharedPreferences("node_id", id)
    }

    suspend fun setAutoConnect(enabled: Boolean) {
        context.dataStore.edit { preferences ->
            preferences[AUTO_CONNECT] = enabled
        }
    }

    suspend fun setNotificationsEnabled(enabled: Boolean) {
        context.dataStore.edit { preferences ->
            preferences[NOTIFICATIONS_ENABLED] = enabled
        }
    }

    suspend fun setScreenshotQuality(quality: Int) {
        context.dataStore.edit { preferences ->
            preferences[SCREENSHOT_QUALITY] = quality
        }
    }

    // Save a single setting directly to SharedPreferences
    private fun saveDirectToSharedPreferences(key: String, value: String) {
        try {
            val prefs = context.getSharedPreferences("openclaw_settings", Context.MODE_PRIVATE)
            prefs.edit().putString(key, value).apply()
            Log.d("SettingsRepo", "Saved to SharedPreferences: $key=$value")
        } catch (e: Exception) {
            Log.e("SettingsRepo", "Failed to save to SharedPreferences: ${e.message}")
        }
    }
}
