//! Integration tests for herodo script executor
//!
//! These tests verify that herodo can execute Rhai scripts correctly,
//! handle errors appropriately, and integrate with SAL modules.

use std::fs;
use std::path::Path;
use tempfile::TempDir;

/// Test that herodo can execute a simple Rhai script
#[test]
fn test_simple_script_execution() {
    let temp_dir = TempDir::new().expect("Failed to create temp directory");
    let script_path = temp_dir.path().join("test.rhai");

    // Create a simple test script
    fs::write(
        &script_path,
        r#"
        print("Hello from herodo test!");
        let result = 42;
        result
    "#,
    )
    .expect("Failed to write test script");

    // Execute the script
    let result = herolib_do::run(script_path.to_str().unwrap());
    assert!(
        result.is_ok(),
        "Script execution should succeed: {:?}",
        result.err()
    );
}

/// Test that herodo can execute multiple scripts in a directory
#[test]
fn test_directory_script_execution() {
    let temp_dir = TempDir::new().expect("Failed to create temp directory");

    // Create multiple test scripts
    fs::write(
        temp_dir.path().join("01_first.rhai"),
        r#"
        print("First script executing");
        let first = 1;
    "#,
    )
    .expect("Failed to write first script");

    fs::write(
        temp_dir.path().join("02_second.rhai"),
        r#"
        print("Second script executing");
        let second = 2;
    "#,
    )
    .expect("Failed to write second script");

    fs::write(
        temp_dir.path().join("03_third.rhai"),
        r#"
        print("Third script executing");
        let third = 3;
    "#,
    )
    .expect("Failed to write third script");

    // Execute all scripts in the directory
    let result = herolib_do::run(temp_dir.path().to_str().unwrap());
    assert!(result.is_ok(), "Directory script execution should succeed");
}

/// Test that herodo handles non-existent paths correctly
#[test]
fn test_nonexistent_path_handling() {
    // This test verifies error handling but herolib_do::run calls process::exit
    // In a real scenario, we would need to refactor herodo to return errors
    // instead of calling process::exit for better testability

    // For now, we test that the path validation logic works
    let nonexistent_path = "/this/path/does/not/exist";
    let path = Path::new(nonexistent_path);
    assert!(!path.exists(), "Test path should not exist");
}

/// Test that herodo can execute scripts with SAL module functions
#[test]
fn test_sal_module_integration() {
    let temp_dir = TempDir::new().expect("Failed to create temp directory");
    let script_path = temp_dir.path().join("sal_test.rhai");

    // Create a script that uses SAL functions
    fs::write(
        &script_path,
        r#"
        print("Testing SAL module integration");

        // Test file existence check (should work with temp directory)
        let temp_exists = exist(".");
        print("Current directory exists: " + temp_exists);

        // Test basic text operations
        let text = "  hello world  ";
        let trimmed = text.trim();
        print("Trimmed text: '" + trimmed + "'");

        print("SAL integration test completed");
    "#,
    )
    .expect("Failed to write SAL test script");

    // Execute the script
    let result = herolib_do::run(script_path.to_str().unwrap());
    assert!(
        result.is_ok(),
        "SAL integration script should execute successfully"
    );
}

/// Test script execution with subdirectories
#[test]
fn test_recursive_directory_execution() {
    let temp_dir = TempDir::new().expect("Failed to create temp directory");

    // Create subdirectory
    let sub_dir = temp_dir.path().join("subdir");
    fs::create_dir(&sub_dir).expect("Failed to create subdirectory");

    // Create scripts in main directory
    fs::write(
        temp_dir.path().join("main.rhai"),
        r#"
        print("Main directory script");
    "#,
    )
    .expect("Failed to write main script");

    // Create scripts in subdirectory
    fs::write(
        sub_dir.join("sub.rhai"),
        r#"
        print("Subdirectory script");
    "#,
    )
    .expect("Failed to write sub script");

    // Execute all scripts recursively
    let result = herolib_do::run(temp_dir.path().to_str().unwrap());
    assert!(
        result.is_ok(),
        "Recursive directory execution should succeed"
    );
}

/// Test that herodo handles empty directories gracefully
#[test]
fn test_empty_directory_handling() {
    let temp_dir = TempDir::new().expect("Failed to create temp directory");

    // Create an empty subdirectory
    let empty_dir = temp_dir.path().join("empty");
    fs::create_dir(&empty_dir).expect("Failed to create empty directory");

    // This should handle the empty directory case
    // Note: herolib_do::run will call process::exit(1) for empty directories
    // In a production refactor, this should return an error instead
    let path = empty_dir.to_str().unwrap();
    let path_obj = Path::new(path);
    assert!(
        path_obj.is_dir(),
        "Empty directory should exist and be a directory"
    );
}

/// Test script with syntax errors
#[test]
fn test_syntax_error_handling() {
    let temp_dir = TempDir::new().expect("Failed to create temp directory");
    let script_path = temp_dir.path().join("syntax_error.rhai");

    // Create a script with syntax errors
    fs::write(
        &script_path,
        r#"
        print("This script has syntax errors");
        let invalid syntax here;
        missing_function_call(;
    "#,
    )
    .expect("Failed to write syntax error script");

    // Note: herolib_do::run will call process::exit(1) on script errors
    // In a production refactor, this should return an error instead
    // For now, we just verify the file exists and can be read
    assert!(script_path.exists(), "Syntax error script should exist");
    let content = fs::read_to_string(&script_path).expect("Should be able to read script");
    assert!(
        content.contains("syntax errors"),
        "Script should contain expected content"
    );
}

/// Test file extension validation
#[test]
fn test_file_extension_validation() {
    let temp_dir = TempDir::new().expect("Failed to create temp directory");

    // Create files with different extensions
    let rhai_file = temp_dir.path().join("valid.rhai");
    let txt_file = temp_dir.path().join("invalid.txt");

    fs::write(&rhai_file, "print(\"Valid rhai file\");").expect("Failed to write rhai file");
    fs::write(&txt_file, "This is not a rhai file").expect("Failed to write txt file");

    // Verify file extensions
    assert_eq!(rhai_file.extension().unwrap(), "rhai");
    assert_eq!(txt_file.extension().unwrap(), "txt");

    // herodo should execute .rhai files and warn about non-.rhai files
    let result = herolib_do::run(rhai_file.to_str().unwrap());
    assert!(
        result.is_ok(),
        "Valid .rhai file should execute successfully"
    );
}
