"""Tests for review sampler."""

from __future__ import annotations

from bandito.review.sampler import sample_traces


class TestSampleTraces:
    def test_empty(self):
        assert sample_traces([]) == []

    def test_small_set_returned_fully(self, make_trace):
        traces = [make_trace() for _ in range(3)]
        samples = sample_traces(traces, max_total=30)
        assert len(samples) == 3

    def test_high_cost_prioritized(self, make_trace):
        traces = [make_trace(cost=0.001) for _ in range(20)]
        traces.append(make_trace(trace_id="expensive", cost=1.0))
        samples = sample_traces(traces, max_total=10)
        ids = [s.trace_id for s in samples]
        assert "expensive" in ids
        # First sample should be high_cost category
        expensive = [s for s in samples if s.trace_id == "expensive"][0]
        assert expensive.category == "high_cost"

    def test_high_latency_prioritized(self, make_trace):
        traces = [make_trace(latency=0.1) for _ in range(20)]
        traces.append(make_trace(trace_id="slow", latency=30.0))
        samples = sample_traces(traces, max_total=10)
        ids = [s.trace_id for s in samples]
        assert "slow" in ids

    def test_errors_included(self, make_trace):
        traces = [make_trace() for _ in range(20)]
        traces.append(make_trace(trace_id="broken", error="connection refused"))
        samples = sample_traces(traces, max_total=10)
        ids = [s.trace_id for s in samples]
        assert "broken" in ids
        broken = [s for s in samples if s.trace_id == "broken"][0]
        assert broken.category == "error"

    def test_dedup_across_buckets(self, make_trace):
        # A trace that's both expensive and slow should only appear once
        traces = [make_trace(trace_id="both", cost=1.0, latency=30.0)]
        traces.extend(make_trace() for _ in range(5))
        samples = sample_traces(traces, max_total=30)
        both_samples = [s for s in samples if s.trace_id == "both"]
        assert len(both_samples) == 1
        assert both_samples[0].category == "high_cost"  # First bucket wins

    def test_max_total_respected(self, make_trace):
        traces = [make_trace() for _ in range(100)]
        samples = sample_traces(traces, max_total=10)
        assert len(samples) <= 10

    def test_truncation(self, make_trace):
        long_input = "x" * 500
        traces = [make_trace(input_text=long_input)]
        samples = sample_traces(traces, max_total=5)
        assert len(samples[0].input_preview) <= 203  # 200 + "..."

    def test_spans_summary_condensed(self, make_trace):
        traces = [make_trace(num_spans=3)]
        samples = sample_traces(traces, max_total=5)
        assert len(samples[0].spans_summary) == 3
        # Each summary should have name and kind
        for sp in samples[0].spans_summary:
            assert "name" in sp
            assert "kind" in sp

    def test_error_field_set(self, make_trace):
        traces = [make_trace(error="timeout")]
        samples = sample_traces(traces, max_total=5)
        assert samples[0].error == "timeout"
