import "../../runtime/eltest.el"
// test_json.el - native test suite for runtime/json.el
//
// Covers: json_get (dot-path), typed extractors (int, bool, float),
// json_array_len/get, json_set, json_build_object, json_build_array,
// and json_escape_string.

test "json-get-string" {
    let obj: String = "{\"name\":\"alice\",\"role\":\"admin\"}"
    let name: String = json_get(obj, "name")
    assert name == "alice", "get string field name"
    let role: String = json_get(obj, "role")
    assert role == "admin", "get string field role"
    let missing: String = json_get(obj, "xyz")
    assert missing == "", "missing key returns empty string"
}

test "json-get-int" {
    let obj: String = "{\"count\":42,\"offset\":0}"
    let count: Int = json_get_int(obj, "count")
    assert count == 42, "get int field count"
    let offset: Int = json_get_int(obj, "offset")
    assert offset == 0, "get int field offset = 0"
}

test "json-get-bool" {
    let obj: String = "{\"active\":true,\"deleted\":false}"
    let active: Bool = json_get_bool(obj, "active")
    assert active, "get bool true"
    let deleted: Bool = json_get_bool(obj, "deleted")
    assert !deleted, "get bool false"
}

test "json-dot-path" {
    let obj: String = "{\"user\":{\"name\":\"bob\",\"age\":30}}"
    let name: String = json_get(obj, "user.name")
    assert name == "bob", "dot-path traversal user.name"
    let age: String = json_get(obj, "user.age")
    assert age == "30", "dot-path traversal user.age"
}

test "json-array-len" {
    let arr: String = "[\"a\",\"b\",\"c\"]"
    let n: Int = json_array_len(arr)
    assert n == 3, "array length 3"
    let empty_arr: String = "[]"
    let m: Int = json_array_len(empty_arr)
    assert m == 0, "empty array length 0"
}

test "json-array-get" {
    let arr: String = "[\"foo\",\"bar\",\"baz\"]"
    let first: String = json_array_get_string(arr, 0)
    assert first == "foo", "first element"
    let second: String = json_array_get_string(arr, 1)
    assert second == "bar", "second element"
    let third: String = json_array_get_string(arr, 2)
    assert third == "baz", "third element"
}

test "json-get-raw" {
    let obj: String = "{\"items\":[1,2,3],\"meta\":{\"page\":1}}"
    let raw_arr: String = json_get_raw(obj, "items")
    let arr_len: Int = json_array_len(raw_arr)
    assert arr_len == 3, "raw array has 3 elements"
    let raw_meta: String = json_get_raw(obj, "meta")
    let page: String = json_get(raw_meta, "page")
    assert page == "1", "page from nested raw object"
}

test "json-set" {
    let obj: String = "{\"name\":\"alice\"}"
    let updated: String = json_set(obj, "name", "\"bob\"")
    let name: String = json_get(updated, "name")
    assert name == "bob", "set replaces existing key"
}

test "json-build-object" {
    let kvs: [String] = native_list_empty()
    let kvs = native_list_append(kvs, "name")
    let kvs = native_list_append(kvs, "alice")
    let kvs = native_list_append(kvs, "role")
    let kvs = native_list_append(kvs, "admin")
    let obj: String = json_build_object(kvs)
    let name: String = json_get(obj, "name")
    let role: String = json_get(obj, "role")
    assert name == "alice", "built object name field"
    assert role == "admin", "built object role field"
}

test "json-build-array" {
    let items: [String] = native_list_empty()
    let items = native_list_append(items, "\"alpha\"")
    let items = native_list_append(items, "\"beta\"")
    let items = native_list_append(items, "\"gamma\"")
    let arr: String = json_build_array(items)
    let n: Int = json_array_len(arr)
    assert n == 3, "built array has 3 elements"
    let first: String = json_array_get_string(arr, 0)
    assert first == "alpha", "first built element"
    let third: String = json_array_get_string(arr, 2)
    assert third == "gamma", "third built element"
}

test "json-escape-string" {
    let escaped: String = json_escape_string("say \"hello\"")
    assert str_contains(escaped, "\\\""), "double quotes are escaped"
    let tab_esc: String = json_escape_string("a\tb")
    assert str_contains(tab_esc, "\\t"), "tabs are escaped"
    let plain: String = json_escape_string("no special chars")
    assert plain == "no special chars", "plain string unchanged"
}

test "json-get-float" {
    let obj: String = "{\"price\":9.99,\"tax\":0.0}"
    let price: Float = json_get_float(obj, "price")
    let diff: Float = price - 9.99
    assert diff > -0.001, "price close to 9.99 low"
    assert diff < 0.001, "price close to 9.99 high"
    let tax: Float = json_get_float(obj, "tax")
    assert tax == 0.0, "tax is zero"
}

test "json-nested-array-index" {
    let obj: String = "{\"tags\":[\"go\",\"el\",\"rust\"]}"
    let tags_raw: String = json_get_raw(obj, "tags")
    let count: Int = json_array_len(tags_raw)
    assert count == 3, "tags array has 3 elements"
    let first_tag: String = json_array_get_string(tags_raw, 0)
    assert first_tag == "go", "first tag is go"
    let last_tag: String = json_array_get_string(tags_raw, 2)
    assert last_tag == "rust", "last tag is rust"
}
