//! External integration utilities for machine learning interoperability
//!
//! This module provides utilities for integrating with external systems,
//! including Python interoperability, WASM compilation support, and
//! foreign function interface (FFI) utilities.

use crate::{UtilsError, UtilsResult};
use scirs2_core::ndarray::{Array1, Array2};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::fmt;
use std::os::raw::c_char;

/// Python interoperability utilities
pub struct PythonInterop;

impl PythonInterop {
    /// Convert Rust array to Python-compatible format
    pub fn array_to_python_buffer(array: &Array1<f64>) -> PyArrayBuffer {
        PyArrayBuffer {
            data: array.as_slice().expect("operation should succeed").to_vec(),
            shape: vec![array.len()],
            dtype: "float64".to_string(),
            order: "C".to_string(),
        }
    }

    /// Convert 2D Rust array to Python-compatible format
    pub fn array2_to_python_buffer(array: &Array2<f64>) -> PyArrayBuffer {
        let (rows, cols) = array.dim();
        PyArrayBuffer {
            data: array.as_slice().expect("operation should succeed").to_vec(),
            shape: vec![rows, cols],
            dtype: "float64".to_string(),
            order: "C".to_string(),
        }
    }

    /// Create Rust array from Python buffer
    pub fn python_buffer_to_array(buffer: &PyArrayBuffer) -> UtilsResult<Array1<f64>> {
        if buffer.shape.len() != 1 {
            return Err(UtilsError::InvalidParameter(
                "Expected 1D array".to_string(),
            ));
        }

        if buffer.dtype != "float64" {
            return Err(UtilsError::InvalidParameter(format!(
                "Unsupported dtype: {}",
                buffer.dtype
            )));
        }

        Array1::from_vec(buffer.data.clone())
            .into_shape_with_order(buffer.shape[0])
            .map_err(|e| UtilsError::InvalidParameter(format!("Shape error: {e}")))
    }

    /// Create 2D Rust array from Python buffer
    pub fn python_buffer_to_array2(buffer: &PyArrayBuffer) -> UtilsResult<Array2<f64>> {
        if buffer.shape.len() != 2 {
            return Err(UtilsError::InvalidParameter(
                "Expected 2D array".to_string(),
            ));
        }

        if buffer.dtype != "float64" {
            return Err(UtilsError::InvalidParameter(format!(
                "Unsupported dtype: {}",
                buffer.dtype
            )));
        }

        Array2::from_shape_vec((buffer.shape[0], buffer.shape[1]), buffer.data.clone())
            .map_err(|e| UtilsError::InvalidParameter(format!("Shape error: {e}")))
    }

    /// Generate Python numpy import code
    pub fn generate_numpy_import_code(array_name: &str, buffer: &PyArrayBuffer) -> String {
        format!(
            r#"
import numpy as np

# Data generated by sklears-utils
{} = np.array({:?}, dtype='{}').reshape({:?})
"#,
            array_name, buffer.data, buffer.dtype, buffer.shape
        )
    }

    /// Generate Python function call template
    pub fn generate_function_call_template(
        function_name: &str,
        parameters: &[PythonParameter],
    ) -> String {
        let param_strings: Vec<String> = parameters
            .iter()
            .map(|p| match &p.value {
                PythonValue::String(s) => format!("{}='{}'", p.name, s),
                PythonValue::Number(n) => format!("{}={}", p.name, n),
                PythonValue::Boolean(b) => {
                    format!("{}={}", p.name, if *b { "True" } else { "False" })
                }
                PythonValue::Array(name) => format!("{}={}", p.name, name),
            })
            .collect();

        format!("{}({})", function_name, param_strings.join(", "))
    }

    /// Create Python script for ML model
    pub fn create_ml_script(
        model_type: &str,
        training_data: &PyArrayBuffer,
        labels: &PyArrayBuffer,
        hyperparameters: &HashMap<String, f64>,
    ) -> UtilsResult<String> {
        let mut script = String::new();

        // Imports
        script.push_str("import numpy as np\n");
        script.push_str("from sklearn.model_selection import train_test_split\n");

        match model_type {
            "linear_regression" => {
                script.push_str("from sklearn.linear_model import LinearRegression\n")
            }
            "random_forest" => {
                script.push_str("from sklearn.ensemble import RandomForestRegressor\n")
            }
            "svm" => script.push_str("from sklearn.svm import SVC\n"),
            _ => {
                return Err(UtilsError::InvalidParameter(format!(
                    "Unsupported model type: {model_type}"
                )))
            }
        }

        script.push_str("\n# Data preparation\n");
        script.push_str(&Self::generate_numpy_import_code("X", training_data));
        script.push_str(&Self::generate_numpy_import_code("y", labels));

        script.push_str("\n# Train-test split\n");
        script.push_str("X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n");

        script.push_str("\n# Model creation and training\n");
        let model_creation = match model_type {
            "linear_regression" => "model = LinearRegression()".to_string(),
            "random_forest" => {
                let n_estimators = hyperparameters.get("n_estimators").unwrap_or(&100.0);
                format!(
                    "model = RandomForestRegressor(n_estimators={})",
                    *n_estimators as i32
                )
            }
            "svm" => {
                let c = hyperparameters.get("C").unwrap_or(&1.0);
                format!("model = SVC(C={c})")
            }
            _ => {
                return Err(UtilsError::InvalidParameter(format!(
                    "Unsupported model type: {model_type}"
                )))
            }
        };

        script.push_str(&model_creation);
        script.push_str("\nmodel.fit(X_train, y_train)\n");

        script.push_str("\n# Evaluation\n");
        script.push_str("score = model.score(X_test, y_test)\n");
        script.push_str("print(f'Model score: {score:.4f}')\n");

        Ok(script)
    }
}

/// WASM compilation utilities
pub struct WasmUtils;

impl WasmUtils {
    /// Generate WASM-compatible function signature
    pub fn generate_wasm_signature(
        function_name: &str,
        parameters: &[WasmParameter],
        return_type: WasmType,
    ) -> String {
        let param_strings: Vec<String> = parameters
            .iter()
            .map(|p| format!("{}: {}", p.name, p.param_type))
            .collect();

        format!(
            "#[wasm_bindgen]\npub fn {}({}) -> {} {{",
            function_name,
            param_strings.join(", "),
            return_type
        )
    }

