import pytest

from src.gameplay import reaction as reaction_module
from src.gameplay.reaction import ReactionGate

NOW = 1_800_000_000


@pytest.fixture
def gate(monkeypatch):
    monkeypatch.delenv(reaction_module.REACTION_ENV, raising=False)
    monkeypatch.setattr(
        reaction_module.random, 'gauss', lambda mu, sigma: mu,
    )
    monkeypatch.setattr(
        reaction_module.random, 'random', lambda: 1.0,
    )
    return ReactionGate()


def test_disabled_passes_immediately(monkeypatch):
    monkeypatch.setenv(reaction_module.REACTION_ENV, '0')
    gate = ReactionGate()
    assert gate.ready(True, NOW) is True
    assert gate.ready(False, NOW) is False


def test_condition_fires_after_human_delay(gate):
    assert gate.ready(True, NOW) is False
    assert gate.ready(True, NOW + 0.1) is False
    assert gate.ready(True, NOW + 0.4) is True


def test_condition_drop_cancels_pending_reaction(gate):
    assert gate.ready(True, NOW) is False
    assert gate.ready(False, NOW + 0.1) is False
    # Nach Abbruch startet die Reaktionszeit von vorn.
    assert gate.ready(True, NOW + 0.2) is False
    assert gate.ready(True, NOW + 0.2 + 0.4) is True


def test_gate_rearms_after_firing(gate):
    assert gate.ready(True, NOW) is False
    assert gate.ready(True, NOW + 0.4) is True
    # Sofort erneut bereit fuer die naechste Reaktion.
    assert gate.ready(True, NOW + 0.4) is False
    assert gate.ready(True, NOW + 0.8) is True


def test_delay_is_randomized_within_bounds(monkeypatch):
    monkeypatch.delenv(reaction_module.REACTION_ENV, raising=False)
    monkeypatch.setattr(reaction_module.random, 'random', lambda: 1.0)
    monkeypatch.setattr(
        reaction_module.random, 'gauss', lambda mu, sigma: 99,
    )
    gate = ReactionGate()
    gate.ready(True, NOW)
    assert gate.delay == 1.2
    monkeypatch.setattr(
        reaction_module.random, 'gauss', lambda mu, sigma: -5,
    )
    gate = ReactionGate()
    gate.ready(True, NOW)
    assert gate.delay == 0.15


def test_distraction_adds_slow_tail(monkeypatch):
    monkeypatch.delenv(reaction_module.REACTION_ENV, raising=False)
    monkeypatch.setattr(
        reaction_module.random, 'gauss', lambda mu, sigma: mu,
    )
    monkeypatch.setattr(reaction_module.random, 'random', lambda: 0.05)
    gate = ReactionGate()
    gate.ready(True, NOW)
    assert gate.delay == 0.35 + 1.4
    assert gate.ready(True, NOW + 1.0) is False
    assert gate.ready(True, NOW + 1.8) is True


def test_urgent_suppresses_distraction(monkeypatch):
    monkeypatch.delenv(reaction_module.REACTION_ENV, raising=False)
    monkeypatch.setattr(
        reaction_module.random, 'gauss', lambda mu, sigma: mu,
    )
    monkeypatch.setattr(reaction_module.random, 'random', lambda: 0.05)
    gate = ReactionGate()
    gate.ready(True, NOW, urgent=True)
    assert gate.delay == 0.35
    assert gate.ready(True, NOW + 0.4, urgent=True) is True


def test_urgent_clamps_pending_slow_reaction(monkeypatch):
    monkeypatch.delenv(reaction_module.REACTION_ENV, raising=False)
    monkeypatch.setattr(
        reaction_module.random, 'gauss', lambda mu, sigma: mu,
    )
    monkeypatch.setattr(reaction_module.random, 'random', lambda: 0.05)
    gate = ReactionGate()
    gate.ready(True, NOW)  # armt mit 1.75s Ablenkungs-Tail
    assert gate.delay == 1.75

    assert gate.ready(True, NOW + 0.5, urgent=True) is False
    assert gate.delay == 1.2
    assert gate.ready(True, NOW + 1.3, urgent=True) is True
