// tests/suite/test_collections.el — tests for native list operations
//
// runtime/collections.el does not exist; this file tests the native list
// primitives that are always available in El: el_list_empty, el_list_append,
// el_list_len, el_list_get.
//
// These primitives underpin str_split, str_join, and the env.el list helpers.

// ── el_list_empty ─────────────────────────────────────────────────────────────

fn test_list_empty_basic(_: String) -> String {
    let lst: [String] = el_list_empty()
    assert_int_eq(el_list_len(lst), 0, "empty list has length 0")
    return ""
}

fn test_list_empty_multiple(_: String) -> String {
    let a: [String] = el_list_empty()
    let b: [String] = el_list_empty()
    assert_int_eq(el_list_len(a), 0, "first empty list has length 0")
    assert_int_eq(el_list_len(b), 0, "second empty list has length 0")
    // Append to one does not affect the other
    let a2: [String] = el_list_append(a, "hello")
    assert_int_eq(el_list_len(a2), 1, "appended list has length 1")
    assert_int_eq(el_list_len(b), 0, "other empty list unaffected")
    return ""
}

// ── el_list_append ────────────────────────────────────────────────────────────

fn test_list_append_single(_: String) -> String {
    let lst: [String] = el_list_empty()
    let lst2: [String] = el_list_append(lst, "hello")
    assert_int_eq(el_list_len(lst2), 1, "length is 1 after append")
    assert_eq(el_list_get(lst2, 0), "hello", "first element is what was appended")
    return ""
}

fn test_list_append_multiple(_: String) -> String {
    let lst: [String] = el_list_empty()
    let lst = el_list_append(lst, "alpha")
    let lst = el_list_append(lst, "beta")
    let lst = el_list_append(lst, "gamma")
    assert_int_eq(el_list_len(lst), 3, "length 3 after 3 appends")
    assert_eq(el_list_get(lst, 0), "alpha", "first element: alpha")
    assert_eq(el_list_get(lst, 1), "beta", "second element: beta")
    assert_eq(el_list_get(lst, 2), "gamma", "third element: gamma")
    return ""
}

fn test_list_append_order(_: String) -> String {
    let lst: [String] = el_list_empty()
    let lst = el_list_append(lst, "1")
    let lst = el_list_append(lst, "2")
    let lst = el_list_append(lst, "3")
    let lst = el_list_append(lst, "4")
    let lst = el_list_append(lst, "5")
    assert_int_eq(el_list_len(lst), 5, "five elements appended")
    assert_eq(el_list_get(lst, 0), "1", "order preserved: index 0")
    assert_eq(el_list_get(lst, 2), "3", "order preserved: index 2")
    assert_eq(el_list_get(lst, 4), "5", "order preserved: index 4")
    return ""
}

fn test_list_append_empty_string(_: String) -> String {
    let lst: [String] = el_list_empty()
    let lst = el_list_append(lst, "")
    assert_int_eq(el_list_len(lst), 1, "empty string element counted")
    assert_eq(el_list_get(lst, 0), "", "empty string retrievable")
    return ""
}

// ── el_list_len ───────────────────────────────────────────────────────────────

fn test_list_len_basic(_: String) -> String {
    let lst: [String] = el_list_empty()
    assert_int_eq(el_list_len(lst), 0, "initial length 0")
    let lst = el_list_append(lst, "a")
    assert_int_eq(el_list_len(lst), 1, "length 1 after one append")
    let lst = el_list_append(lst, "b")
    assert_int_eq(el_list_len(lst), 2, "length 2 after two appends")
    let lst = el_list_append(lst, "c")
    assert_int_eq(el_list_len(lst), 3, "length 3 after three appends")
    return ""
}

fn test_list_len_large(_: String) -> String {
    let lst: [String] = el_list_empty()
    let i: Int = 0
    while i < 20 {
        let lst = el_list_append(lst, int_to_str(i))
        let i = i + 1
    }
    assert_int_eq(el_list_len(lst), 20, "length 20 after 20 appends")
    assert_eq(el_list_get(lst, 0), "0", "first element is 0")
    assert_eq(el_list_get(lst, 19), "19", "last element is 19")
    return ""
}

// ── el_list_get ───────────────────────────────────────────────────────────────

fn test_list_get_basic(_: String) -> String {
    let lst: [String] = el_list_empty()
    let lst = el_list_append(lst, "first")
    let lst = el_list_append(lst, "second")
    let lst = el_list_append(lst, "third")
    assert_eq(el_list_get(lst, 0), "first", "get index 0")
    assert_eq(el_list_get(lst, 1), "second", "get index 1")
    assert_eq(el_list_get(lst, 2), "third", "get index 2")
    return ""
}

