from pathlib import Path

import pytest

from adapter.matrix.agent_registry import AgentRegistryError, load_agent_registry


def test_load_agent_registry_reads_yaml_entries(tmp_path: Path):
    path = tmp_path / "agents.yaml"
    path.write_text(
        "agents:\n"
        "  - id: agent-1\n"
        "    label: Analyst\n"
        "  - id: agent-2\n"
        "    label: Research\n",
        encoding="utf-8",
    )

    registry = load_agent_registry(path)

    assert [agent.agent_id for agent in registry.agents] == ["agent-1", "agent-2"]
    assert registry.get("agent-1").label == "Analyst"


def test_agent_registry_agents_sequence_is_immutable(tmp_path: Path):
    path = tmp_path / "agents.yaml"
    path.write_text(
        "agents:\n"
        "  - id: agent-1\n"
        "    label: Analyst\n",
        encoding="utf-8",
    )

    registry = load_agent_registry(path)

    with pytest.raises(AttributeError):
        registry.agents.append(  # type: ignore[attr-defined]
            registry.agents[0]
        )


def test_load_agent_registry_rejects_duplicate_ids(tmp_path: Path):
    path = tmp_path / "agents.yaml"
    path.write_text(
        "agents:\n"
        "  - id: agent-1\n"
        "    label: Analyst\n"
        "  - id: agent-1\n"
        "    label: Duplicate\n",
        encoding="utf-8",
    )

    with pytest.raises(AgentRegistryError, match="duplicate agent id"):
        load_agent_registry(path)


def test_load_agent_registry_rejects_non_mapping_entries(tmp_path: Path):
    path = tmp_path / "agents.yaml"
    path.write_text(
        "agents:\n"
        "  - agent-1\n",
        encoding="utf-8",
    )

    with pytest.raises(AgentRegistryError, match="each agent entry requires id and label"):
        load_agent_registry(path)


@pytest.mark.parametrize(
    "content",
    [
        "",
        "agents: []\n",
        "agents: agent-1\n",
        "foo: bar\n",
    ],
)
def test_load_agent_registry_rejects_missing_non_list_and_empty_agents(
    tmp_path: Path, content: str
):
    path = tmp_path / "agents.yaml"
    path.write_text(content, encoding="utf-8")

    with pytest.raises(AgentRegistryError, match="agents registry must contain a non-empty agents list"):
        load_agent_registry(path)


@pytest.mark.parametrize(
    "content, expected",
    [
        (
            "agents:\n"
            "  - label: Analyst\n",
            "each agent entry requires id and label",
        ),
        (
            "agents:\n"
            "  - id: agent-1\n",
            "each agent entry requires id and label",
        ),
    ],
)
def test_load_agent_registry_rejects_missing_id_or_label(tmp_path: Path, content: str, expected: str):
    path = tmp_path / "agents.yaml"
    path.write_text(content, encoding="utf-8")

    with pytest.raises(AgentRegistryError, match=expected):
        load_agent_registry(path)


def test_load_agent_registry_rejects_invalid_top_level_yaml(tmp_path: Path):
    path = tmp_path / "agents.yaml"
    path.write_text(
        "- id: agent-1\n"
        "  label: Analyst\n",
        encoding="utf-8",
    )

    with pytest.raises(AgentRegistryError, match="agent registry must be a mapping with an agents list"):
        load_agent_registry(path)


def test_load_agent_registry_rejects_malformed_yaml(tmp_path: Path):
    path = tmp_path / "agents.yaml"
    path.write_text(
        "agents:\n"
        "  - id: agent-1\n"
        "    label: Analyst\n"
        "  - id: agent-2\n"
        "    label: Research\n"
        "  - [\n",
        encoding="utf-8",
    )

    with pytest.raises(AgentRegistryError, match="invalid agent registry YAML"):
        load_agent_registry(path)


@pytest.mark.parametrize(
    "content",
    [
        "agents:\n"
        "  - id: null\n"
        "    label: Analyst\n",
        "agents:\n"
        "  - id: agent-1\n"
        "    label: null\n",
    ],
)
def test_load_agent_registry_rejects_null_id_or_label(tmp_path: Path, content: str):
    path = tmp_path / "agents.yaml"
    path.write_text(content, encoding="utf-8")

    with pytest.raises(AgentRegistryError, match="each agent entry requires id and label"):
        load_agent_registry(path)


@pytest.mark.parametrize(
    "content",
    [
        "agents:\n"
        "  - id: '   '\n"
        "    label: Analyst\n",
        "agents:\n"
        "  - id: agent-1\n"
        "    label: '   '\n",
    ],
)
def test_load_agent_registry_rejects_blank_id_or_label(tmp_path: Path, content: str):
    path = tmp_path / "agents.yaml"
    path.write_text(content, encoding="utf-8")

    with pytest.raises(AgentRegistryError, match="each agent entry requires id and label"):
        load_agent_registry(path)


@pytest.mark.parametrize(
    "content",
    [
        "agents:\n"
        "  - id: 123\n"
        "    label: Analyst\n",
        "agents:\n"
        "  - id: agent-1\n"
        "    label: 456\n",
        "agents:\n"
        "  - id: true\n"
        "    label: Analyst\n",
        "agents:\n"
        "  - id: agent-1\n"
        "    label: false\n",
    ],
)
def test_load_agent_registry_rejects_non_string_id_or_label(tmp_path: Path, content: str):
    path = tmp_path / "agents.yaml"
    path.write_text(content, encoding="utf-8")

    with pytest.raises(AgentRegistryError, match="each agent entry requires id and label"):
        load_agent_registry(path)
