import sys
import io

from agenx.tracer import Tracer
from agenx.display import StdoutExporter
from agenx.trace.spans.models import (
    SpanStatus
)
from agenx._internal import (
    get_current_span
)

def test_span_creates_and_finishes():
    t = Tracer()

    with t.span("hello") as s:
        assert s.name == "hello"
        assert s.status == SpanStatus.RUNNING
    
    assert s.status == SpanStatus.OK


def test_auto_parent_id():
    t = Tracer()
    with t.span("outer") as outer:
        with t.span("inner") as inner:
            assert inner.parent_id == outer.span_id


def test_inherited_trace_id():
    t = Tracer()
    with t.span("outer") as outer:
        with t.span("inner") as inner:
            assert inner.trace_id == outer.trace_id


def test_context_restored_after_exception():
    t = Tracer()
    with t.span("outer") as outer:
        try:
            with t.span("inner"):
                raise ValueError("inner fails")
        except ValueError:
            pass
            
        assert get_current_span() is outer


def test_exporters_run_on_end():
    t = Tracer()
    received = []
    
    t.configure(exporters=[lambda s: received.append(s.name)])

    with t.span("exported"):
        pass

    assert received == ['exported']
    

def capture(fn):
    old = sys.stdout
    sys.stdout = io.StringIO()
    try:
        fn()
        return sys.stdout.getvalue()
    finally:
        sys.stdout = old

def test_prints_span_name_and_type():
    t = Tracer()
    t.configure(exporters=[StdoutExporter(show_ids=False)])
    out = capture(lambda: t.span("my_step").__enter__().__exit__(None, None, None))
    def run():
        with t.span("my_step"): pass
    assert "my_step" in capture(run)
    assert "[STEP]" in capture(run)