"""Tests for lambdagent core: Term, Context, TraceEntry."""
import pytest
from lambdagent.core import Term, Context, TraceEntry, LambdagentError, UnboundVariable


class DummyTerm(Term):
    def apply(self, input, ctx):
        ctx.log(self._name, self._trace_id, input, f"echo:{input}", 1.0)
        return f"echo:{input}"


def test_term_call():
    t = DummyTerm("test")
    assert t("hello") == "echo:hello"


def test_term_compose():
    a = DummyTerm("a")
    b = DummyTerm("b")
    pipe = a >> b
    assert pipe("x") == "echo:echo:x"


def test_term_par():
    a = DummyTerm("a")
    b = DummyTerm("b")
    par = a | b
    result = par("x")
    assert result == ("echo:x", "echo:x")


def test_context_trace():
    ctx = Context()
    t = DummyTerm("t")
    t.apply("in", ctx)
    assert len(ctx.trace) == 1
    assert ctx.trace[0].term_name == "t"
    assert ctx.trace[0].input == "in"
    assert ctx.trace[0].output == "echo:in"


def test_context_extend():
    ctx = Context(bindings={"x": 1})
    child = ctx.extend(y=2)
    assert child.lookup("x") == 1
    assert child.lookup("y") == 2


def test_context_unbound():
    ctx = Context()
    with pytest.raises(UnboundVariable):
        ctx.lookup("missing")


def test_context_memory():
    ctx = Context(memory={"key": "val"})
    assert ctx.memory["key"] == "val"
