"""Entropyk — Unit Tests for Component Wrappers.

Tests for all component constructors, validation, and repr.
"""

import pytest
import entropyk


class TestCompressor:
    """Tests for Compressor component."""

    def test_default(self):
        c = entropyk.Compressor()
        assert "Compressor" in repr(c)

    def test_custom_params(self):
        c = entropyk.Compressor(speed_rpm=3600.0, efficiency=0.9, fluid="R410A")
        assert c.speed == 3600.0
        assert c.efficiency_value == pytest.approx(0.9)
        assert c.fluid_name == "R410A"

    def test_negative_speed_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Compressor(speed_rpm=-1.0)

    def test_negative_displacement_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Compressor(displacement=-1.0)

    def test_invalid_efficiency_raises(self):
        with pytest.raises(ValueError, match="between"):
            entropyk.Compressor(efficiency=1.5)

    def test_repr(self):
        c = entropyk.Compressor(speed_rpm=2900.0, efficiency=0.85, fluid="R134a")
        r = repr(c)
        assert "2900" in r
        assert "0.85" in r
        assert "R134a" in r


class TestCondenser:
    """Tests for Condenser component."""

    def test_default(self):
        c = entropyk.Condenser()
        assert c.ua_value == pytest.approx(5000.0)

    def test_custom_ua(self):
        c = entropyk.Condenser(ua=10000.0)
        assert c.ua_value == pytest.approx(10000.0)

    def test_negative_ua_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Condenser(ua=-1.0)

    def test_repr(self):
        c = entropyk.Condenser(ua=5000.0)
        assert "Condenser" in repr(c)
        assert "5000" in repr(c)


class TestEvaporator:
    """Tests for Evaporator component."""

    def test_default(self):
        e = entropyk.Evaporator()
        assert e.ua_value == pytest.approx(3000.0)

    def test_custom_ua(self):
        e = entropyk.Evaporator(ua=8000.0)
        assert e.ua_value == pytest.approx(8000.0)

    def test_negative_ua_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Evaporator(ua=-1.0)

    def test_repr(self):
        e = entropyk.Evaporator(ua=3000.0)
        assert "Evaporator" in repr(e)


class TestEconomizer:
    """Tests for Economizer component."""

    def test_default(self):
        e = entropyk.Economizer()
        assert "Economizer" in repr(e)

    def test_custom_ua(self):
        e = entropyk.Economizer(ua=5000.0)
        assert "5000" in repr(e)

    def test_negative_ua_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Economizer(ua=-1.0)


class TestExpansionValve:
    """Tests for ExpansionValve component."""

    def test_default(self):
        v = entropyk.ExpansionValve()
        assert v.fluid_name == "R134a"
        assert v.opening_value == pytest.approx(0.5)

    def test_with_opening(self):
        v = entropyk.ExpansionValve(opening=0.5)
        assert v.opening_value == pytest.approx(0.5)

    def test_invalid_opening_raises(self):
        with pytest.raises(ValueError, match="between"):
            entropyk.ExpansionValve(opening=1.5)

    def test_repr(self):
        v = entropyk.ExpansionValve(fluid="R410A", opening=0.8)
        assert "ExpansionValve" in repr(v)
        assert "R410A" in repr(v)


class TestPipe:
    """Tests for Pipe component."""

    def test_default(self):
        p = entropyk.Pipe()
        assert "Pipe" in repr(p)

    def test_custom_params(self):
        p = entropyk.Pipe(length=5.0, diameter=0.025)
        assert "5.00" in repr(p)

    def test_negative_length_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Pipe(length=-1.0)

    def test_negative_diameter_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Pipe(diameter=-0.01)


class TestPump:
    """Tests for Pump component."""

    def test_default(self):
        p = entropyk.Pump()
        assert "Pump" in repr(p)

    def test_negative_pressure_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Pump(pressure_rise_pa=-100.0)

    def test_invalid_efficiency_raises(self):
        with pytest.raises(ValueError, match="between"):
            entropyk.Pump(efficiency=2.0)


class TestFan:
    """Tests for Fan component."""

    def test_default(self):
        f = entropyk.Fan()
        assert "Fan" in repr(f)

    def test_negative_pressure_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.Fan(pressure_rise_pa=-100.0)


class TestFlowSplitter:
    """Tests for FlowSplitter component."""

    def test_default(self):
        s = entropyk.FlowSplitter()
        assert "FlowSplitter" in repr(s)

    def test_custom_outlets(self):
        s = entropyk.FlowSplitter(n_outlets=3)
        assert "3" in repr(s)

    def test_too_few_outlets_raises(self):
        with pytest.raises(ValueError, match=">="):
            entropyk.FlowSplitter(n_outlets=1)


class TestFlowMerger:
    """Tests for FlowMerger component."""

    def test_default(self):
        m = entropyk.FlowMerger()
        assert "FlowMerger" in repr(m)

    def test_custom_inlets(self):
        m = entropyk.FlowMerger(n_inlets=4)
        assert "4" in repr(m)

    def test_too_few_inlets_raises(self):
        with pytest.raises(ValueError, match=">="):
            entropyk.FlowMerger(n_inlets=1)


class TestFlowSource:
    """Tests for FlowSource component."""

    def test_default(self):
        s = entropyk.FlowSource()
        assert "FlowSource" in repr(s)

    def test_custom(self):
        s = entropyk.FlowSource(pressure_pa=200000.0, temperature_k=350.0)
        assert "200000" in repr(s)

    def test_negative_pressure_raises(self):
        with pytest.raises(ValueError, match="positive"):
            entropyk.FlowSource(pressure_pa=-1.0)


class TestFlowSink:
    """Tests for FlowSink component."""

    def test_default(self):
        s = entropyk.FlowSink()
        assert "FlowSink" in repr(s)


class TestOperationalState:
    """Tests for OperationalState enum."""

    def test_on(self):
        s = entropyk.OperationalState("on")
        assert str(s) == "On"

    def test_off(self):
        s = entropyk.OperationalState("off")
        assert str(s) == "Off"

    def test_bypass(self):
        s = entropyk.OperationalState("bypass")
        assert str(s) == "Bypass"

    def test_invalid_raises(self):
        with pytest.raises(ValueError, match="one of"):
            entropyk.OperationalState("invalid")

    def test_eq(self):
        s1 = entropyk.OperationalState("on")
        s2 = entropyk.OperationalState("on")
        assert s1 == s2