    /// Generate WASM memory management helpers
    pub fn generate_memory_helpers() -> String {
        r#"
use wasm_bindgen::prelude::*;

// Memory management helpers for WASM
#[wasm_bindgen]
pub fn alloc(size: usize) -> *mut u8 {
    let mut buf = Vec::with_capacity(size);
    let ptr = buf.as_mut_ptr();
    std::mem::forget(buf);
    ptr
}

#[wasm_bindgen]
pub fn dealloc(ptr: *mut u8, size: usize) {
    unsafe {
        let _ = Vec::from_raw_parts(ptr, size, size);
    }
}

// Array helpers
#[wasm_bindgen]
pub struct Float64Array {
    data: Vec<f64>,
}

#[wasm_bindgen]
impl Float64Array {
    #[wasm_bindgen(constructor)]
    pub fn new(size: usize) -> Float64Array {
        Float64Array {
            data: vec![0.0; size],
        }
    }

    #[wasm_bindgen(getter)]
    pub fn length(&self) -> usize {
        self.data.len()
    }

    #[wasm_bindgen]
    pub fn get(&self, index: usize) -> f64 {
        self.data.get(index).copied().unwrap_or(0.0)
    }

    #[wasm_bindgen]
    pub fn set(&mut self, index: usize, value: f64) {
        if index < self.data.len() {
            self.data[index] = value;
        }
    }

    #[wasm_bindgen]
    pub fn as_ptr(&self) -> *const f64 {
        self.data.as_ptr()
    }
}
"#
        .to_string()
    }

    /// Generate WASM bindings for ML functions
    pub fn generate_ml_bindings() -> String {
        r#"
use wasm_bindgen::prelude::*;

// Linear algebra operations
#[wasm_bindgen]
pub fn dot_product(a: &[f64], b: &[f64]) -> f64 {
    if a.len() != b.len() {
        return 0.0;
    }
    a.iter().zip(b.iter()).map(|(x, y)| x * y).sum()
}

#[wasm_bindgen]
pub fn matrix_multiply(
    a: &[f64], a_rows: usize, a_cols: usize,
    b: &[f64], b_rows: usize, b_cols: usize,
    result: &mut [f64]
) -> bool {
    if a_cols != b_rows || result.len() != a_rows * b_cols {
        return false;
    }

    for i in 0..a_rows {
        for j in 0..b_cols {
            let mut sum = 0.0;
            for k in 0..a_cols {
                sum += a[i * a_cols + k] * b[k * b_cols + j];
            }
            result[i * b_cols + j] = sum;
        }
    }
    true
}

// Statistical functions
#[wasm_bindgen]
pub fn mean(data: &[f64]) -> f64 {
    if data.is_empty() {
        return 0.0;
    }
    data.iter().sum::<f64>() / data.len() as f64
}

#[wasm_bindgen]
pub fn variance(data: &[f64]) -> f64 {
    if data.len() < 2 {
        return 0.0;
    }
    let mean_val = mean(data);
    let variance = data.iter()
        .map(|x| (x - mean_val).powi(2))
        .sum::<f64>() / (data.len() - 1) as f64;
    variance
}

#[wasm_bindgen]
pub fn standard_deviation(data: &[f64]) -> f64 {
    variance(data).sqrt()
}
"#
        .to_string()
    }

    /// Create build configuration for WASM
    pub fn create_wasm_build_config() -> WasmBuildConfig {
        WasmBuildConfig {
            target: "wasm32-unknown-unknown".to_string(),
            features: vec![
                "wasm-bindgen".to_string(),
                "console_error_panic_hook".to_string(),
            ],
            optimization: WasmOptimization::Size,
            debug: false,
            typescript_bindings: true,
        }
    }

    /// Generate package.json for WASM project
    pub fn generate_package_json(project_name: &str, version: &str) -> String {
        format!(
            r#"{{
  "name": "{project_name}",
  "version": "{version}",
  "description": "WASM bindings for sklears ML utilities",
  "main": "index.js",
  "types": "index.d.ts",
  "scripts": {{
    "build": "wasm-pack build --target web --out-dir pkg",
    "build:nodejs": "wasm-pack build --target nodejs --out-dir pkg-node",
    "test": "wasm-pack test --headless --chrome"
  }},
  "devDependencies": {{
    "wasm-pack": "^0.12.0"
  }},
  "files": [
    "pkg/"
  ],
  "keywords": [
    "wasm",
    "machine-learning",
    "sklears",
    "linear-algebra"
  ]
}}"#
        )
    }
}

/// R interoperability utilities
pub struct RInterop;

impl RInterop {
    /// Convert Rust array to R-compatible format
    pub fn array_to_r_vector(array: &Array1<f64>) -> RVector {
        RVector {
            data: array.as_slice().expect("operation should succeed").to_vec(),
            length: array.len(),
            r_type: RType::Numeric,
        }
    }

    /// Convert 2D Rust array to R matrix
    pub fn array2_to_r_matrix(array: &Array2<f64>) -> RMatrix {
        let (rows, cols) = array.dim();

        // Convert from row-major (ndarray) to column-major (R) storage
        let mut col_major_data = vec![0.0; rows * cols];
        for i in 0..rows {
            for j in 0..cols {
                col_major_data[j * rows + i] = array[[i, j]];
            }
        }

        RMatrix {
            data: col_major_data,
            nrow: rows,
            ncol: cols,
            byrow: false, // R defaults to column-major
            r_type: RType::Numeric,
        }
    }

    /// Create Rust array from R vector
    pub fn r_vector_to_array(vector: &RVector) -> UtilsResult<Array1<f64>> {
        if vector.r_type != RType::Numeric {
            return Err(UtilsError::InvalidParameter(format!(
                "Expected numeric vector, got {:?}",
                vector.r_type
            )));
        }

        Array1::from_vec(vector.data.clone())
            .into_shape_with_order(vector.length)
            .map_err(|e| UtilsError::InvalidParameter(format!("Shape error: {e}")))
    }

    /// Create 2D Rust array from R matrix
    pub fn r_matrix_to_array2(matrix: &RMatrix) -> UtilsResult<Array2<f64>> {
        if matrix.r_type != RType::Numeric {
            return Err(UtilsError::InvalidParameter(format!(
                "Expected numeric matrix, got {:?}",
                matrix.r_type
            )));
        }

        if matrix.byrow {
            // Data is already in row-major format, can use directly
            Array2::from_shape_vec((matrix.nrow, matrix.ncol), matrix.data.clone())
                .map_err(|e| UtilsError::InvalidParameter(format!("Shape error: {e}")))
        } else {
            // Convert from column-major (R) to row-major (ndarray) storage
            let mut row_major_data = vec![0.0; matrix.data.len()];
            for i in 0..matrix.nrow {
                for j in 0..matrix.ncol {
                    row_major_data[i * matrix.ncol + j] = matrix.data[j * matrix.nrow + i];
                }
            }
            Array2::from_shape_vec((matrix.nrow, matrix.ncol), row_major_data)
                .map_err(|e| UtilsError::InvalidParameter(format!("Shape error: {e}")))
        }
    }

