"""Tests for LangGraph agent (state, graph)."""

from unittest.mock import patch

import pytest

from foremet.agent.state import AgentState
from foremet.agent.graph import build_graph


def test_agent_state_typed_dict() -> None:
    """AgentState has messages key with list type."""
    state: AgentState = {"messages": []}
    assert "messages" in state
    assert state["messages"] == []


def test_build_graph_returns_compiled_graph() -> None:
    """Build graph returns a compiled graph with invoke (no real LLM call)."""
    from langchain_core.tools import StructuredTool
    from pydantic import BaseModel

    class NoOpArgs(BaseModel):
        pass

    noop_tool = StructuredTool(name="noop", description="No-op", args_schema=NoOpArgs, func=lambda: "ok")
    graph = build_graph(
        system_prompt="You are a helper.",
        tools=[noop_tool],
        llm_provider="openai",
        model="gpt-4o-mini",
    )
    assert graph is not None
    assert hasattr(graph, "invoke")
    assert hasattr(graph, "astream")


def test_build_graph_invoke_with_mock_llm() -> None:
    """Invoke graph with mocked _get_llm returns state with messages."""
    from langchain_core.messages import AIMessage, HumanMessage

    def fake_get_llm(*args, **kwargs):
        mock = patch.MagicMock()
        mock.bind_tools.return_value = mock
        mock.invoke.return_value = AIMessage(content="Mocked reply.")
        return mock

    with patch("foremet.agent.graph._get_llm", side_effect=fake_get_llm):
        from langchain_core.tools import StructuredTool
        from pydantic import BaseModel
        class NoOpArgs(BaseModel):
            pass
        noop_tool = StructuredTool(name="noop", description="No-op", args_schema=NoOpArgs, func=lambda: "ok")

        graph = build_graph(
            system_prompt="Helper.",
            tools=[noop_tool],
            llm_provider="openai",
            model="gpt-4o-mini",
        )
        result = graph.invoke({"messages": [HumanMessage(content="Hi")]})
        assert "messages" in result
        assert isinstance(result["messages"], list)
        assert len(result["messages"]) >= 1
