use rok_utils::arr::{
    chunk, compact, contains, every, filter, find, first, flatten, get, last, map, reduce, reverse,
    skip, some, take, unique,
};

#[test]
fn array_map() {
    let numbers = [1, 2, 3, 4, 5];
    let result = map(&numbers, |x| x * 2);
    assert_eq!(result, [2, 4, 6, 8, 10]);

    let strings = ["a", "b", "c"];
    let result = map(&strings, |s| s.to_uppercase());
    assert_eq!(result, ["A", "B", "C"]);
}

#[test]
fn array_filter() {
    let numbers = [1, 2, 3, 4, 5];
    let result = filter(&numbers, |x| x % 2 == 0);
    assert_eq!(result, [2, 4]);

    let strings = ["hello", "world", "rust"];
    let result = filter(&strings, |s| s.len() > 4);
    assert_eq!(result, ["hello", "world"]);
}

#[test]
fn array_reduce() {
    let numbers = [1, 2, 3, 4, 5];
    let sum = reduce(&numbers, 0, |acc, x| acc + x);
    assert_eq!(sum, 15);

    let product = reduce(&numbers, 1, |acc, x| acc * x);
    assert_eq!(product, 120);
}

#[test]
fn array_chunk() {
    let numbers = [1, 2, 3, 4, 5, 6];
    let result = chunk(&numbers, 2);
    assert_eq!(result, [[1, 2], [3, 4], [5, 6]]);

    let numbers = [1, 2, 3, 4, 5];
    let result = chunk(&numbers, 2);
    assert_eq!(result.len(), 3);
}

#[test]
fn array_unique() {
    let items = [1, 2, 2, 3, 3, 3, 4];
    let result = unique(&items);
    assert_eq!(result, [1, 2, 3, 4]);

    let strings = ["a", "b", "a", "c"];
    let result = unique(&strings);
    assert_eq!(result, ["a", "b", "c"]);
}

#[test]
fn array_contains() {
    let numbers = [1, 2, 3, 4, 5];
    assert!(contains(&numbers, &3));
    assert!(!contains(&numbers, &6));

    let strings = ["hello", "world"];
    assert!(contains(&strings, &"hello"));
    assert!(!contains(&strings, &"rust"));
}

#[test]
fn array_first_last() {
    let numbers = [1, 2, 3, 4, 5];
    assert_eq!(first(&numbers), Some(&1));
    assert_eq!(last(&numbers), Some(&5));

    let empty: [i32; 0] = [];
    assert_eq!(first(&empty), None);
    assert_eq!(last(&empty), None);
}

#[test]
fn array_get() {
    let numbers = [10, 20, 30, 40, 50];
    assert_eq!(get(&numbers, 0), Some(&10));
    assert_eq!(get(&numbers, 2), Some(&30));
    assert_eq!(get(&numbers, 10), None);
}

#[test]
fn array_find() {
    let numbers = [1, 2, 3, 4, 5];
    assert_eq!(find(&numbers, |x| x % 2 == 0), Some(&2));
    assert_eq!(find(&numbers, |x| *x > 10), None);
}

#[test]
fn array_some_every() {
    let numbers = [1, 2, 3, 4, 5];
    assert!(some(&numbers, |x| x % 2 == 0));
    assert!(!some(&numbers, |x| *x > 10));

    assert!(every(&numbers, |x| *x > 0));
    assert!(!every(&numbers, |x| x % 2 == 0));
}

#[test]
fn array_flatten() {
    let nested: Vec<Vec<i32>> = vec![vec![1, 2], vec![3, 4], vec![5, 0]];
    let result = flatten(&nested);
    assert_eq!(result, [1, 2, 3, 4, 5, 0]);
}

#[test]
fn array_compact() {
    let items = [1, 0, 3, 0, 5];
    let result = compact(&items);
    assert_eq!(result, [1, 3, 5]);

    let strings = ["hello", "", "world", ""];
    let result = compact(&strings);
    assert_eq!(result, ["hello", "world"]);
}

#[test]
fn array_take_skip() {
    let numbers = [1, 2, 3, 4, 5];
    let result = take(&numbers, 3);
    assert_eq!(result, [1, 2, 3]);

    let result = skip(&numbers, 2);
    assert_eq!(result, [3, 4, 5]);
}

#[test]
fn array_reverse() {
    let numbers = [1, 2, 3, 4, 5];
    let result = reverse(&numbers);
    assert_eq!(result, [5, 4, 3, 2, 1]);
}

#[cfg(feature = "random")]
use rok_utils::shuffle;

#[cfg(feature = "random")]
#[test]
fn array_shuffle() {
    let numbers = [1, 2, 3, 4, 5];
    let result = shuffle(&numbers);
    assert_eq!(result.len(), 5);
    assert!(result.iter().all(|x| numbers.contains(x)));
}