    /// Generate R vector creation code
    pub fn generate_r_vector_code(vector_name: &str, vector: &RVector) -> String {
        format!(
            "{} <- c({})",
            vector_name,
            vector
                .data
                .iter()
                .map(|x| x.to_string())
                .collect::<Vec<_>>()
                .join(", ")
        )
    }

    /// Generate R matrix creation code
    pub fn generate_r_matrix_code(matrix_name: &str, matrix: &RMatrix) -> String {
        let data_str = matrix
            .data
            .iter()
            .map(|x| x.to_string())
            .collect::<Vec<_>>()
            .join(", ");

        format!(
            "{} <- matrix(c({}), nrow = {}, ncol = {}, byrow = {})",
            matrix_name,
            data_str,
            matrix.nrow,
            matrix.ncol,
            if matrix.byrow { "TRUE" } else { "FALSE" }
        )
    }

    /// Generate R data frame creation code
    pub fn generate_r_dataframe_code(
        df_name: &str,
        columns: &HashMap<String, RVector>,
    ) -> UtilsResult<String> {
        let mut column_defs = Vec::new();

        // Check that all columns have the same length
        let first_length = columns.values().next().map(|v| v.length).unwrap_or(0);

        for (name, vector) in columns {
            if vector.length != first_length {
                return Err(UtilsError::InvalidParameter(
                    "All columns must have the same length".to_string(),
                ));
            }

            let data_str = vector
                .data
                .iter()
                .map(|x| x.to_string())
                .collect::<Vec<_>>()
                .join(", ");

            column_defs.push(format!("{name} = c({data_str})"));
        }

        Ok(format!(
            "{} <- data.frame({})",
            df_name,
            column_defs.join(", ")
        ))
    }

    /// Generate R package loading code
    pub fn generate_r_package_imports(packages: &[&str]) -> String {
        let mut imports = String::new();

        for package in packages {
            imports.push_str(&format!("library({package})\n"));
        }

        imports
    }

    /// Generate R function call template
    pub fn generate_r_function_call(function_name: &str, parameters: &[RParameter]) -> String {
        let param_strings: Vec<String> = parameters
            .iter()
            .map(|p| match &p.value {
                RValue::String(s) => format!("{} = \"{}\"", p.name, s),
                RValue::Number(n) => format!("{} = {}", p.name, n),
                RValue::Boolean(b) => format!("{} = {}", p.name, if *b { "TRUE" } else { "FALSE" }),
                RValue::Vector(name) => format!("{} = {}", p.name, name),
                RValue::Matrix(name) => format!("{} = {}", p.name, name),
                RValue::DataFrame(name) => format!("{} = {}", p.name, name),
            })
            .collect();

        format!("{}({})", function_name, param_strings.join(", "))
    }

    /// Create R script for ML model
    pub fn create_r_ml_script(
        model_type: &str,
        training_data: &RMatrix,
        response_var: &RVector,
        hyperparameters: &HashMap<String, f64>,
    ) -> UtilsResult<String> {
        let mut script = String::new();

        // Package imports based on model type
        match model_type {
            "linear_regression" => {
                script.push_str("# Linear regression using base R\n");
            }
            "random_forest" => {
                script.push_str(&Self::generate_r_package_imports(&["randomForest"]));
            }
            "svm" => {
                script.push_str(&Self::generate_r_package_imports(&["e1071"]));
            }
            "glm" => {
                script.push_str("# Generalized linear model using base R\n");
            }
            "tree" => {
                script.push_str(&Self::generate_r_package_imports(&["tree"]));
            }
            _ => {
                return Err(UtilsError::InvalidParameter(format!(
                    "Unsupported R model type: {model_type}"
                )))
            }
        }

        script.push_str("\n# Data preparation\n");
        script.push_str(&Self::generate_r_matrix_code("X", training_data));
        script.push('\n');
        script.push_str(&Self::generate_r_vector_code("y", response_var));
        script.push('\n');

        // Create data frame for some models
        if matches!(model_type, "glm" | "tree") {
            script.push_str("\n# Create data frame\n");
            script.push_str("df <- data.frame(y = y, X)\n");
            script.push_str("colnames(df) <- c('response', paste0('X', 1:ncol(X)))\n");
        }

        script.push_str("\n# Train-test split\n");
        script.push_str("set.seed(42)\n");
        script.push_str("train_indices <- sample(1:nrow(X), size = 0.8 * nrow(X))\n");
        script.push_str("X_train <- X[train_indices, ]\n");
        script.push_str("X_test <- X[-train_indices, ]\n");
        script.push_str("y_train <- y[train_indices]\n");
        script.push_str("y_test <- y[-train_indices]\n");

        script.push_str("\n# Model creation and training\n");
        let model_creation = match model_type {
            "linear_regression" => "model <- lm(y_train ~ X_train)".to_string(),
            "random_forest" => {
                let ntree = hyperparameters.get("ntree").unwrap_or(&500.0);
                let mtry = hyperparameters.get("mtry").unwrap_or(&3.0);
                format!(
                    "model <- randomForest(x = X_train, y = y_train, ntree = {}, mtry = {})",
                    *ntree as i32, *mtry as i32
                )
            }
            "svm" => {
                let cost = hyperparameters.get("cost").unwrap_or(&1.0);
                let gamma = hyperparameters.get("gamma").unwrap_or(&0.1);
                format!("model <- svm(x = X_train, y = y_train, cost = {cost}, gamma = {gamma})")
            }
            "glm" => {
                let family = "gaussian"; // Default, could be parameterized
                format!("df_train <- df[train_indices, ]\nmodel <- glm(response ~ ., data = df_train, family = {family})")
            }
            "tree" => {
                "df_train <- df[train_indices, ]\nmodel <- tree(response ~ ., data = df_train)"
                    .to_string()
            }
            _ => {
                return Err(UtilsError::InvalidParameter(format!(
                    "Unsupported R model type: {model_type}"
                )))
            }
        };

        script.push_str(&model_creation);
        script.push('\n');

        script.push_str("\n# Prediction and evaluation\n");
        let prediction_code = match model_type {
            "linear_regression" => {
                "predictions <- predict(model, data.frame(X_test))\nrmse <- sqrt(mean((predictions - y_test)^2))\ncat('RMSE:', rmse, '\\n')"
            },
            "random_forest" => {
                "predictions <- predict(model, X_test)\nrmse <- sqrt(mean((predictions - y_test)^2))\ncat('RMSE:', rmse, '\\n')"
            },
            "svm" => {
                "predictions <- predict(model, X_test)\nrmse <- sqrt(mean((predictions - y_test)^2))\ncat('RMSE:', rmse, '\\n')"
            },
            "glm" | "tree" => {
                "df_test <- df[-train_indices, ]\npredictions <- predict(model, df_test)\nrmse <- sqrt(mean((predictions - y_test)^2))\ncat('RMSE:', rmse, '\\n')"
            },
            _ => {
                return Err(UtilsError::InvalidParameter(format!(
                    "Unsupported R model type for prediction: {model_type}"
                )))
            }
        };

        script.push_str(prediction_code);
        script.push('\n');

        script.push_str("\n# Model summary\n");
        script.push_str("print(summary(model))\n");

        Ok(script)
    }

