"""Tests for Layer 1 physical invariants.

Merged from v-copilot (comprehensive coverage, registry tests)
and v-jules (defensive parameter handling tests).
"""

from layer1_invariants import (
    ALL_INVARIANTS,
    membrane_potential_decays_toward_rest,
    refractory_period_positive,
    reset_at_or_below_threshold,
    threshold_above_resting,
    time_constant_positive,
)


def _valid_params(**overrides):
    """Return a valid parameter set with optional overrides."""
    params = {
        "threshold": 1.0,
        "resting_potential": 0.0,
        "refractory_period": 0.002,
        "tau": 0.02,
        "reset_potential": 0.0,
    }
    params.update(overrides)
    return params


# --- threshold_above_resting ---


def test_threshold_above_resting_pass():
    assert threshold_above_resting(_valid_params()) is True


def test_threshold_above_resting_fail_equal():
    assert threshold_above_resting(_valid_params(threshold=0.0)) is False


def test_threshold_above_resting_fail_below():
    assert threshold_above_resting(_valid_params(threshold=-0.1)) is False


def test_threshold_above_resting_missing_param():
    """From v-jules: defensive .get() returns False on missing key."""
    assert threshold_above_resting({}) is False


# --- refractory_period_positive ---


def test_refractory_period_positive_pass():
    assert refractory_period_positive(_valid_params()) is True


def test_refractory_period_positive_fail_zero():
    assert refractory_period_positive(_valid_params(refractory_period=0)) is False


def test_refractory_period_positive_fail_negative():
    assert refractory_period_positive(_valid_params(refractory_period=-0.001)) is False


def test_refractory_period_positive_missing_param():
    """From v-jules: defensive .get() returns False on missing key."""
    assert refractory_period_positive({}) is False


# --- time_constant_positive ---


def test_time_constant_positive_pass():
    assert time_constant_positive(_valid_params()) is True


def test_time_constant_positive_fail_zero():
    assert time_constant_positive(_valid_params(tau=0)) is False


def test_time_constant_positive_fail_negative():
    assert time_constant_positive(_valid_params(tau=-0.01)) is False


def test_time_constant_positive_missing_param():
    """From v-jules: defensive .get() returns False on missing key."""
    assert time_constant_positive({}) is False


# --- reset_at_or_below_threshold ---


def test_reset_at_or_below_threshold_pass_below():
    assert reset_at_or_below_threshold(_valid_params()) is True


def test_reset_at_or_below_threshold_pass_equal():
    assert reset_at_or_below_threshold(_valid_params(reset_potential=1.0)) is True


def test_reset_at_or_below_threshold_fail():
    assert reset_at_or_below_threshold(_valid_params(reset_potential=1.5)) is False


def test_reset_at_or_below_threshold_missing_param():
    """From v-jules: defensive .get() returns False on missing key."""
    assert reset_at_or_below_threshold({}) is False


# --- membrane_potential_decays_toward_rest ---


def test_membrane_potential_decays_toward_rest_pass_above():
    params = _valid_params(current_voltage=0.5)
    assert membrane_potential_decays_toward_rest(params) is True


def test_membrane_potential_decays_toward_rest_pass_below():
    params = _valid_params(current_voltage=-0.1)
    assert membrane_potential_decays_toward_rest(params) is True


def test_membrane_potential_decays_toward_rest_pass_at_rest():
    params = _valid_params(current_voltage=0.0)
    assert membrane_potential_decays_toward_rest(params) is True


def test_membrane_potential_decays_toward_rest_fail_bad_tau():
    params = _valid_params(tau=0, current_voltage=0.5)
    assert membrane_potential_decays_toward_rest(params) is False


def test_membrane_potential_decays_toward_rest_fail_negative_tau():
    params = _valid_params(tau=-0.01, current_voltage=0.5)
    assert membrane_potential_decays_toward_rest(params) is False


def test_membrane_potential_decays_toward_rest_missing_tau():
    """From v-jules: defensive .get() returns False on missing key."""
    assert membrane_potential_decays_toward_rest({}) is False


# --- ALL_INVARIANTS registry ---


def test_all_invariants_registry_contains_five():
    assert len(ALL_INVARIANTS) == 5


def test_all_invariants_pass_with_valid_params():
    params = _valid_params(current_voltage=0.5)
    for name, fn in ALL_INVARIANTS.items():
        assert fn(params) is True, f"Invariant {name} unexpectedly failed"
