#!/usr/bin/env herodo
// 03_container_builder.rhai
// Tests for Nerdctl Container Builder pattern

// Custom assert function
fn assert_true(condition, message) {
    if !condition {
        print(`ASSERTION FAILED: ${message}`);
        throw message;
    }
}

// Custom assert_eq function
fn assert_eq(actual, expected, message) {
    if actual != expected {
        print(`ASSERTION FAILED: ${message}`);
        print(`Expected: "${expected}"`);
        print(`Actual: "${actual}"`);
        throw message;
    }
}

// Helper function to check if nerdctl is available
fn is_nerdctl_available() {
    try {
        let result = run("which nerdctl");
        return result.success;
    } catch(err) {
        return false;
    }
}

// Helper function to check if a container exists
fn container_exists(container_name) {
    try {
        let result = run(`nerdctl ps -a --format "{{.Names}}" | grep -w ${container_name}`);
        return result.success;
    } catch(err) {
        return false;
    }
}

// Helper function to clean up a container if it exists
fn cleanup_container(container_name) {
    if container_exists(container_name) {
        try {
            run(`nerdctl stop ${container_name}`);
            run(`nerdctl rm ${container_name}`);
            print(`Cleaned up container: ${container_name}`);
        } catch(err) {
            print(`Error cleaning up container ${container_name}: ${err}`);
        }
    }
}

print("=== Testing Nerdctl Container Builder Pattern ===");

// Check if nerdctl is available
let nerdctl_available = is_nerdctl_available();
if !nerdctl_available {
    print("nerdctl is not available. Skipping Nerdctl tests.");
    // Exit gracefully without error
    return;
}

print("✓ nerdctl is available");

// Define test container name
let container_name = "rhai_test_builder";

// Clean up any existing test container
cleanup_container(container_name);

// Create test directories
let work_dir = "rhai_test_nerdctl_work";
let config_dir = "rhai_test_nerdctl_config";
mkdir(work_dir);
mkdir(config_dir);

try {
    // Test creating a container from an image with builder pattern
    print("Testing nerdctl_container_from_image() with builder pattern...");
    
    // Create a container with a rich set of options using the builder pattern
    let container = nerdctl_container_from_image(container_name, "alpine:latest")
        .reset()  // Reset to default configuration
        .with_detach(true)
        .with_ports(["8080:80", "9090:90"])
        .with_volumes([`${work_dir}:/data`, `${config_dir}:/config`])
        .with_envs(#{
            "ENV1": "value1",
            "ENV2": "value2",
            "TEST_MODE": "true"
        })
        .with_network("bridge")
        .with_cpu_limit("0.5")
        .with_memory_limit("256m");
    
    // Verify container properties
    assert_eq(container.name, container_name, "Container name should match");
    assert_eq(container.image, "alpine:latest", "Container image should match");
    assert_true(container.detach, "Container detach mode should be true");
    
    // Run the container
    print("Testing run() with builder pattern...");
    let run_result = container.run();
    assert_true(run_result.success, "Container run should succeed");
    assert_true(container.container_id != "", "Container ID should not be empty after run");
    print(`✓ run(): Container started with ID: ${container.container_id}`);
    
    // Test environment variables
    print("Testing environment variables...");
    let env_result = container.exec("env");
    assert_true(env_result.success, "Container exec should succeed");
    assert_true(env_result.stdout.contains("ENV1=value1"), "Environment variable ENV1 should be set");
    assert_true(env_result.stdout.contains("ENV2=value2"), "Environment variable ENV2 should be set");
    assert_true(env_result.stdout.contains("TEST_MODE=true"), "Environment variable TEST_MODE should be set");
    print("✓ Environment variables set correctly");
    
    // Test volume mounts
    print("Testing volume mounts...");
    
    // Create a test file in the work directory
    file_write(`${work_dir}/test.txt`, "Hello from host");
    
    // Check if the file is accessible in the container
    let volume_result = container.exec("cat /data/test.txt");
    assert_true(volume_result.success, "Container exec should succeed");
    assert_true(volume_result.stdout.contains("Hello from host"), "Volume mount should work correctly");
    print("✓ Volume mounts working correctly");
    
    // Test writing from container to volume
    print("Testing writing from container to volume...");
    let write_result = container.exec("echo 'Hello from container' > /config/container.txt");
    assert_true(write_result.success, "Container exec should succeed");
    
    // Check if the file was created on the host
    let host_file_content = file_read(`${config_dir}/container.txt`);
    assert_true(host_file_content.contains("Hello from container"), "Container should be able to write to volume");
    print("✓ Container can write to volume");
    
    // Test stopping the container
    print("Testing stop()...");
    let stop_result = container.stop();
    assert_true(stop_result.success, "Container stop should succeed");
    print("✓ stop(): Container stopped successfully");
    
    // Test removing the container
    print("Testing remove()...");
    let remove_result = container.remove();
    assert_true(remove_result.success, "Container remove should succeed");
    print("✓ remove(): Container removed successfully");
    
    print("All container builder pattern tests completed successfully!");
    
    // Clean up test directories
    delete(work_dir);
    delete(config_dir);
    print("✓ Cleanup: Test directories removed");
} catch(err) {
    print(`Error: ${err}`);
    
    // Clean up in case of error
    cleanup_container(container_name);
    
    // Clean up test directories
    delete(work_dir);
    delete(config_dir);
    print("✓ Cleanup: Test directories removed");
    
    throw err;
}