    /// Generate R statistical analysis script
    pub fn create_r_statistical_analysis(
        data: &RMatrix,
        analysis_type: &str,
    ) -> UtilsResult<String> {
        let mut script = String::new();

        script.push_str("# Statistical analysis generated by sklears-utils\n");
        script.push_str(&Self::generate_r_matrix_code("data", data));
        script.push('\n');

        match analysis_type {
            "descriptive" => {
                script.push_str("\n# Descriptive statistics\n");
                script.push_str("summary(data)\n");
                script.push_str("apply(data, 2, sd)  # Standard deviations\n");
                script.push_str("cor(data)  # Correlation matrix\n");
            }
            "pca" => {
                script.push_str("\n# Principal Component Analysis\n");
                script.push_str("pca_result <- prcomp(data, center = TRUE, scale. = TRUE)\n");
                script.push_str("summary(pca_result)\n");
                script
                    .push_str("plot(pca_result$x[,1:2])  # Scatter plot of first two components\n");
            }
            "clustering" => {
                script.push_str("\n# K-means clustering\n");
                script.push_str("set.seed(42)\n");
                script.push_str("kmeans_result <- kmeans(data, centers = 3)\n");
                script.push_str("print(kmeans_result)\n");
                script.push_str("plot(data, col = kmeans_result$cluster)\n");
            }
            "normality_test" => {
                script.push_str("\n# Normality tests\n");
                script.push_str("for(i in 1:ncol(data)) {\n");
                script.push_str("  cat('Column', i, '\\n')\n");
                script.push_str("  print(shapiro.test(data[,i]))\n");
                script.push_str("}\n");
            }
            _ => {
                return Err(UtilsError::InvalidParameter(format!(
                    "Unsupported analysis type: {analysis_type}"
                )))
            }
        }

        Ok(script)
    }

    /// Convert R data types to Rust-compatible format
    pub fn convert_r_output(output: &str, expected_type: ROutputType) -> UtilsResult<ROutputValue> {
        match expected_type {
            ROutputType::Vector => {
                // Parse R vector output: [1] 1.0 2.0 3.0
                let cleaned = output.replace("[1]", "").trim().to_string();
                let values: Result<Vec<f64>, _> = cleaned
                    .split_whitespace()
                    .map(|s| s.parse::<f64>())
                    .collect();

                match values {
                    Ok(v) => Ok(ROutputValue::Vector(v)),
                    Err(_) => Err(UtilsError::InvalidParameter(
                        "Failed to parse R vector output".to_string(),
                    )),
                }
            }
            ROutputType::Scalar => {
                // Parse single value
                let cleaned = output.replace("[1]", "");
                let cleaned = cleaned.trim();
                match cleaned.parse::<f64>() {
                    Ok(v) => Ok(ROutputValue::Scalar(v)),
                    Err(_) => Err(UtilsError::InvalidParameter(
                        "Failed to parse R scalar output".to_string(),
                    )),
                }
            }
            ROutputType::String => Ok(ROutputValue::String(output.to_string())),
        }
    }
}

/// Foreign Function Interface (FFI) utilities
pub struct FFIUtils;

impl FFIUtils {
    /// Create C-compatible function signature
    pub fn create_c_signature(
        function_name: &str,
        parameters: &[CParameter],
        return_type: CType,
    ) -> String {
        let param_strings: Vec<String> = parameters
            .iter()
            .map(|p| format!("{} {}", p.param_type, p.name))
            .collect();

        format!(
            "extern \"C\" fn {}({}) -> {}",
            function_name,
            param_strings.join(", "),
            return_type
        )
    }

    /// Generate C header file
    pub fn generate_c_header(library_name: &str, functions: &[CFunctionSignature]) -> String {
        let mut header = String::new();

        let library_upper = library_name.to_uppercase();
        header.push_str(&format!("#ifndef {library_upper}_H\n"));
        header.push_str(&format!("#define {library_upper}_H\n\n"));
        header.push_str("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n");

        for func in functions {
            header.push_str(&format!("{};\n", func.signature));
        }

        header.push_str("\n#ifdef __cplusplus\n}\n#endif\n\n");
        header.push_str(&format!("#endif // {library_upper}_H\n"));

        header
    }

    /// Convert Rust string to C string
    pub fn rust_string_to_c(s: &str) -> UtilsResult<*mut c_char> {
        let c_string = CString::new(s)
            .map_err(|e| UtilsError::InvalidParameter(format!("Invalid C string: {e}")))?;
        Ok(c_string.into_raw())
    }

    /// Convert C string to Rust string
    ///
    /// # Safety
    ///
    /// This function is unsafe because it dereferences a raw pointer. The caller must ensure:
    /// - The pointer is valid and points to a null-terminated C string
    /// - The pointer remains valid for the duration of this function call
    /// - The memory pointed to by the pointer is not accessed by other threads during this call
    pub unsafe fn c_string_to_rust(ptr: *const c_char) -> UtilsResult<String> {
        if ptr.is_null() {
            return Err(UtilsError::InvalidParameter("Null pointer".to_string()));
        }

        let c_str = CStr::from_ptr(ptr);
        c_str
            .to_str()
            .map(|s| s.to_string())
            .map_err(|e| UtilsError::InvalidParameter(format!("Invalid UTF-8: {e}")))
    }

    /// Create array transfer structure for FFI
    pub fn create_array_transfer(data: &[f64]) -> ArrayTransfer {
        ArrayTransfer {
            data: data.as_ptr(),
            length: data.len(),
            capacity: data.len(),
        }
    }

