use rhai::Engine;
use sal_process::rhai::register_process_module;

fn create_test_engine() -> Engine {
    let mut engine = Engine::new();
    register_process_module(&mut engine).unwrap();
    engine
}

#[test]
fn test_rhai_run_command() {
    let engine = create_test_engine();

    let script = r#"
        let result = run_command("echo hello");
        result.success && result.stdout.contains("hello")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_run_silent() {
    let engine = create_test_engine();

    let script = r#"
        let result = run_silent("echo silent test");
        result.success && result.stdout.contains("silent test")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_run_builder_pattern() {
    let engine = create_test_engine();

    let script = r#"
        let result = run("echo builder test").silent().execute();
        result.success && result.stdout.contains("builder test")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_run_builder_ignore_error() {
    let engine = create_test_engine();

    let script = r#"
        let result = run("false").ignore_error().silent().execute();
        !result.success
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_run_builder_with_log() {
    let engine = create_test_engine();

    let script = r#"
        let result = run("echo log test").log().silent().execute();
        result.success && result.stdout.contains("log test")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_which_function() {
    let engine = create_test_engine();

    // Test with a command that should exist
    #[cfg(target_os = "windows")]
    let script = r#"
        let path = which("cmd");
        path != () && path.len() > 0
    "#;

    #[cfg(not(target_os = "windows"))]
    let script = r#"
        let path = which("sh");
        path != () && path.len() > 0
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_which_nonexistent() {
    let engine = create_test_engine();

    let script = r#"
        let path = which("nonexistent_command_12345");
        path == ()
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_process_list() {
    let engine = create_test_engine();

    let script = r#"
        let processes = process_list("");
        processes.len() > 0
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_process_list_with_pattern() {
    let engine = create_test_engine();

    let script = r#"
        let all_processes = process_list("");
        if all_processes.len() > 0 {
            let first_process = all_processes[0];
            let filtered = process_list(first_process.name);
            filtered.len() >= 1
        } else {
            false
        }
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_process_info_properties() {
    let engine = create_test_engine();

    let script = r#"
        let processes = process_list("");
        if processes.len() > 0 {
            let process = processes[0];
            process.pid > 0 && process.name.len() > 0
        } else {
            false
        }
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_command_result_properties() {
    let engine = create_test_engine();

    let script = r#"
        let result = run_command("echo test");
        result.success && result.stdout.contains("test")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_kill_nonexistent() {
    let engine = create_test_engine();

    let script = r#"
        let result = kill("nonexistent_process_12345");
        result.contains("No matching processes") || result.contains("Successfully killed")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_run_with_options() {
    let engine = create_test_engine();

    let script = r#"
        let options = #{
            silent: true,
            die: false,
            log: false
        };
        let result = run("echo options test", options);
        result.success && result.stdout.contains("options test")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_run_multiline_script() {
    let engine = create_test_engine();

    let script = r#"
        let bash_script = `
            echo "Line 1"
            echo "Line 2"
            echo "Line 3"
        `;
        let result = run_command(bash_script);
        result.success && 
        result.stdout.contains("Line 1") && 
        result.stdout.contains("Line 2") && 
        result.stdout.contains("Line 3")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_error_handling() {
    let engine = create_test_engine();

    // Test that errors are properly converted to Rhai errors
    let script = r#"
        let error_occurred = false;
        try {
            run_command("nonexistent_command_12345");
        } catch(e) {
            error_occurred = true;
        }
        error_occurred
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_process_get_error_handling() {
    let engine = create_test_engine();

    let script = r#"
        let error_occurred = false;
        try {
            process_get("nonexistent_process_12345");
        } catch(e) {
            error_occurred = true;
        }
        error_occurred
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_builder_chaining() {
    let engine = create_test_engine();

    let script = r#"
        let result = run("echo chaining")
            .silent()
            .ignore_error()
            .log()
            .execute();
        result.success && result.stdout.contains("chaining")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_cross_platform_commands() {
    let engine = create_test_engine();

    // Test platform-specific commands
    #[cfg(target_os = "windows")]
    let script = r#"
        let result = run_command("echo Windows test");
        result.success && result.stdout.contains("Windows test")
    "#;

    #[cfg(not(target_os = "windows"))]
    let script = r#"
        let result = run_command("echo Unix test");
        result.success && result.stdout.contains("Unix test")
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}

#[test]
fn test_rhai_complex_workflow() {
    let engine = create_test_engine();

    let script = r#"
        // Test a complex workflow combining multiple functions
        let echo_path = which("echo");
        if echo_path == () {
            false
        } else {
            let result = run("echo workflow test").silent().execute();
            if !result.success {
                false
            } else {
                let processes = process_list("");
                processes.len() > 0
            }
        }
    "#;

    let result: bool = engine.eval(script).unwrap();
    assert!(result);
}
