//! WASM component bindings.
//!
//! Provides JavaScript-friendly wrappers for thermodynamic components.

use entropyk_components::port::{Connected, FluidId, Port};
use entropyk_components::Component;
use wasm_bindgen::prelude::*;

/// WASM wrapper for a thermodynamic component.
#[wasm_bindgen]
pub struct WasmComponent {
    pub(crate) inner: Box<dyn Component>,
}

#[wasm_bindgen]
impl WasmComponent {
    /// Get component name.
    pub fn name(&self) -> String {
        // This is a simplification; the real Component trait doesn't have name()
        // but the System stores it. For now, we'll just return a placeholder or
        // store it in the wrapper if needed.
        "Component".to_string()
    }
}

/// WASM wrapper for Compressor.
#[wasm_bindgen]
pub struct WasmCompressor {
    pub(crate) inner: entropyk_components::Compressor<Connected>,
}

#[wasm_bindgen]
impl WasmCompressor {
    /// Create a new Compressor component.
    #[wasm_bindgen(constructor)]
    pub fn new(
        m1: f64,
        m2: f64,
        m3: f64,
        m4: f64,
        m5: f64,
        m6: f64,
        m7: f64,
        m8: f64,
        m9: f64,
        m10: f64,
    ) -> WasmCompressor {
        let coeffs =
            entropyk_components::Ahri540Coefficients::new(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10);
        let fluid_id = FluidId::new("R410A");
        let p = entropyk_core::Pressure::from_bar(10.0);
        let h = entropyk_core::Enthalpy::from_joules_per_kg(400000.0);
        let suction = Port::new(fluid_id.clone(), p, h);
        let discharge = Port::new(fluid_id, p, h);

        let comp =
            entropyk_components::Compressor::new(coeffs, suction, discharge, 2900.0, 0.0001, 0.85)
                .unwrap();

        // Connect to dummy ports to get Connected state
        let suction_p = Port::new(FluidId::new("R410A"), p, h);
        let discharge_p = Port::new(FluidId::new("R410A"), p, h);
        let connected = comp.connect(suction_p, discharge_p).unwrap();

        WasmCompressor { inner: connected }
    }

    /// Convert to a generic WasmComponent.
    pub fn into_component(self) -> WasmComponent {
        WasmComponent {
            inner: Box::new(self.inner),
        }
    }
}

/// WASM wrapper for Condenser.
#[wasm_bindgen]
pub struct WasmCondenser {
    inner: entropyk_components::Condenser,
}

#[wasm_bindgen]
impl WasmCondenser {
    /// Create a new condenser with thermal conductance UA.
    #[wasm_bindgen(constructor)]
    pub fn new(ua: f64) -> WasmCondenser {
        WasmCondenser {
            inner: entropyk_components::Condenser::new(ua),
        }
    }

    /// Convert to a generic WasmComponent.
    pub fn into_component(self) -> WasmComponent {
        WasmComponent {
            inner: Box::new(self.inner),
        }
    }
}

/// WASM wrapper for Evaporator.
#[wasm_bindgen]
pub struct WasmEvaporator {
    inner: entropyk_components::Evaporator,
}

#[wasm_bindgen]
impl WasmEvaporator {
    /// Create a new evaporator with thermal conductance UA.
    #[wasm_bindgen(constructor)]
    pub fn new(ua: f64) -> WasmEvaporator {
        WasmEvaporator {
            inner: entropyk_components::Evaporator::new(ua),
        }
    }

    /// Convert to a generic WasmComponent.
    pub fn into_component(self) -> WasmComponent {
        WasmComponent {
            inner: Box::new(self.inner),
        }
    }
}

/// WASM wrapper for ExpansionValve.
#[wasm_bindgen]
pub struct WasmExpansionValve {
    pub(crate) inner: entropyk_components::ExpansionValve<Connected>,
}

#[wasm_bindgen]
impl WasmExpansionValve {
    /// Create a new expansion valve.
    #[wasm_bindgen(constructor)]
    pub fn new() -> WasmExpansionValve {
        let fluid_id = FluidId::new("R410A");
        let p = entropyk_core::Pressure::from_bar(10.0);
        let h = entropyk_core::Enthalpy::from_joules_per_kg(400000.0);
        let inlet = Port::new(fluid_id.clone(), p, h);
        let outlet = Port::new(fluid_id, p, h);

        let valve = entropyk_components::ExpansionValve::new(inlet, outlet, Some(1.0)).unwrap();

        let inlet_p = Port::new(FluidId::new("R410A"), p, h);
        let outlet_p = Port::new(FluidId::new("R410A"), p, h);
        let connected = valve.connect(inlet_p, outlet_p).unwrap();

        WasmExpansionValve { inner: connected }
    }

    /// Convert to a generic WasmComponent.
    pub fn into_component(self) -> WasmComponent {
        WasmComponent {
            inner: Box::new(self.inner),
        }
    }
}

/// WASM wrapper for Pipe.
#[wasm_bindgen]
pub struct WasmPipe {
    pub(crate) inner: entropyk_components::Pipe<Connected>,
}

#[wasm_bindgen]
impl WasmPipe {
    /// Create a new pipe.
    #[wasm_bindgen(constructor)]
    pub fn new(length: f64, diameter: f64) -> WasmPipe {
        let geometry = entropyk_components::PipeGeometry::smooth(length, diameter).unwrap();
        let fluid_id = FluidId::new("Water");
        let p = entropyk_core::Pressure::from_bar(1.0);
        let h = entropyk_core::Enthalpy::from_joules_per_kg(100000.0);
        let inlet = Port::new(fluid_id.clone(), p, h);
        let outlet = Port::new(fluid_id, p, h);

        let pipe = entropyk_components::Pipe::new(
            geometry, inlet, outlet, 1000.0, // Default density
            0.001,  // Default viscosity
        )
        .unwrap();

        let inlet_p = Port::new(FluidId::new("Water"), p, h);
        let outlet_p = Port::new(FluidId::new("Water"), p, h);
        let connected = pipe.connect(inlet_p, outlet_p).unwrap();

        WasmPipe { inner: connected }
    }

    /// Convert to a generic WasmComponent.
    pub fn into_component(self) -> WasmComponent {
        WasmComponent {
            inner: Box::new(self.inner),
        }
    }
}