    /// Generate FFI binding examples
    pub fn generate_ffi_examples() -> String {
        r#"
// Example FFI functions for machine learning operations

use std::os::raw::{c_double, c_int};
use std::slice;

#[repr(C)]
pub struct ArrayTransfer {
    pub data: *const f64,
    pub length: usize,
    pub capacity: usize,
}

// Linear regression example
#[no_mangle]
pub extern "C" fn linear_regression_fit(
    x_data: *const c_double,
    y_data: *const c_double,
    n_samples: c_int,
    coefficients: *mut c_double,
    intercept: *mut c_double,
) -> c_int {
    if x_data.is_null() || y_data.is_null() || coefficients.is_null() || intercept.is_null() {
        return -1; // Error: null pointer
    }

    unsafe {
        let x_slice = slice::from_raw_parts(x_data, n_samples as usize);
        let y_slice = slice::from_raw_parts(y_data, n_samples as usize);
        
        // Simple linear regression calculation
        let n = n_samples as f64;
        let sum_x: f64 = x_slice.iter().sum();
        let sum_y: f64 = y_slice.iter().sum();
        let sum_xy: f64 = x_slice.iter().zip(y_slice.iter()).map(|(x, y)| x * y).sum();
        let sum_xx: f64 = x_slice.iter().map(|x| x * x).sum();
        
        let slope = (n * sum_xy - sum_x * sum_y) / (n * sum_xx - sum_x * sum_x);
        let intercept_val = (sum_y - slope * sum_x) / n;
        
        *coefficients = slope;
        *intercept = intercept_val;
        
        0 // Success
    }
}

// Array operations example
#[no_mangle]
pub extern "C" fn array_mean(
    data: *const c_double,
    length: c_int,
    result: *mut c_double,
) -> c_int {
    if data.is_null() || result.is_null() || length <= 0 {
        return -1;
    }

    unsafe {
        let slice = slice::from_raw_parts(data, length as usize);
        let mean = slice.iter().sum::<f64>() / length as f64;
        *result = mean;
        0
    }
}
"#
        .to_string()
    }
}

// Data structures for external integration

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PyArrayBuffer {
    pub data: Vec<f64>,
    pub shape: Vec<usize>,
    pub dtype: String,
    pub order: String,
}

#[derive(Debug, Clone)]
pub struct PythonParameter {
    pub name: String,
    pub value: PythonValue,
}

#[derive(Debug, Clone)]
pub enum PythonValue {
    String(String),
    Number(f64),
    Boolean(bool),
    Array(String), // Reference to array variable name
}

#[derive(Debug, Clone)]
pub struct WasmParameter {
    pub name: String,
    pub param_type: WasmType,
}

#[derive(Debug, Clone)]
pub enum WasmType {
    F64,
    F32,
    I32,
    U32,
    Bool,
    String,
}

impl fmt::Display for WasmType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            WasmType::F64 => write!(f, "f64"),
            WasmType::F32 => write!(f, "f32"),
            WasmType::I32 => write!(f, "i32"),
            WasmType::U32 => write!(f, "u32"),
            WasmType::Bool => write!(f, "bool"),
            WasmType::String => write!(f, "String"),
        }
    }
}

#[derive(Debug, Clone)]
pub struct WasmBuildConfig {
    pub target: String,
    pub features: Vec<String>,
    pub optimization: WasmOptimization,
    pub debug: bool,
    pub typescript_bindings: bool,
}

#[derive(Debug, Clone)]
pub enum WasmOptimization {
    None,
    Size,
    Speed,
}

#[derive(Debug, Clone)]
pub struct CParameter {
    pub name: String,
    pub param_type: CType,
}

#[derive(Debug, Clone)]
pub enum CType {
    Int,
    Double,
    Float,
    CharPtr,
    VoidPtr,
    ConstCharPtr,
    ConstDoublePtr,
}

impl fmt::Display for CType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CType::Int => write!(f, "int"),
            CType::Double => write!(f, "double"),
            CType::Float => write!(f, "float"),
            CType::CharPtr => write!(f, "char*"),
            CType::VoidPtr => write!(f, "void*"),
            CType::ConstCharPtr => write!(f, "const char*"),
            CType::ConstDoublePtr => write!(f, "const double*"),
        }
    }
}

