package ai.openclaw.android.node

import android.content.Context
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.double
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment

@RunWith(RobolectricTestRunner::class)
class DeviceHandlerTest {
  @Test
  fun handleDeviceInfo_returnsStablePayload() {
    val handler = DeviceHandler(appContext())

    val result = handler.handleDeviceInfo(null)

    assertTrue(result.ok)
    val payload = parsePayload(result.payloadJson)
    assertEquals("Android", payload.getValue("systemName").jsonPrimitive.content)
    assertTrue(payload.getValue("deviceName").jsonPrimitive.content.isNotBlank())
    assertTrue(payload.getValue("modelIdentifier").jsonPrimitive.content.isNotBlank())
    assertTrue(payload.getValue("systemVersion").jsonPrimitive.content.isNotBlank())
    assertTrue(payload.getValue("appVersion").jsonPrimitive.content.isNotBlank())
    assertTrue(payload.getValue("appBuild").jsonPrimitive.content.isNotBlank())
    assertTrue(payload.getValue("locale").jsonPrimitive.content.isNotBlank())
  }

  @Test
  fun handleDeviceStatus_returnsExpectedShape() {
    val handler = DeviceHandler(appContext())

    val result = handler.handleDeviceStatus(null)

    assertTrue(result.ok)
    val payload = parsePayload(result.payloadJson)
    val battery = payload.getValue("battery").jsonObject
    val storage = payload.getValue("storage").jsonObject
    val thermal = payload.getValue("thermal").jsonObject
    val network = payload.getValue("network").jsonObject

    val state = battery.getValue("state").jsonPrimitive.content
    assertTrue(state in setOf("unknown", "unplugged", "charging", "full"))
    battery["level"]?.jsonPrimitive?.double?.let { level ->
      assertTrue(level in 0.0..1.0)
    }
    battery.getValue("lowPowerModeEnabled").jsonPrimitive.boolean

    val totalBytes = storage.getValue("totalBytes").jsonPrimitive.content.toLong()
    val freeBytes = storage.getValue("freeBytes").jsonPrimitive.content.toLong()
    val usedBytes = storage.getValue("usedBytes").jsonPrimitive.content.toLong()
    assertTrue(totalBytes >= 0L)
    assertTrue(freeBytes >= 0L)
    assertTrue(usedBytes >= 0L)
    assertEquals((totalBytes - freeBytes).coerceAtLeast(0L), usedBytes)

    val thermalState = thermal.getValue("state").jsonPrimitive.content
    assertTrue(thermalState in setOf("nominal", "fair", "serious", "critical"))

    val networkStatus = network.getValue("status").jsonPrimitive.content
    assertTrue(networkStatus in setOf("satisfied", "unsatisfied", "requiresConnection"))
    val interfaces = network.getValue("interfaces").jsonArray.map { it.jsonPrimitive.content }
    assertTrue(interfaces.all { it in setOf("wifi", "cellular", "wired", "other") })

    assertTrue(payload.getValue("uptimeSeconds").jsonPrimitive.double >= 0.0)
  }

  private fun appContext(): Context = RuntimeEnvironment.getApplication()

  private fun parsePayload(payloadJson: String?): JsonObject {
    val jsonString = payloadJson ?: error("expected payload")
    return Json.parseToJsonElement(jsonString).jsonObject
  }
}
