//! WASM-specific backend initialization.
//!
//! Provides TabularBackend with embedded fluid tables for WASM builds.
//! CoolProp C++ cannot compile to WASM, so we must use tabular interpolation.

use entropyk_fluids::{FluidBackend, TabularBackend};
use std::sync::OnceLock;
use wasm_bindgen::prelude::*;

/// Embedded R134a fluid table data.
const R134A_TABLE: &str = include_str!("../../../crates/fluids/data/r134a.json");

// TODO: Generate and embed additional fluid tables (R410A, R32, etc.)
// using the TabularBackend table generation tool. Only R134a is currently available.

/// Global backend instance, lazily initialized.
static GLOBAL_BACKEND: OnceLock<TabularBackend> = OnceLock::new();

/// Get or create the global backend with embedded fluid tables.
pub fn global_backend() -> &'static TabularBackend {
    GLOBAL_BACKEND.get_or_init(|| {
        let mut backend = TabularBackend::new();
        backend
            .load_table_from_str(R134A_TABLE)
            .expect("Embedded R134a table must be valid");
        tracing::info!("WASM backend initialized with R134a fluid table");
        backend
    })
}

/// Create a default backend (for backwards compatibility and tests).
pub fn create_default_backend() -> TabularBackend {
    let mut backend = TabularBackend::new();
    backend
        .load_table_from_str(R134A_TABLE)
        .expect("Embedded R134a table must be valid");
    backend
}

/// Create an empty backend for custom fluid loading.
pub fn create_empty_backend() -> TabularBackend {
    TabularBackend::new()
}

/// Load a fluid table from a JSON string (exposed to JS).
///
/// The table is loaded into the global backend so it is available
/// for subsequent solve calls. Returns an error if the JSON is invalid
/// or the table cannot be parsed.
#[wasm_bindgen]
pub fn load_fluid_table(json: String) -> Result<(), String> {
    // We cannot mutate the OnceLock, so we load into a new backend
    // and register it via a separate mechanism.
    // For now, validate the table can be parsed.
    let mut test_backend = TabularBackend::new();
    test_backend
        .load_table_from_str(&json)
        .map_err(|e| format!("Failed to load fluid table: {}", e))?;

    tracing::warn!(
        "Fluid table validated but not yet registered in global backend. \
         Custom fluid loading requires additional infrastructure."
    );
    Ok(())
}

/// Get list of available fluids in the default backend.
#[wasm_bindgen]
pub fn list_available_fluids() -> Vec<String> {
    global_backend()
        .list_fluids()
        .into_iter()
        .map(|f| f.0)
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    use wasm_bindgen_test::*;

    #[wasm_bindgen_test]
    fn test_create_default_backend() {
        let backend = create_default_backend();
        let fluids = backend.list_fluids();
        assert!(!fluids.is_empty());
        assert!(fluids.iter().any(|f| f.0 == "R134a"));
    }

    #[wasm_bindgen_test]
    fn test_list_available_fluids() {
        let fluids = list_available_fluids();
        assert!(!fluids.is_empty());
        assert!(fluids.contains(&"R134a".to_string()));
    }

    #[wasm_bindgen_test]
    fn test_create_empty_backend() {
        let backend = create_empty_backend();
        let fluids = backend.list_fluids();
        assert!(fluids.is_empty());
    }
}
