"""Integration tests – asynchronous (tagged) mode."""

from __future__ import annotations

import threading

import pytest

pytestmark = pytest.mark.integration


class TestAsyncMode:
    def test_async_run_single(self, async_client):
        reply = async_client.run("/system/identity/print")
        assert reply.done is not None
        assert "name" in reply.re[0].map

    def test_async_run_concurrent(self, async_client):
        """Multiple concurrent tagged requests must each receive their own reply."""
        commands = [
            "/system/identity/print",
            "/system/resource/print",
            "/interface/print",
        ]
        results: dict[str, object] = {}
        errors: list[Exception] = []

        def fetch(cmd):
            try:
                r = async_client.run(cmd)
                results[cmd] = r
            except Exception as exc:
                errors.append(exc)

        threads = [threading.Thread(target=fetch, args=(cmd,)) for cmd in commands]
        for t in threads:
            t.start()
        for t in threads:
            t.join(timeout=15)

        assert not errors, f"Async errors: {errors}"
        assert len(results) == len(commands)
        for cmd in commands:
            assert results[cmd].done is not None

    def test_async_multiple_sequential(self, async_client):
        for i in range(10):
            reply = async_client.run("/system/identity/print")
            assert reply.done is not None

    def test_async_start_twice_raises(self, client):
        from routeros import AlreadyAsyncError

        client.async_start()
        with pytest.raises(AlreadyAsyncError):
            client.async_start()
