"""Integration tests – listener / streaming mode."""

from __future__ import annotations

import threading
import time

import pytest

pytestmark = pytest.mark.integration


class TestListener:
    def test_listen_and_cancel(self, client):
        """Start an IP-address listener, receive at least initial state, then cancel."""
        listener = client.listen("/ip/address/listen")
        received = []

        def drain():
            for sentence in listener:
                received.append(sentence)

        t = threading.Thread(target=drain, daemon=True)
        t.start()

        # Allow a brief window for initial state sentences.
        time.sleep(1.0)

        # Cancel the stream.
        listener.cancel()
        t.join(timeout=10)

        assert not t.is_alive(), "Drain thread did not terminate after cancel"
        # done is set when the stream ends normally.
        assert listener.done is not None

    def test_listen_queue(self, client):
        """listen() with a queue_size produces a usable Queue."""
        listener = client.listen("/ip/address/listen", queue_size=100)

        # Let it run briefly.
        time.sleep(0.5)
        listener.cancel()

        # The queue sentinel (None) must eventually appear.
        items = []
        import queue as q_module
        try:
            while True:
                item = listener.chan().get(timeout=5)
                if item is None:
                    break
                items.append(item)
        except q_module.Empty:
            pass  # Queue drained

        assert listener.done is not None

    def test_listen_auto_enables_async(self, ros_address, ros_credentials):
        """listen() must transparently enable async mode."""
        import routeros

        username, password = ros_credentials
        with routeros.dial(ros_address, username, password, timeout=10.0) as c:
            assert not c._async
            listener = c.listen("/ip/address/listen")
            assert c._async  # Must have been auto-enabled
            listener.cancel()
            time.sleep(0.5)

    def test_listen_iter(self, client):
        """Iterating ListenReply yields Sentence objects and stops on cancel."""
        listener = client.listen("/interface/listen")
        count = [0]

        def run():
            for sen in listener:
                assert "name" in sen.map or True  # interface sentences have "name"
                count[0] += 1

        t = threading.Thread(target=run, daemon=True)
        t.start()
        time.sleep(0.5)
        listener.cancel()
        t.join(timeout=10)
        assert not t.is_alive()
