use gonidium::{Backend, PythonBackend, lower, parse_dsl};

#[test]
fn python_codegen_basic() {
    let src = r#"
    |a: f64, b: f64|
    a * b + 1
    "#;
    let func = parse_dsl(src).expect("parse");
    let dag = lower(&func).expect("lower").dag;
    let backend = PythonBackend;
    let code = backend.emit_kernel(&dag, "kernel");
    assert!(code.contains("import math"));
    assert!(code.contains("def kernel(a, b):"));
    assert!(code.contains("return"));
}

/// Python codegen must emit float('inf') / float('nan') for special float constants.
#[test]
fn python_codegen_special_float_constants() {
    use gonidium::ir::{Const, DType, Node, NodeId, TypedDag};
    let dag = TypedDag::try_new(
        vec![
            Node::Const(Const::Float(f64::INFINITY)),
            Node::Const(Const::Float(f64::NAN)),
            Node::Const(Const::Float(f64::NEG_INFINITY)),
        ],
        vec![DType::F64, DType::F64, DType::F64],
        vec![],
        vec![NodeId(0), NodeId(1), NodeId(2)],
    )
    .expect("well-formed test dag");
    let backend = PythonBackend;
    let code = backend.emit_kernel(&dag, "kernel");
    assert!(
        code.contains("float('inf')"),
        "expected float('inf') in:\n{code}"
    );
    assert!(
        code.contains("float('nan')"),
        "expected float('nan') in:\n{code}"
    );
    assert!(
        code.contains("float('-inf')"),
        "expected float('-inf') in:\n{code}"
    );
}

#[test]
fn python_codegen_floor_ceil_calls() {
    let src = r#"
    |x: f64|
    ceil(floor(x) + 0.1)
    "#;
    let func = parse_dsl(src).expect("parse");
    let dag = lower(&func).expect("lower").dag;
    let backend = PythonBackend;
    let code = backend.emit_kernel(&dag, "kernel");
    assert!(code.contains("float(math.floor"));
    assert!(code.contains("float(math.ceil"));
}
