"""Tests for browser_axtree tool."""

from unittest.mock import MagicMock, PropertyMock, patch

from openjarvis.tools.browser_axtree import BrowserAXTreeTool


def _make_mock_page():
    page = MagicMock()
    page.accessibility.snapshot.return_value = {
        "role": "WebArea",
        "name": "Test Page",
        "children": [
            {"role": "heading", "name": "Welcome", "level": 1},
            {"role": "link", "name": "Click me", "url": "https://example.com"},
            {"role": "textbox", "name": "Search", "value": ""},
        ],
    }
    return page


def _make_mock_session(page=None):
    if page is None:
        page = _make_mock_page()
    session = MagicMock()
    type(session).page = PropertyMock(return_value=page)
    return session


class TestBrowserAXTreeTool:
    def test_instantiation(self) -> None:
        tool = BrowserAXTreeTool()
        assert tool.tool_id == "browser_axtree"
        assert tool.spec.name == "browser_axtree"

    def test_execute_returns_tree(self) -> None:
        session = _make_mock_session()
        with patch("openjarvis.tools.browser_axtree._session", session):
            tool = BrowserAXTreeTool()
            result = tool.execute()
        assert result.success is True
        assert "heading" in result.content
        assert "Welcome" in result.content

    def test_execute_includes_all_roles(self) -> None:
        session = _make_mock_session()
        with patch("openjarvis.tools.browser_axtree._session", session):
            tool = BrowserAXTreeTool()
            result = tool.execute()
        assert result.success is True
        assert "WebArea" in result.content
        assert "link" in result.content
        assert "textbox" in result.content

    def test_execute_includes_node_count_metadata(self) -> None:
        session = _make_mock_session()
        with patch("openjarvis.tools.browser_axtree._session", session):
            tool = BrowserAXTreeTool()
            result = tool.execute()
        assert result.success is True
        # 1 root + 3 children = 4 nodes
        assert result.metadata["node_count"] == 4

    def test_execute_max_depth(self) -> None:
        """When max_depth=1 only the root node should appear."""
        session = _make_mock_session()
        with patch("openjarvis.tools.browser_axtree._session", session):
            tool = BrowserAXTreeTool()
            result = tool.execute(max_depth=1)
        assert result.success is True
        assert "WebArea" in result.content
        # Children at depth 1 should not be present
        assert "heading" not in result.content

    def test_execute_empty_snapshot(self) -> None:
        page = MagicMock()
        page.accessibility.snapshot.return_value = None
        session = _make_mock_session(page)
        with patch("openjarvis.tools.browser_axtree._session", session):
            tool = BrowserAXTreeTool()
            result = tool.execute()
        assert result.success is False
        assert "No accessibility tree" in result.content

    def test_playwright_not_installed(self) -> None:
        session = MagicMock()
        type(session).page = PropertyMock(
            side_effect=ImportError("playwright not installed")
        )
        with patch("openjarvis.tools.browser_axtree._session", session):
            tool = BrowserAXTreeTool()
            result = tool.execute()
        assert result.success is False
        assert "playwright" in result.content.lower()

    def test_spec_category_and_capabilities(self) -> None:
        tool = BrowserAXTreeTool()
        assert tool.spec.category == "browser"
        assert "network:fetch" in tool.spec.required_capabilities

    def test_spec_has_max_depth_parameter(self) -> None:
        tool = BrowserAXTreeTool()
        props = tool.spec.parameters.get("properties", {})
        assert "max_depth" in props
        assert props["max_depth"]["type"] == "integer"

    def test_to_openai_function(self) -> None:
        tool = BrowserAXTreeTool()
        fn = tool.to_openai_function()
        assert fn["type"] == "function"
        assert fn["function"]["name"] == "browser_axtree"

    def test_execute_snapshot_error(self) -> None:
        page = MagicMock()
        page.accessibility.snapshot.side_effect = Exception("Browser crashed")
        session = _make_mock_session(page)
        with patch("openjarvis.tools.browser_axtree._session", session):
            tool = BrowserAXTreeTool()
            result = tool.execute()
        assert result.success is False
        assert "AX tree extraction error" in result.content
