#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
use runmat_builtins::{IntValue, Tensor, Value};

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_scalar_variants_arithmetic() {
    let i8v = Value::Int(IntValue::I8(5));
    let i16v = Value::Int(IntValue::I16(-2));
    let u32v = Value::Int(IntValue::U32(7));
    let u64v = Value::Int(IntValue::U64(3));
    assert_eq!(
        runmat_runtime::call_builtin("plus", &[i8v.clone(), i16v.clone()]).unwrap(),
        Value::Num(3.0)
    );
    assert_eq!(
        runmat_runtime::call_builtin("minus", &[u32v.clone(), u64v.clone()]).unwrap(),
        Value::Num(4.0)
    );
    assert_eq!(
        runmat_runtime::call_builtin("times", &[i8v.clone(), u32v.clone()]).unwrap(),
        Value::Num(35.0)
    );
    assert_eq!(
        runmat_runtime::call_builtin("rdivide", &[u32v.clone(), i16v.clone()]).unwrap(),
        Value::Num(7.0 / (-2.0))
    );
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_promotion_with_double() {
    let i = Value::Int(IntValue::I32(4));
    let d = Value::Num(2.5);
    assert_eq!(
        runmat_runtime::call_builtin("plus", &[i.clone(), d.clone()]).unwrap(),
        Value::Num(6.5)
    );
    assert_eq!(
        runmat_runtime::call_builtin("times", &[d.clone(), i.clone()]).unwrap(),
        Value::Num(10.0)
    );
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn integer_class_and_string() {
    let i = Value::Int(IntValue::U16(42));
    let cls = runmat_runtime::call_builtin("class", [i.clone()].as_slice()).unwrap();
    if let Value::String(s) = cls {
        assert_eq!(s, "uint16");
    } else {
        panic!();
    }
    let s = runmat_runtime::call_builtin("string", [i].as_slice()).unwrap();
    if let Value::StringArray(sa) = s {
        assert_eq!(sa.data[0], "42");
    } else {
        panic!();
    }
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn uint16_builtin_dispatches_and_casts_array() {
    let input = Value::Tensor(Tensor::new(vec![3.49, -2.0, 70000.0], vec![1, 3]).unwrap());
    let output = runmat_runtime::call_builtin("uint16", &[input]).expect("uint16 builtin");
    match output {
        Value::Tensor(tensor) => {
            assert_eq!(tensor.shape, vec![1, 3]);
            assert_eq!(tensor.data, vec![3.0, 0.0, u16::MAX as f64]);
        }
        other => panic!("expected tensor output, got {other:?}"),
    }
}
