import pytest
import time

from agenx.trace.spans.models import (
    Span,
    SpanType,
    SpanStatus
)
from agenx._internal import (
    make_span_id, 
    make_trace_id,
    now,
    duration_ms
)
from agenx.trace.spans.span import LiveSpan

def generate_span(**overrides) -> Span:
    defaults = dict(
        span_id=make_span_id(),
        trace_id=make_trace_id(),
        parent_id=None,
        name="test_span",
        type=SpanType.STEP,
        start_time=now(),
    )

    defaults.update(**overrides)
    return Span(**defaults)

def make_live(callbacks=None, **overrides) -> LiveSpan:
    return LiveSpan(generate_span(**overrides), on_end_callbacks=callbacks or [])

def test_span_starts_running():
    live = make_live()
    assert live.status == SpanStatus.RUNNING

def test_span_ok_on_clean_exit():
    with make_live() as s:
        pass
    assert s.status == SpanStatus.OK

def test_span_duration_positive():
    with make_live() as s:
        time.sleep(0.03)
    assert duration_ms(s._span.start_time, s._span.end_time) > 0

def test_span_error_on_exception():
    with pytest.raises(ValueError):
        with make_live() as s:
            raise ValueError("boom")
    assert s.status == SpanStatus.ERROR
    assert isinstance(s._span.error, ValueError)

def test_exception_is_not_swallowed():
    """LiveSpan must never suppress user exceptions"""
    with pytest.raises(RuntimeError, match="test error message"):
        with make_live():
            raise RuntimeError("test error message")