import pytest
from logos_adk.topology import resolve_topology, validate_send


class TestResolveTopology:
    def test_mesh_allows_all(self):
        agents = ["a", "b", "c"]
        topo = resolve_topology("mesh", agents)
        assert topo == {"a": {"b", "c"}, "b": {"a", "c"}, "c": {"a", "b"}}

    def test_dict_topology_converts_to_sets(self):
        topo = resolve_topology(
            {"intake": ["processor"], "processor": ["output"], "output": []},
            ["intake", "processor", "output"],
        )
        assert topo == {"intake": {"processor"}, "processor": {"output"}, "output": set()}

    def test_none_topology_allows_all(self):
        agents = ["a", "b"]
        topo = resolve_topology(None, agents)
        assert topo == {"a": {"b"}, "b": {"a"}}

    def test_unknown_agent_in_topology_raises(self):
        with pytest.raises(ValueError, match="not in agent list"):
            resolve_topology({"unknown": ["a"]}, ["a", "b"])

    def test_unknown_target_in_topology_raises(self):
        with pytest.raises(ValueError, match="not in agent list"):
            resolve_topology({"a": ["unknown"]}, ["a", "b"])


class TestValidateSend:
    def test_allowed_send(self):
        topo = {"a": {"b"}, "b": {"a"}}
        validate_send("a", "b", topo)  # should not raise

    def test_disallowed_send_raises_routing_error(self):
        from logos_adk.errors import RoutingError

        topo = {"a": {"b"}, "b": set(), "c": set()}
        with pytest.raises(RoutingError, match="not allowed.*topology"):
            validate_send("b", "a", topo)

    def test_send_to_unknown_agent_raises(self):
        from logos_adk.errors import RoutingError

        topo = {"a": {"b"}, "b": set()}
        with pytest.raises(RoutingError, match="not found"):
            validate_send("a", "unknown", topo)

    def test_send_to_self_raises(self):
        from logos_adk.errors import RoutingError

        topo = {"a": {"b"}, "b": {"a"}}
        with pytest.raises(RoutingError, match="cannot send to itself"):
            validate_send("a", "a", topo)
