"""Tests for the temporary visual effects system."""

import time

import pytest

from mudlib.effects import (
    Effect,
    active_effects,
    add_effect,
    clear_expired,
    get_effects_at,
)


@pytest.fixture(autouse=True)
def clean_effects():
    """Clear effects before and after each test."""
    active_effects.clear()
    yield
    active_effects.clear()


def test_add_effect_creates_entry():
    add_effect(10, 20, "~", "\033[1;97m", ttl=2.0)
    assert len(active_effects) == 1
    e = active_effects[0]
    assert e.x == 10
    assert e.y == 20
    assert e.char == "~"
    assert e.color == "\033[1;97m"


def test_add_effect_sets_expiry_from_ttl():
    before = time.monotonic()
    add_effect(0, 0, "~", "", ttl=2.0)
    after = time.monotonic()
    e = active_effects[0]
    assert before + 2.0 <= e.expires_at <= after + 2.0


def test_get_effects_at_returns_matching():
    add_effect(5, 5, "~", "c1", ttl=2.0)
    add_effect(5, 5, "~", "c2", ttl=2.0)
    add_effect(6, 5, "~", "c3", ttl=2.0)

    at_5_5 = get_effects_at(5, 5)
    assert len(at_5_5) == 2
    assert {e.color for e in at_5_5} == {"c1", "c2"}


def test_get_effects_at_excludes_expired():
    add_effect(5, 5, "~", "alive", ttl=10.0)
    # manually insert an expired effect
    active_effects.append(
        Effect(x=5, y=5, char="~", color="dead", expires_at=time.monotonic() - 1.0)
    )

    at_5_5 = get_effects_at(5, 5)
    assert len(at_5_5) == 1
    assert at_5_5[0].color == "alive"


def test_clear_expired_removes_old_effects():
    add_effect(1, 1, "~", "alive", ttl=10.0)
    active_effects.append(
        Effect(x=2, y=2, char="~", color="dead", expires_at=time.monotonic() - 1.0)
    )

    clear_expired()
    assert len(active_effects) == 1
    assert active_effects[0].color == "alive"


def test_multiple_effects_along_path():
    """Simulates adding a cloud trail along a flight path."""
    for i in range(5):
        add_effect(10 + i, 20, "~", "\033[1;97m", ttl=2.0)

    assert len(active_effects) == 5
    # all at y=20, x from 10-14
    for i, e in enumerate(active_effects):
        assert e.x == 10 + i
        assert e.y == 20
