use crate::value::Value;
use hamelin_lib::tree::builder::{boolean, double, int, null, string};

use super::test_helpers::TestContext;

#[test]
fn test_eval_int_literal() {
    let ctx = TestContext::new();

    let expr = int(42);
    let result = ctx.eval_expr(&expr);

    assert_eq!(result, Value::Int(42));
}

#[test]
fn test_eval_string_literal() {
    let ctx = TestContext::new();

    let expr = string("hello");
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::String("hello".to_string()));
}

#[test]
fn test_eval_boolean_literal() {
    let ctx = TestContext::new();

    // Test true literal
    let expr = boolean(true);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Boolean(true));

    // Test false literal
    let expr = boolean(false);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Boolean(false));
}

#[test]
fn test_eval_double_literal() {
    let ctx = TestContext::new();

    let expr = double(3.14159);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Double(3.14159));
}

#[test]
fn test_eval_null_literal() {
    let ctx = TestContext::new();

    let expr = null();
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Null);
    assert!(result.is_null());
}

#[test]
fn test_eval_various_int_literals() {
    let ctx = TestContext::new();

    // Test zero
    let expr = int(0);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Int(0));

    // Test negative number
    let expr = int(-42);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Int(-42));

    // Test large positive number
    let expr = int(2147483647);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Int(2147483647));

    // Test large negative number
    let expr = int(-2147483648);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Int(-2147483648));
}

#[test]
fn test_eval_various_double_literals() {
    let ctx = TestContext::new();

    // Test zero as double
    let expr = double(0.0);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Double(0.0));

    // Test negative double
    let expr = double(-3.14159);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Double(-3.14159));

    // Test very small positive double
    let expr = double(0.000001);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Double(0.000001));

    // Test very large double
    let expr = double(1e10);
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::Double(1e10));
}

#[test]
fn test_eval_various_string_literals() {
    let ctx = TestContext::new();

    // Test empty string
    let expr = string("");
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::String("".to_string()));

    // Test string with spaces
    let expr = string("hello world");
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::String("hello world".to_string()));

    // Test string with special characters
    let expr = string("Hello, 世界! 🌍");
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::String("Hello, 世界! 🌍".to_string()));

    // Test string with escape sequences (if supported)
    let expr = string("line1\nline2\tindented");
    let result = ctx.eval_expr(&expr);
    assert_eq!(result, Value::String("line1\nline2\tindented".to_string()));
}
