package com.centralcloud.oncall.sms

import android.content.Context
import android.util.Log
import com.centralcloud.oncall.BuildConfig
import com.centralcloud.oncall.util.HttpUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.json.JSONObject

/**
 * Fetches the centralcloud-ops remote config for this device and applies
 * any SMS-relay settings to [SmsRelayPreferences].
 *
 * Called once on app start (from MainActivity.onCreate). If the device has
 * no device_id configured yet the fetch is skipped — nothing to authenticate
 * with. Config is also re-applied on every successful heartbeat cycle
 * (DeviceHeartbeatWorker) so it stays fresh without an explicit call here.
 *
 *   GET {opsUrl}/api/android/config
 *   X-Device-Id: <token>
 *
 *   Response (relevant fields):
 *   {
 *     "ops_url": "https://ops.centralcloud.com",
 *     "native_push": {
 *       "enabled": true,
 *       "topic": "hugo-centralcloud-com",
 *       "stream_url": "https://ops.centralcloud.com/api/push/hugo-centralcloud-com/stream",
 *       "messages_url": "https://ops.centralcloud.com/api/push/hugo-centralcloud-com/messages"
 *     },
 *     "sms_relay": {
 *       "enabled": true,
 *       "whitelist": ["+46701234567", "BANKID"]
 *     }
 *   }
 */
object RemoteConfigFetcher {

    private const val TAG = "RemoteConfigFetcher"

    /**
     * Fetches remote config and applies it.
     * Returns true if the fetch succeeded, false on any error.
     * Must be called from a coroutine — suspends on IO.
     */
    suspend fun fetchAndApply(context: Context): Boolean = withContext(Dispatchers.IO) {
        val prefs = SmsRelayPreferences(context)
        val deviceId = prefs.deviceId
        if (deviceId.isBlank()) {
            Log.d(TAG, "skip: device_id not set yet")
            return@withContext false
        }

        val baseUrl = prefs.baseUrl.ifBlank { BuildConfig.ONCALL_CONFIG_URL.substringBeforeLast("/api") }
        val url = "${baseUrl.trimEnd('/')}/api/android/config"

        return@withContext try {
            val client = HttpUtil.defaultClient(context, baseUrl)
            val request = HttpUtil.requestBuilder(url)
                .addHeader("X-Device-Id", deviceId)
                .get()
                .build()

            client.newCall(request).execute().use { response ->
                if (!response.isSuccessful) {
                    Log.w(TAG, "config fetch failed: ${response.code}")
                    return@use false
                }
                val body = response.body?.string() ?: return@use false
                apply(context, prefs, JSONObject(body))
                true
            }
        } catch (t: Throwable) {
            Log.w(TAG, "config fetch error", t)
            false
        }
    }

    private fun apply(context: Context, prefs: SmsRelayPreferences, json: JSONObject) {
        // Persist ops_url as the base URL for heartbeats and SMS forwarding.
        json.optString("ops_url").takeIf { it.isNotBlank() }?.let { opsUrl ->
            if (prefs.baseUrl != opsUrl) {
                prefs.baseUrl = opsUrl
                Log.d(TAG, "updated baseUrl=$opsUrl")
            }
        }

        json.optJSONObject("native_push")?.let { nativePush ->
            val enabled = nativePush.optBoolean("enabled", false)
            val topic = nativePush.optString("topic")
            val streamUrl = nativePush.optString("stream_url")
            val messagesUrl = nativePush.optString("messages_url")

            prefs.nativePushEnabled = enabled
            prefs.nativePushTopic = topic
            prefs.nativePushStreamUrl = streamUrl
            prefs.nativePushMessagesUrl = messagesUrl

            if (enabled && topic.isNotBlank() && (streamUrl.isNotBlank() || messagesUrl.isNotBlank())) {
                OpsPushWorker.schedule(context)
                OpsPushWorker.enqueueOnce(context)
            } else {
                OpsPushWorker.cancel(context)
            }

            Log.d(TAG, "applied native_push: enabled=$enabled topic=$topic")
        }

        val smsRelay = json.optJSONObject("sms_relay") ?: return
        val enabled = smsRelay.optBoolean("enabled", false)
        val whitelist = smsRelay.optJSONArray("whitelist")
            ?.let { arr -> (0 until arr.length()).map { arr.getString(it) }.toSet() }
            ?: emptySet()

        prefs.enabled = enabled
        prefs.whitelist = whitelist

        Log.d(TAG, "applied sms_relay: enabled=$enabled whitelist_size=${whitelist.size}")
    }
}
