import os
from unittest.mock import MagicMock, patch

import pytest

from litellm.integrations.weave.weave_otel import (
    _set_weave_specific_attributes,
    get_weave_otel_config,
)
from litellm.types.integrations.weave_otel import WeaveOtelConfig, WeaveSpanAttributes


def test_get_weave_otel_config():
    """Test config creation with required env vars and error cases for missing vars."""
    # Test successful config creation with required environment variables
    with patch.dict(
        os.environ,
        {
            "WANDB_API_KEY": "test_api_key",
            "WANDB_PROJECT_ID": "test-entity/test-project",
        },
        clear=True,
    ):
        config = get_weave_otel_config()

        assert isinstance(config, WeaveOtelConfig)
        assert config.protocol == "otlp_http"
        assert config.project_id == "test-entity/test-project"
        assert config.otlp_auth_headers is not None
        assert "Authorization=" in config.otlp_auth_headers
        assert "project_id=test-entity/test-project" in config.otlp_auth_headers
        assert config.endpoint == "https://trace.wandb.ai/otel/v1/traces"

        # Verify environment variables were set
        assert (
            os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"]
            == "https://trace.wandb.ai/otel/v1/traces"
        )
        assert os.environ["OTEL_EXPORTER_OTLP_HEADERS"] == config.otlp_auth_headers

    # Test ValueError when WANDB_API_KEY is missing
    with patch.dict(
        os.environ, {"WANDB_PROJECT_ID": "test-entity/test-project"}, clear=True
    ):
        with pytest.raises(ValueError, match="WANDB_API_KEY must be set"):
            get_weave_otel_config()

    # Test ValueError when WANDB_PROJECT_ID is missing
    with patch.dict(os.environ, {"WANDB_API_KEY": "test_api_key"}, clear=True):
        with pytest.raises(ValueError, match="WANDB_PROJECT_ID must be set"):
            get_weave_otel_config()


def test_get_weave_otel_config_with_custom_host():
    """Test config creation with custom WANDB_HOST."""
    # Test with host that already has https://
    with patch.dict(
        os.environ,
        {
            "WANDB_API_KEY": "test_api_key",
            "WANDB_PROJECT_ID": "test-entity/test-project",
            "WANDB_HOST": "https://custom.wandb.io",
        },
        clear=True,
    ):
        config = get_weave_otel_config()
        assert config.endpoint == "https://custom.wandb.io/otel/v1/traces"
        assert (
            os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"]
            == "https://custom.wandb.io/otel/v1/traces"
        )

    # Test with host without http:// or https://
    with patch.dict(
        os.environ,
        {
            "WANDB_API_KEY": "test_api_key",
            "WANDB_PROJECT_ID": "test-entity/test-project",
            "WANDB_HOST": "custom.wandb.io",
        },
        clear=True,
    ):
        config = get_weave_otel_config()
        assert config.endpoint == "https://custom.wandb.io/otel/v1/traces"

    # Test with host with trailing slash
    with patch.dict(
        os.environ,
        {
            "WANDB_API_KEY": "test_api_key",
            "WANDB_PROJECT_ID": "test-entity/test-project",
            "WANDB_HOST": "https://custom.wandb.io/",
        },
        clear=True,
    ):
        config = get_weave_otel_config()
        assert config.endpoint == "https://custom.wandb.io/otel/v1/traces"


def test_set_weave_specific_attributes_display_name_from_metadata():
    """Test _set_weave_specific_attributes sets display_name from metadata."""
    mock_span = MagicMock()
    kwargs = {
        "metadata": {"display_name": "custom-display-name"},
        "model": "gpt-4",
    }

    with patch(
        "litellm.integrations.weave.weave_otel.safe_set_attribute"
    ) as mock_safe_set:
        _set_weave_specific_attributes(mock_span, kwargs, None)

        # Should set display_name from metadata
        mock_safe_set.assert_any_call(
            mock_span, WeaveSpanAttributes.DISPLAY_NAME.value, "custom-display-name"
        )


def test_set_weave_specific_attributes_display_name_from_model():
    """Test _set_weave_specific_attributes sets display_name from model when not in metadata."""
    mock_span = MagicMock()
    kwargs = {
        "model": "openai/gpt-4o-mini",
        "metadata": {},
    }

    with patch(
        "litellm.integrations.weave.weave_otel.safe_set_attribute"
    ) as mock_safe_set:
        _set_weave_specific_attributes(mock_span, kwargs, None)

        # Should set display_name from model
        mock_safe_set.assert_any_call(
            mock_span, WeaveSpanAttributes.DISPLAY_NAME.value, "openai__gpt-4o-mini"
        )


def test_set_weave_specific_attributes_thread_id_and_is_turn():
    """Test _set_weave_specific_attributes sets thread_id and is_turn from session_id."""
    mock_span = MagicMock()
    kwargs = {
        "metadata": {"session_id": "session-123"},
    }

    with patch(
        "litellm.integrations.weave.weave_otel.safe_set_attribute"
    ) as mock_safe_set:
        _set_weave_specific_attributes(mock_span, kwargs, None)

        # Should set thread_id and is_turn
        mock_safe_set.assert_any_call(
            mock_span, WeaveSpanAttributes.THREAD_ID.value, "session-123"
        )
        mock_safe_set.assert_any_call(
            mock_span, WeaveSpanAttributes.IS_TURN.value, True
        )
