"""Tests for upstream monkey-patches."""

from __future__ import annotations

from unittest.mock import patch

from flowlines._patches import _applied, _patch_google_genai_missing_llm_prompts


class TestGoogleGenaiMissingLlmPrompts:
    """Tests for the ``SpanAttributes.LLM_PROMPTS`` back-fill patch."""

    def setup_method(self) -> None:
        """Remove the patch tag so each test starts fresh."""
        _applied.discard("google_genai_llm_prompts")

    def test_adds_llm_prompts_when_missing(self) -> None:
        """The patch sets ``SpanAttributes.LLM_PROMPTS`` to ``'gen_ai.prompt'``."""
        from opentelemetry.semconv_ai import SpanAttributes

        # Remove if already present (from previous test or global state)
        had_attr = hasattr(SpanAttributes, "LLM_PROMPTS")
        if had_attr:
            original = SpanAttributes.LLM_PROMPTS  # type: ignore[attr-defined]
            delattr(SpanAttributes, "LLM_PROMPTS")

        try:
            _patch_google_genai_missing_llm_prompts()
            assert hasattr(SpanAttributes, "LLM_PROMPTS")
            assert SpanAttributes.LLM_PROMPTS == "gen_ai.prompt"  # type: ignore[attr-defined]
        finally:
            if had_attr:
                SpanAttributes.LLM_PROMPTS = original  # type: ignore[attr-defined]
            elif hasattr(SpanAttributes, "LLM_PROMPTS"):
                delattr(SpanAttributes, "LLM_PROMPTS")

    def test_noop_when_already_present(self) -> None:
        """The patch does not overwrite an existing ``LLM_PROMPTS`` attribute."""
        from opentelemetry.semconv_ai import SpanAttributes

        sentinel = "existing_value"
        had_attr = hasattr(SpanAttributes, "LLM_PROMPTS")
        if had_attr:
            original = SpanAttributes.LLM_PROMPTS  # type: ignore[attr-defined]

        SpanAttributes.LLM_PROMPTS = sentinel  # type: ignore[attr-defined]
        try:
            _patch_google_genai_missing_llm_prompts()
            assert sentinel == SpanAttributes.LLM_PROMPTS  # type: ignore[attr-defined]
        finally:
            if had_attr:
                SpanAttributes.LLM_PROMPTS = original  # type: ignore[attr-defined]
            else:
                delattr(SpanAttributes, "LLM_PROMPTS")

    def test_idempotent(self) -> None:
        """Calling the patch twice is safe."""
        _patch_google_genai_missing_llm_prompts()
        _patch_google_genai_missing_llm_prompts()

    def test_noop_when_semconv_ai_missing(self) -> None:
        """The patch is a no-op when ``opentelemetry.semconv_ai`` is absent."""
        with patch.dict("sys.modules", {"opentelemetry.semconv_ai": None}):
            _patch_google_genai_missing_llm_prompts()
