"""trace uid 와 축 태그 — Opik 계층의 두 원재료."""
import uuid

import pytest

from app.modules.llm.opik_trace import build_axis_tags, new_trace_uid


def test_uid_is_uuid_version_7():
    """Opik 서버가 uuid4 를 400 으로 거부한다(2026-08-23 실측).

    "Trace id must be a version 7 UUID"
    """
    for _ in range(20):
        u = uuid.UUID(new_trace_uid())
        assert u.version == 7, f"version={u.version} — Opik 이 거부한다"


def test_uid_is_unique():
    assert len({new_trace_uid() for _ in range(500)}) == 500


def test_uid_is_time_ordered():
    """UUIDv7 은 시간순이다 — 정렬하면 만든 순서가 된다."""
    made = [new_trace_uid() for _ in range(50)]
    assert made == sorted(made)


def test_axis_tags_carry_prefixes():
    tags = build_axis_tags(
        step="scene_image_pipeline", op="still_recipe_judge",
        kind="judge", model="x-ai/grok-4.6", provider="openrouter",
    )
    assert tags == [
        "step:scene_image_pipeline",
        "op:still_recipe_judge",
        "kind:judge",
        "model:x-ai/grok-4.6",
        "provider:openrouter",
    ]


def test_axis_tags_skip_empty_axes():
    assert build_axis_tags(step="a") == ["step:a"]
    assert build_axis_tags(step="a", op=None, model="") == ["step:a"]


def test_axis_tags_never_emit_bare_names():
    """접두사 없는 태그가 하나라도 나오면 축이 다시 섞인다."""
    tags = build_axis_tags(step="s", op="o", kind="k", model="m",
                           provider="p", status="retry")
    assert all(":" in t for t in tags)


@pytest.mark.parametrize("bad", ["  ", "\t", None, ""])
def test_axis_tags_treat_blank_as_absent(bad):
    assert build_axis_tags(step="s", op=bad) == ["step:s"]
