"""Entropyk — NumPy / Buffer Protocol Tests.

Tests for zero-copy state vector access and NumPy integration.
"""

import pytest
import entropyk

# numpy may not be installed in test env — skip gracefully
numpy = pytest.importorskip("numpy")


class TestStateVectorNumpy:
    """Tests for state vector as NumPy array."""

    def test_state_vector_to_numpy(self):
        """ConvergedState.state_vector returns a list convertible to np array."""
        # Build a minimal system so we can get a state vector length
        system = entropyk.System()
        system.add_component(entropyk.Condenser())
        system.add_component(entropyk.Evaporator())
        system.add_edge(0, 1)
        system.add_edge(1, 0)
        system.finalize()

        # The state_vector_len should be > 0 after finalize
        svl = system.state_vector_len
        assert svl >= 0

    def test_converged_state_vector_is_list(self):
        """The state_vector attribute on ConvergedState should be a Python list
        of floats, convertible to numpy.array."""
        # We can't solve without real physics, but we can verify the accessor type
        # from the class itself
        assert hasattr(entropyk, "ConvergedState")

    def test_numpy_array_from_list(self):
        """Verify that a list of floats (as returned by state_vector) can be
        efficiently converted to a numpy array."""
        data = [1.0, 2.0, 3.0, 4.0, 5.0]
        arr = numpy.array(data, dtype=numpy.float64)
        assert arr.shape == (5,)
        assert arr.dtype == numpy.float64
        numpy.testing.assert_array_almost_equal(arr, data)


class TestTypesWithNumpy:
    """Tests for using core types with NumPy."""

    def test_pressure_float_in_numpy(self):
        """Pressure can be used as a float value in numpy operations."""
        p = entropyk.Pressure(bar=1.0)
        arr = numpy.array([float(p)], dtype=numpy.float64)
        assert arr[0] == pytest.approx(100000.0)

    def test_temperature_float_in_numpy(self):
        """Temperature can be used as a float value in numpy operations."""
        t = entropyk.Temperature(celsius=25.0)
        arr = numpy.array([float(t)], dtype=numpy.float64)
        assert arr[0] == pytest.approx(298.15)

    def test_enthalpy_float_in_numpy(self):
        """Enthalpy can be used as a float value in numpy operations."""
        h = entropyk.Enthalpy(kj_per_kg=250.0)
        arr = numpy.array([float(h)], dtype=numpy.float64)
        assert arr[0] == pytest.approx(250000.0)

    def test_massflow_float_in_numpy(self):
        """MassFlow can be used as a float value in numpy operations."""
        m = entropyk.MassFlow(kg_per_s=0.5)
        arr = numpy.array([float(m)], dtype=numpy.float64)
        assert arr[0] == pytest.approx(0.5)
