"""Tests for brynq.capability — agent capability registry and task routing."""

import json
import pytest


@pytest.fixture(autouse=True)
def _isolate_capability(tmp_path, monkeypatch):
    """Redirect capability storage to temp directory."""
    cap_dir = tmp_path / "capabilities"
    cap_dir.mkdir()
    sessions_dir = tmp_path / "sessions"
    sessions_dir.mkdir()
    channels_dir = tmp_path / "channels"
    channels_dir.mkdir()
    tasks_dir = tmp_path / "tasks"
    tasks_dir.mkdir()
    monkeypatch.setattr("brynq.capability.CAPABILITY_DIR", cap_dir)
    monkeypatch.setattr("brynq.capability.TASK_LOG", cap_dir / "_task_log.jsonl")
    monkeypatch.setattr("brynq.capability.SESSIONS_DIR", sessions_dir)
    monkeypatch.setattr("brynq.capability.CHANNELS_DIR", channels_dir)


def _create_session(sessions_dir, session_id):
    """Helper: create a session file so the agent appears active."""
    import brynq.capability as cap
    path = cap.SESSIONS_DIR / f"{session_id}.json"
    path.write_text(json.dumps({"session_id": session_id}))


class TestRegister:
    def test_register_creates_file(self):
        from brynq.capability import register_capability, CAPABILITY_DIR
        reg = register_capability("python", "I write Python", session_id="agent-1")
        assert (CAPABILITY_DIR / "agent-1_python.json").exists()
        assert reg["capability"] == "python"
        assert reg["session_id"] == "agent-1"

    def test_register_multiple_capabilities(self):
        from brynq.capability import register_capability, CAPABILITY_DIR
        register_capability("python", "Python dev", session_id="a1")
        register_capability("testing", "Test writer", session_id="a1")
        assert (CAPABILITY_DIR / "a1_python.json").exists()
        assert (CAPABILITY_DIR / "a1_testing.json").exists()


class TestUnregister:
    def test_unregister_removes_file(self):
        from brynq.capability import register_capability, unregister_capability, CAPABILITY_DIR
        register_capability("python", "desc", session_id="a1")
        assert unregister_capability("python", session_id="a1") is True
        assert not (CAPABILITY_DIR / "a1_python.json").exists()

    def test_unregister_nonexistent(self):
        from brynq.capability import unregister_capability
        assert unregister_capability("bogus", session_id="a1") is False


class TestListCapabilities:
    def test_empty_list(self):
        from brynq.capability import list_capabilities
        assert list_capabilities(active_only=False) == []

    def test_lists_all_when_not_active_only(self):
        from brynq.capability import register_capability, list_capabilities
        register_capability("python", "desc", session_id="a1")
        register_capability("testing", "desc", session_id="a2")
        caps = list_capabilities(active_only=False)
        assert len(caps) == 2

    def test_active_only_filters(self):
        from brynq.capability import register_capability, list_capabilities, SESSIONS_DIR
        register_capability("python", "desc", session_id="a1")
        register_capability("testing", "desc", session_id="a2")
        # Only a1 has an active session
        (SESSIONS_DIR / "a1.json").write_text('{"session_id":"a1"}')
        caps = list_capabilities(active_only=True)
        assert len(caps) == 1
        assert caps[0]["session_id"] == "a1"


class TestFindAgents:
    def test_find_by_exact_capability(self):
        from brynq.capability import register_capability, find_agents, SESSIONS_DIR
        register_capability("python", "Python expert", session_id="a1")
        (SESSIONS_DIR / "a1.json").write_text('{"session_id":"a1"}')
        agents = find_agents(capability="python")
        assert len(agents) == 1
        assert agents[0]["session_id"] == "a1"
        assert agents[0]["score"] > 0

    def test_find_by_partial_capability(self):
        from brynq.capability import register_capability, find_agents, SESSIONS_DIR
        register_capability("python_expert", "Senior Python developer", session_id="a1")
        (SESSIONS_DIR / "a1.json").write_text('{"session_id":"a1"}')
        agents = find_agents(capability="python")
        assert len(agents) == 1

    def test_find_by_query(self):
        from brynq.capability import register_capability, find_agents, SESSIONS_DIR
        register_capability("code_review", "Reviews Python and JS code", session_id="a1")
        (SESSIONS_DIR / "a1.json").write_text('{"session_id":"a1"}')
        agents = find_agents(query="python code")
        assert len(agents) == 1

    def test_find_no_match_returns_empty(self):
        from brynq.capability import register_capability, find_agents, SESSIONS_DIR
        register_capability("python", "desc", session_id="a1")
        (SESSIONS_DIR / "a1.json").write_text('{"session_id":"a1"}')
        agents = find_agents(capability="rust")
        assert agents == []

    def test_find_ranks_by_score(self):
        from brynq.capability import register_capability, find_agents, SESSIONS_DIR
        register_capability("python", "Python dev", session_id="a1")
        register_capability("python_expert", "Expert Python developer", session_id="a2")
        for sid in ("a1", "a2"):
            (SESSIONS_DIR / f"{sid}.json").write_text(f'{{"session_id":"{sid}"}}')
        agents = find_agents(capability="python")
        assert len(agents) == 2
        # Exact match (a1) should score higher than partial (a2)
        assert agents[0]["session_id"] == "a1"

    def test_platform_filter(self):
        from brynq.capability import register_capability, find_agents, SESSIONS_DIR
        register_capability("python", "desc", session_id="a1", platform="claude")
        register_capability("python", "desc", session_id="a2", platform="gemini")
        for sid in ("a1", "a2"):
            (SESSIONS_DIR / f"{sid}.json").write_text(f'{{"session_id":"{sid}"}}')
        agents = find_agents(capability="python", platform="claude")
        assert len(agents) == 1
        assert agents[0]["platform"] == "claude"


class TestDelegateTask:
    def test_delegate_to_capable_agent(self):
        from brynq.capability import register_capability, delegate_task, SESSIONS_DIR
        register_capability("python", "desc", session_id="a1", session_name="worker-1")
        (SESSIONS_DIR / "a1.json").write_text('{"session_id":"a1"}')
        result = delegate_task("Fix bug", "Fix the null check", "python")
        assert result["routed"] is True
        assert result["assigned_to"] == "worker-1"
        assert "task_id" in result

    def test_delegate_no_agent_posts_unassigned(self):
        from brynq.capability import delegate_task
        result = delegate_task("Fix bug", "desc", "quantum_computing")
        assert result["routed"] is False
        assert "reason" in result


class TestRouteTask:
    def test_route_returns_session_name(self):
        from brynq.capability import register_capability, route_task, SESSIONS_DIR
        register_capability("testing", "desc", session_id="a1", session_name="tester-bot")
        (SESSIONS_DIR / "a1.json").write_text('{"session_id":"a1"}')
        assert route_task("Run tests", "testing") == "tester-bot"

    def test_route_no_match_returns_none(self):
        from brynq.capability import route_task
        assert route_task("Build spaceship", "aerospace") is None