#[derive(Debug, Clone)]
pub struct CFunctionSignature {
    pub name: String,
    pub signature: String,
    pub description: String,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct ArrayTransfer {
    pub data: *const f64,
    pub length: usize,
    pub capacity: usize,
}

// R integration data structures

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RVector {
    pub data: Vec<f64>,
    pub length: usize,
    pub r_type: RType,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RMatrix {
    pub data: Vec<f64>,
    pub nrow: usize,
    pub ncol: usize,
    pub byrow: bool,
    pub r_type: RType,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum RType {
    Numeric,
    Integer,
    Character,
    Logical,
    Factor,
}

#[derive(Debug, Clone)]
pub struct RParameter {
    pub name: String,
    pub value: RValue,
}

#[derive(Debug, Clone)]
pub enum RValue {
    String(String),
    Number(f64),
    Boolean(bool),
    Vector(String),    // Reference to vector variable name
    Matrix(String),    // Reference to matrix variable name
    DataFrame(String), // Reference to data frame variable name
}

#[derive(Debug, Clone)]
pub enum ROutputType {
    Vector,
    Scalar,
    String,
}

#[derive(Debug, Clone)]
pub enum ROutputValue {
    Vector(Vec<f64>),
    Scalar(f64),
    String(String),
}

#[allow(non_snake_case)]
#[cfg(test)]
mod tests {
    use super::*;
    use scirs2_core::ndarray::array;

    #[test]
    fn test_python_array_conversion() {
        let arr = array![1.0, 2.0, 3.0, 4.0];
        let buffer = PythonInterop::array_to_python_buffer(&arr);

        assert_eq!(buffer.data, vec![1.0, 2.0, 3.0, 4.0]);
        assert_eq!(buffer.shape, vec![4]);
        assert_eq!(buffer.dtype, "float64");
        assert_eq!(buffer.order, "C");

        // Test conversion back
        let converted =
            PythonInterop::python_buffer_to_array(&buffer).expect("operation should succeed");
        assert_eq!(converted, arr);
    }

    #[test]
    fn test_python_array2_conversion() {
        let arr = array![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
        let buffer = PythonInterop::array2_to_python_buffer(&arr);

        assert_eq!(buffer.data, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
        assert_eq!(buffer.shape, vec![3, 2]);

        // Test conversion back
        let converted =
            PythonInterop::python_buffer_to_array2(&buffer).expect("operation should succeed");
        assert_eq!(converted, arr);
    }

    #[test]
    fn test_numpy_code_generation() {
        let buffer = PyArrayBuffer {
            data: vec![1.0, 2.0, 3.0],
            shape: vec![3],
            dtype: "float64".to_string(),
            order: "C".to_string(),
        };

        let code = PythonInterop::generate_numpy_import_code("my_array", &buffer);

        assert!(code.contains("import numpy as np"));
        assert!(code.contains("my_array = np.array"));
        assert!(code.contains("[1.0, 2.0, 3.0]"));
        assert!(code.contains("dtype='float64'"));
        assert!(code.contains("reshape([3])"));
    }

    #[test]
    fn test_python_function_call_template() {
        let params = vec![
            PythonParameter {
                name: "n_estimators".to_string(),
                value: PythonValue::Number(100.0),
            },
            PythonParameter {
                name: "random_state".to_string(),
                value: PythonValue::Number(42.0),
            },
            PythonParameter {
                name: "verbose".to_string(),
                value: PythonValue::Boolean(true),
            },
        ];

        let call = PythonInterop::generate_function_call_template("RandomForestRegressor", &params);

        assert!(call.contains("RandomForestRegressor("));
        assert!(call.contains("n_estimators=100"));
        assert!(call.contains("random_state=42"));
        assert!(call.contains("verbose=True"));
    }

    #[test]
    fn test_ml_script_generation() {
        let training_data = PyArrayBuffer {
            data: vec![1.0, 2.0, 3.0, 4.0],
            shape: vec![2, 2],
            dtype: "float64".to_string(),
            order: "C".to_string(),
        };

        let labels = PyArrayBuffer {
            data: vec![0.0, 1.0],
            shape: vec![2],
            dtype: "float64".to_string(),
            order: "C".to_string(),
        };

        let mut hyperparams = HashMap::new();
        hyperparams.insert("n_estimators".to_string(), 50.0);

        let script =
            PythonInterop::create_ml_script("random_forest", &training_data, &labels, &hyperparams)
                .expect("operation should succeed");

        assert!(script.contains("import numpy as np"));
        assert!(script.contains("from sklearn.ensemble import RandomForestRegressor"));
        assert!(script.contains("train_test_split"));
        assert!(script.contains("RandomForestRegressor(n_estimators=50)"));
        assert!(script.contains("model.fit(X_train, y_train)"));
        assert!(script.contains("model.score(X_test, y_test)"));
    }

    #[test]
    fn test_wasm_signature_generation() {
        let params = vec![
            WasmParameter {
                name: "a".to_string(),
                param_type: WasmType::F64,
            },
            WasmParameter {
                name: "b".to_string(),
                param_type: WasmType::F64,
            },
        ];

        let signature = WasmUtils::generate_wasm_signature("add", &params, WasmType::F64);

        assert!(signature.contains("#[wasm_bindgen]"));
        assert!(signature.contains("pub fn add(a: f64, b: f64) -> f64"));
    }

    #[test]
    fn test_wasm_memory_helpers() {
        let helpers = WasmUtils::generate_memory_helpers();

        assert!(helpers.contains("pub fn alloc(size: usize)"));
        assert!(helpers.contains("pub fn dealloc(ptr: *mut u8, size: usize)"));
        assert!(helpers.contains("pub struct Float64Array"));
        assert!(helpers.contains("#[wasm_bindgen]"));
    }

    #[test]
    fn test_wasm_ml_bindings() {
        let bindings = WasmUtils::generate_ml_bindings();

        assert!(bindings.contains("pub fn dot_product"));
        assert!(bindings.contains("pub fn matrix_multiply"));
        assert!(bindings.contains("pub fn mean"));
        assert!(bindings.contains("pub fn variance"));
        assert!(bindings.contains("pub fn standard_deviation"));
    }

    #[test]
    fn test_wasm_build_config() {
        let config = WasmUtils::create_wasm_build_config();

        assert_eq!(config.target, "wasm32-unknown-unknown");
        assert!(config.features.contains(&"wasm-bindgen".to_string()));
        assert!(config.typescript_bindings);
        assert!(!config.debug);
    }

    #[test]
    fn test_package_json_generation() {
        let json = WasmUtils::generate_package_json("my-ml-wasm", "0.1.0");

        assert!(json.contains("\"name\": \"my-ml-wasm\""));
        assert!(json.contains("\"version\": \"0.1.0\""));
        assert!(json.contains("wasm-pack"));
        assert!(json.contains("\"machine-learning\""));
    }

    #[test]
    fn test_c_signature_creation() {
        let params = vec![
            CParameter {
                name: "data".to_string(),
                param_type: CType::ConstDoublePtr,
            },
            CParameter {
                name: "length".to_string(),
                param_type: CType::Int,
            },
        ];

        let signature = FFIUtils::create_c_signature("compute_mean", &params, CType::Double);

        assert!(signature.contains("extern \"C\" fn compute_mean"));
        assert!(signature.contains("const double* data"));
        assert!(signature.contains("int length"));
        assert!(signature.contains("-> double"));
    }

    #[test]
    fn test_c_header_generation() {
        let functions = vec![
            CFunctionSignature {
                name: "add".to_string(),
                signature: "double add(double a, double b)".to_string(),
                description: "Add two numbers".to_string(),
            },
            CFunctionSignature {
                name: "multiply".to_string(),
                signature: "double multiply(double a, double b)".to_string(),
                description: "Multiply two numbers".to_string(),
            },
        ];

        let header = FFIUtils::generate_c_header("mylib", &functions);

        assert!(header.contains("#ifndef MYLIB_H"));
        assert!(header.contains("#define MYLIB_H"));
        assert!(header.contains("extern \"C\" {"));
        assert!(header.contains("double add(double a, double b);"));
        assert!(header.contains("double multiply(double a, double b);"));
        assert!(header.contains("#endif // MYLIB_H"));
    }

    #[test]
    fn test_rust_to_c_string() {
        let rust_str = "Hello, World!";
        let c_ptr = FFIUtils::rust_string_to_c(rust_str).expect("operation should succeed");

        // Convert back to verify
        let converted =
            unsafe { FFIUtils::c_string_to_rust(c_ptr).expect("operation should succeed") };
        assert_eq!(converted, rust_str);

        // Clean up
        unsafe {
            let _ = CString::from_raw(c_ptr);
        }
    }

    #[test]
    fn test_array_transfer_creation() {
        let data = vec![1.0, 2.0, 3.0, 4.0];
        let transfer = FFIUtils::create_array_transfer(&data);

        assert_eq!(transfer.length, 4);
        assert_eq!(transfer.capacity, 4);
        assert!(!transfer.data.is_null());
    }

    #[test]
    fn test_ffi_examples_generation() {
        let examples = FFIUtils::generate_ffi_examples();

        assert!(examples.contains("linear_regression_fit"));
        assert!(examples.contains("array_mean"));
        assert!(examples.contains("#[no_mangle]"));
        assert!(examples.contains("extern \"C\""));
        assert!(examples.contains("ArrayTransfer"));
    }

    #[test]
    fn test_python_value_variants() {
        let string_val = PythonValue::String("test".to_string());
        let number_val = PythonValue::Number(42.0);
        let bool_val = PythonValue::Boolean(true);
        let array_val = PythonValue::Array("my_array".to_string());

        // Test that all variants can be created
        match string_val {
            PythonValue::String(_) => {}
            _ => panic!(),
        }
        match number_val {
            PythonValue::Number(_) => {}
            _ => panic!(),
        }
        match bool_val {
            PythonValue::Boolean(_) => {}
            _ => panic!(),
        }
        match array_val {
            PythonValue::Array(_) => {}
            _ => panic!(),
        }
    }

    #[test]
    fn test_wasm_type_display() {
        assert_eq!(WasmType::F64.to_string(), "f64");
        assert_eq!(WasmType::F32.to_string(), "f32");
        assert_eq!(WasmType::I32.to_string(), "i32");
        assert_eq!(WasmType::U32.to_string(), "u32");
        assert_eq!(WasmType::Bool.to_string(), "bool");
        assert_eq!(WasmType::String.to_string(), "String");
    }

    #[test]
    fn test_c_type_display() {
        assert_eq!(CType::Int.to_string(), "int");
        assert_eq!(CType::Double.to_string(), "double");
        assert_eq!(CType::Float.to_string(), "float");
        assert_eq!(CType::CharPtr.to_string(), "char*");
        assert_eq!(CType::VoidPtr.to_string(), "void*");
        assert_eq!(CType::ConstCharPtr.to_string(), "const char*");
        assert_eq!(CType::ConstDoublePtr.to_string(), "const double*");
    }

    // R integration tests

    #[test]
    fn test_r_array_conversion() {
        let arr = array![1.0, 2.0, 3.0, 4.0];
        let r_vector = RInterop::array_to_r_vector(&arr);

        assert_eq!(r_vector.data, vec![1.0, 2.0, 3.0, 4.0]);
        assert_eq!(r_vector.length, 4);
        assert_eq!(r_vector.r_type, RType::Numeric);

        // Test conversion back
        let converted = RInterop::r_vector_to_array(&r_vector).expect("operation should succeed");
        assert_eq!(converted, arr);
    }

    #[test]
    fn test_r_matrix_conversion() {
        let arr = array![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
        let r_matrix = RInterop::array2_to_r_matrix(&arr);

        assert_eq!(r_matrix.data, vec![1.0, 3.0, 5.0, 2.0, 4.0, 6.0]); // Column-major
        assert_eq!(r_matrix.nrow, 3);
        assert_eq!(r_matrix.ncol, 2);
        assert!(!r_matrix.byrow);
        assert_eq!(r_matrix.r_type, RType::Numeric);

        // Test conversion back
        let converted = RInterop::r_matrix_to_array2(&r_matrix).expect("operation should succeed");
        assert_eq!(converted, arr);
    }

    #[test]
    fn test_r_vector_code_generation() {
        let r_vector = RVector {
            data: vec![1.0, 2.0, 3.0],
            length: 3,
            r_type: RType::Numeric,
        };

        let code = RInterop::generate_r_vector_code("my_vector", &r_vector);

        assert_eq!(code, "my_vector <- c(1, 2, 3)");
    }

    #[test]
    fn test_r_matrix_code_generation() {
        let r_matrix = RMatrix {
            data: vec![1.0, 2.0, 3.0, 4.0],
            nrow: 2,
            ncol: 2,
            byrow: false,
            r_type: RType::Numeric,
        };

        let code = RInterop::generate_r_matrix_code("my_matrix", &r_matrix);

        assert_eq!(
            code,
            "my_matrix <- matrix(c(1, 2, 3, 4), nrow = 2, ncol = 2, byrow = FALSE)"
        );
    }

    #[test]
    fn test_r_dataframe_code_generation() {
        let mut columns = HashMap::new();

        columns.insert(
            "x".to_string(),
            RVector {
                data: vec![1.0, 2.0, 3.0],
                length: 3,
                r_type: RType::Numeric,
            },
        );

        columns.insert(
            "y".to_string(),
            RVector {
                data: vec![4.0, 5.0, 6.0],
                length: 3,
                r_type: RType::Numeric,
            },
        );

        let code = RInterop::generate_r_dataframe_code("my_df", &columns)
            .expect("operation should succeed");

        // The order might vary due to HashMap, so check for both possibilities
        let expected1 = "my_df <- data.frame(x = c(1, 2, 3), y = c(4, 5, 6))";
        let expected2 = "my_df <- data.frame(y = c(4, 5, 6), x = c(1, 2, 3))";
        assert!(code == expected1 || code == expected2);
    }

    #[test]
    fn test_r_package_imports() {
        let packages = &["randomForest", "e1071", "ggplot2"];
        let imports = RInterop::generate_r_package_imports(packages);

        assert!(imports.contains("library(randomForest)"));
        assert!(imports.contains("library(e1071)"));
        assert!(imports.contains("library(ggplot2)"));
    }

    #[test]
    fn test_r_function_call_generation() {
        let params = vec![
            RParameter {
                name: "ntree".to_string(),
                value: RValue::Number(500.0),
            },
            RParameter {
                name: "mtry".to_string(),
                value: RValue::Number(3.0),
            },
            RParameter {
                name: "importance".to_string(),
                value: RValue::Boolean(true),
            },
            RParameter {
                name: "x".to_string(),
                value: RValue::Matrix("X_train".to_string()),
            },
        ];

        let call = RInterop::generate_r_function_call("randomForest", &params);

        assert!(call.contains("randomForest("));
        assert!(call.contains("ntree = 500"));
        assert!(call.contains("mtry = 3"));
        assert!(call.contains("importance = TRUE"));
        assert!(call.contains("x = X_train"));
    }

    #[test]
    fn test_r_ml_script_generation() {
        let training_data = RMatrix {
            data: vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
            nrow: 3,
            ncol: 2,
            byrow: false,
            r_type: RType::Numeric,
        };

        let response_var = RVector {
            data: vec![1.0, 0.0, 1.0],
            length: 3,
            r_type: RType::Numeric,
        };

        let mut hyperparams = HashMap::new();
        hyperparams.insert("ntree".to_string(), 100.0);
        hyperparams.insert("mtry".to_string(), 1.0);

        let script = RInterop::create_r_ml_script(
            "random_forest",
            &training_data,
            &response_var,
            &hyperparams,
        )
        .expect("operation should succeed");

        assert!(script.contains("library(randomForest)"));
        assert!(script.contains("X <- matrix"));
        assert!(script.contains("y <- c"));
        assert!(script.contains("randomForest(x = X_train, y = y_train, ntree = 100, mtry = 1)"));
        assert!(script.contains("train_indices"));
        assert!(script.contains("predictions <- predict"));
        assert!(script.contains("summary(model)"));
    }

    #[test]
    fn test_r_linear_regression_script() {
        let training_data = RMatrix {
            data: vec![1.0, 2.0, 3.0, 4.0],
            nrow: 2,
            ncol: 2,
            byrow: false,
            r_type: RType::Numeric,
        };

        let response_var = RVector {
            data: vec![1.0, 2.0],
            length: 2,
            r_type: RType::Numeric,
        };

        let hyperparams = HashMap::new();

        let script = RInterop::create_r_ml_script(
            "linear_regression",
            &training_data,
            &response_var,
            &hyperparams,
        )
        .expect("operation should succeed");

        assert!(script.contains("# Linear regression using base R"));
        assert!(script.contains("model <- lm(y_train ~ X_train)"));
        assert!(!script.contains("library(")); // Base R, no packages needed
    }

    #[test]
    fn test_r_statistical_analysis() {
        let data = RMatrix {
            data: vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
            nrow: 3,
            ncol: 2,
            byrow: false,
            r_type: RType::Numeric,
        };

        // Test descriptive statistics
        let script = RInterop::create_r_statistical_analysis(&data, "descriptive")
            .expect("operation should succeed");
        assert!(script.contains("summary(data)"));
        assert!(script.contains("apply(data, 2, sd)"));
        assert!(script.contains("cor(data)"));

        // Test PCA
        let script = RInterop::create_r_statistical_analysis(&data, "pca")
            .expect("operation should succeed");
        assert!(script.contains("prcomp(data, center = TRUE, scale. = TRUE)"));
        assert!(script.contains("plot(pca_result$x[,1:2])"));

        // Test clustering
        let script = RInterop::create_r_statistical_analysis(&data, "clustering")
            .expect("operation should succeed");
        assert!(script.contains("kmeans(data, centers = 3)"));
        assert!(script.contains("plot(data, col = kmeans_result$cluster)"));
    }

    #[test]
    fn test_r_output_conversion() {
        // Test vector parsing
        let vector_output = "[1] 1.0 2.5 3.8";
        let result = RInterop::convert_r_output(vector_output, ROutputType::Vector)
            .expect("operation should succeed");
        match result {
            ROutputValue::Vector(v) => assert_eq!(v, vec![1.0, 2.5, 3.8]),
            _ => panic!("Expected vector output"),
        }

        // Test scalar parsing
        let scalar_output = "[1] 42.5";
        let result = RInterop::convert_r_output(scalar_output, ROutputType::Scalar)
            .expect("operation should succeed");
        match result {
            ROutputValue::Scalar(s) => assert_eq!(s, 42.5),
            _ => panic!("Expected scalar output"),
        }

        // Test string parsing
        let string_output = "This is a test string";
        let result = RInterop::convert_r_output(string_output, ROutputType::String)
            .expect("operation should succeed");
        match result {
            ROutputValue::String(s) => assert_eq!(s, "This is a test string"),
            _ => panic!("Expected string output"),
        }
    }

    #[test]
    fn test_r_matrix_row_major_conversion() {
        let r_matrix = RMatrix {
            data: vec![1.0, 2.0, 3.0, 4.0],
            nrow: 2,
            ncol: 2,
            byrow: true, // Row-major
            r_type: RType::Numeric,
        };

        let converted = RInterop::r_matrix_to_array2(&r_matrix).expect("operation should succeed");

        // When byrow=true, data is already in row-major format [1,2,3,4]
        // This should give us [[1.0, 2.0], [3.0, 4.0]]
        let expected = array![[1.0, 2.0], [3.0, 4.0]];
        assert_eq!(converted, expected);
    }

    #[test]
    fn test_r_type_variants() {
        let numeric = RType::Numeric;
        let integer = RType::Integer;
        let character = RType::Character;
        let logical = RType::Logical;
        let factor = RType::Factor;

        // Test that all variants can be created and compared
        assert_eq!(numeric, RType::Numeric);
        assert_eq!(integer, RType::Integer);
        assert_eq!(character, RType::Character);
        assert_eq!(logical, RType::Logical);
        assert_eq!(factor, RType::Factor);
    }

    #[test]
    fn test_r_value_variants() {
        let string_val = RValue::String("test".to_string());
        let number_val = RValue::Number(42.0);
        let bool_val = RValue::Boolean(true);
        let vector_val = RValue::Vector("my_vector".to_string());
        let matrix_val = RValue::Matrix("my_matrix".to_string());
        let df_val = RValue::DataFrame("my_df".to_string());

        // Test that all variants can be created
        match string_val {
            RValue::String(_) => {}
            _ => panic!(),
        }
        match number_val {
            RValue::Number(_) => {}
            _ => panic!(),
        }
        match bool_val {
            RValue::Boolean(_) => {}
            _ => panic!(),
        }
        match vector_val {
            RValue::Vector(_) => {}
            _ => panic!(),
        }
        match matrix_val {
            RValue::Matrix(_) => {}
            _ => panic!(),
        }
        match df_val {
            RValue::DataFrame(_) => {}
            _ => panic!(),
        }
    }

    #[test]
    fn test_r_unsupported_model_type() {
        let training_data = RMatrix {
            data: vec![1.0, 2.0, 3.0, 4.0],
            nrow: 2,
            ncol: 2,
            byrow: false,
            r_type: RType::Numeric,
        };

        let response_var = RVector {
            data: vec![1.0, 2.0],
            length: 2,
            r_type: RType::Numeric,
        };

        let hyperparams = HashMap::new();

        let result = RInterop::create_r_ml_script(
            "unsupported_model",
            &training_data,
            &response_var,
            &hyperparams,
        );

        assert!(result.is_err());
        assert!(result
            .unwrap_err()
            .to_string()
            .contains("Unsupported R model type"));
    }

    #[test]
    fn test_r_unsupported_analysis_type() {
        let data = RMatrix {
            data: vec![1.0, 2.0, 3.0, 4.0],
            nrow: 2,
            ncol: 2,
            byrow: false,
            r_type: RType::Numeric,
        };

        let result = RInterop::create_r_statistical_analysis(&data, "unsupported_analysis");
        assert!(result.is_err());
        assert!(result
            .unwrap_err()
            .to_string()
            .contains("Unsupported analysis type"));
    }
}