fn test_list_get_preserves_content(_: String) -> String {
    let lst: [String] = el_list_empty()
    let lst = el_list_append(lst, "hello world")
    let lst = el_list_append(lst, "{\"json\":\"value\"}")
    let lst = el_list_append(lst, "line1\nline2")
    assert_eq(el_list_get(lst, 0), "hello world", "spaces in element preserved")
    assert_eq(el_list_get(lst, 1), "{\"json\":\"value\"}", "JSON string preserved")
    assert_eq(el_list_get(lst, 2), "line1\nline2", "newline in element preserved")
    return ""
}

// ── list with str_join / str_split roundtrip ─────────────────────────────────

fn test_list_split_join_roundtrip(_: String) -> String {
    let original: String = "apple,banana,cherry"
    let parts: [String] = str_split(original, ",")
    assert_int_eq(el_list_len(parts), 3, "split yields 3 parts")
    let rejoined: String = str_join(parts, ",")
    assert_eq(rejoined, original, "split then join is identity")
    return ""
}

fn test_list_build_and_join(_: String) -> String {
    let parts: [String] = el_list_empty()
    let parts = el_list_append(parts, "one")
    let parts = el_list_append(parts, "two")
    let parts = el_list_append(parts, "three")
    let joined: String = str_join(parts, " + ")
    assert_eq(joined, "one + two + three", "join with multi-char separator")
    assert_int_eq(el_list_len(parts), 3, "original list unchanged")
    return ""
}

fn test_list_from_split_access(_: String) -> String {
    let parts: [String] = str_split("a:b:c:d:e", ":")
    assert_int_eq(el_list_len(parts), 5, "split into 5 parts")
    assert_eq(el_list_get(parts, 0), "a", "first part")
    assert_eq(el_list_get(parts, 2), "c", "middle part")
    assert_eq(el_list_get(parts, 4), "e", "last part")
    return ""
}

// ── native_list_empty / native_list_append (aliases from join.el style) ───────

fn test_native_list_empty_basic(_: String) -> String {
    let lst: [String] = native_list_empty()
    assert_int_eq(el_list_len(lst), 0, "native_list_empty yields empty list")
    return ""
}

fn test_native_list_append_basic(_: String) -> String {
    let lst: [String] = native_list_empty()
    let lst = native_list_append(lst, "hello")
    let lst = native_list_append(lst, "world")
    assert_int_eq(el_list_len(lst), 2, "native_list_append: length 2")
    assert_eq(el_list_get(lst, 0), "hello", "native_list_append: first element")
    assert_eq(el_list_get(lst, 1), "world", "native_list_append: second element")
    return ""
}

fn test_native_list_join(_: String) -> String {
    let parts: [String] = native_list_empty()
    let parts = native_list_append(parts, "alpha")
    let parts = native_list_append(parts, "beta")
    let parts = native_list_append(parts, "gamma")
    let result: String = str_join(parts, ", ")
    assert_eq(result, "alpha, beta, gamma", "native list joined correctly")
    return ""
}

// ── env.el list helpers (get / len) ──────────────────────────────────────────

fn test_env_list_helpers(_: String) -> String {
    let lst: [String] = el_list_empty()
    let lst = el_list_append(lst, "x")
    let lst = el_list_append(lst, "y")
    let lst = el_list_append(lst, "z")
    assert_int_eq(len(lst), 3, "len() alias for el_list_len")
    assert_eq(get(lst, 0), "x", "get() alias for el_list_get index 0")
    assert_eq(get(lst, 2), "z", "get() alias for el_list_get index 2")
    return ""
}

// ── list as accumulator pattern ───────────────────────────────────────────────

fn test_list_accumulate_loop(_: String) -> String {
    let results: [String] = el_list_empty()
    let i: Int = 0
    while i < 5 {
        let results = el_list_append(results, int_to_str(i * i))
        let i = i + 1
    }
    assert_int_eq(el_list_len(results), 5, "accumulated 5 squares")
    assert_eq(el_list_get(results, 0), "0", "0^2 = 0")
    assert_eq(el_list_get(results, 1), "1", "1^2 = 1")
    assert_eq(el_list_get(results, 2), "4", "2^2 = 4")
    assert_eq(el_list_get(results, 3), "9", "3^2 = 9")
    assert_eq(el_list_get(results, 4), "16", "4^2 = 16")
    return ""
}

fn test_list_string_building(_: String) -> String {
    let words: [String] = el_list_empty()
    let words = el_list_append(words, "the")
    let words = el_list_append(words, "quick")
    let words = el_list_append(words, "brown")
    let words = el_list_append(words, "fox")
    let sentence: String = str_join(words, " ")
    assert_eq(sentence, "the quick brown fox", "words joined into sentence")
    assert_int_eq(str_count_words(sentence), 4, "sentence has 4 words")
    return ""
}
