# tests/test_adapters/test_langgraph.py

import pytest
from langgraph.graph import StateGraph, START
from typing import TypedDict
from orchestra import enhance
from orchestra.adapters.langgraph import EnhancedLangGraph

class State(TypedDict):
    val: str

def dummy_node(state):
    return {"val": state["val"] + "!"}

def test_langgraph_enhance_wrapper():
    """Test that enhance returns an EnhancedLangGraph"""
    graph = StateGraph(State)
    graph.add_node("node", dummy_node)
    graph.add_edge(START, "node")
    compiled = graph.compile()
    
    enhanced = enhance(compiled)
    assert isinstance(enhanced, EnhancedLangGraph)
    assert enhanced.graph == compiled

@pytest.mark.asyncio
async def test_langgraph_caching_simulation():
    """Simulate caching behavior with mock components"""
    graph = StateGraph(State)
    graph.add_node("node", dummy_node)
    graph.add_edge(START, "node")
    compiled = graph.compile()
    
    # Enhance with mocks
    enhanced = enhance(compiled)
    
    # Mock the cache manager to always return a hit on 2nd call
    # In a real unit test we might mock the inner semantic_store
    # but here we rely on the in-memory store working generally
    
    input_val = {"val": "test"}
    
    # 1. First Call
    res1 = enhanced.invoke(input_val)
    assert res1["val"] == "test!"
    
    # 2. Second Call (should hit cache)
    # We can inspect metrics to verify hit
    res2 = enhanced.invoke(input_val)
    assert res2 == res1
    
    metrics = enhanced.get_metrics()
    assert metrics["cache_hits"] == 1
