"""Tests for the `name` parameter on wrap() and patch_litellm()."""

from __future__ import annotations

import types
from unittest.mock import MagicMock, patch

import pytest


@pytest.fixture(autouse=True)
def _init_carrot(monkeypatch):
    """Auto-initialize carrot_ai with a mock client for every test."""
    import carrot_ai
    import carrot_ai._litellm as _litellm_mod

    mock_client = MagicMock()
    monkeypatch.setattr(carrot_ai, "_client", mock_client)
    _litellm_mod._patched = False
    yield mock_client


class _FakeChoice:
    def __init__(self, content: str):
        self.message = types.SimpleNamespace(
            role="assistant", content=content, tool_calls=None
        )


class _FakeUsage:
    prompt_tokens = 10
    completion_tokens = 5
    total_tokens = 15


class _FakeResponse:
    def __init__(self):
        self.choices = [_FakeChoice("Hello!")]
        self.model = "gpt-4o"
        self.usage = _FakeUsage()


class _FakeOpenAI:
    __module__ = "openai"

    def __init__(self):
        self.chat = types.SimpleNamespace(
            completions=types.SimpleNamespace(create=MagicMock(return_value=_FakeResponse()))
        )


class TestWrapNameParam:
    def test_default_name_is_resource(self, _init_carrot):
        """Without name param, trace name should be the resource name."""
        import carrot_ai

        mock_client = _init_carrot
        fake = _FakeOpenAI()
        carrot_ai.wrap(fake)

        fake.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": "Hi"}],
        )

        submitted = mock_client.submit.call_args[0][0]
        assert submitted["name"] == "chat.completions"

    def test_custom_name_overrides_resource(self, _init_carrot):
        """With name param, trace name should be the custom name."""
        import carrot_ai

        mock_client = _init_carrot
        fake = _FakeOpenAI()
        carrot_ai.wrap(fake, name="my-chatbot")

        fake.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": "Hi"}],
        )

        submitted = mock_client.submit.call_args[0][0]
        assert submitted["name"] == "my-chatbot"

    def test_tags_still_work_with_name(self, _init_carrot):
        """Both name and tags can be set together."""
        import carrot_ai

        mock_client = _init_carrot
        fake = _FakeOpenAI()
        carrot_ai.wrap(fake, name="my-service", tags=["prod", "v2"])

        fake.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": "Hi"}],
        )

        submitted = mock_client.submit.call_args[0][0]
        assert submitted["name"] == "my-service"
        assert submitted["tags"] == ["prod", "v2"]


class TestPatchLitellmNameParam:
    def test_default_name_is_chat_completions(self, _init_carrot):
        """Without name param, litellm traces should use 'chat.completions'."""
        import carrot_ai

        mock_client = _init_carrot

        fake_litellm = types.ModuleType("litellm")
        fake_litellm.completion = MagicMock(return_value=_FakeResponse())
        fake_litellm.acompletion = MagicMock()

        with patch.dict("sys.modules", {"litellm": fake_litellm}):
            carrot_ai.patch_litellm()

        fake_litellm.completion(
            model="openai/gpt-4o",
            messages=[{"role": "user", "content": "Hi"}],
        )

        submitted = mock_client.submit.call_args[0][0]
        assert submitted["name"] == "chat.completions"

    def test_custom_name_overrides_default(self, _init_carrot):
        """With name param, litellm traces should use the custom name."""
        import carrot_ai

        mock_client = _init_carrot

        fake_litellm = types.ModuleType("litellm")
        fake_litellm.completion = MagicMock(return_value=_FakeResponse())
        fake_litellm.acompletion = MagicMock()

        with patch.dict("sys.modules", {"litellm": fake_litellm}):
            carrot_ai.patch_litellm(name="summarizer")

        fake_litellm.completion(
            model="openai/gpt-4o",
            messages=[{"role": "user", "content": "Hi"}],
        )

        submitted = mock_client.submit.call_args[0][0]
        assert submitted["name"] == "summarizer"

    def test_tags_still_work_with_name(self, _init_carrot):
        """Both name and tags can be set together on patch_litellm."""
        import carrot_ai

        mock_client = _init_carrot

        fake_litellm = types.ModuleType("litellm")
        fake_litellm.completion = MagicMock(return_value=_FakeResponse())
        fake_litellm.acompletion = MagicMock()

        with patch.dict("sys.modules", {"litellm": fake_litellm}):
            carrot_ai.patch_litellm(name="my-svc", tags=["staging"])

        fake_litellm.completion(
            model="openai/gpt-4o",
            messages=[{"role": "user", "content": "Hi"}],
        )

        submitted = mock_client.submit.call_args[0][0]
        assert submitted["name"] == "my-svc"
        assert submitted["tags"] == ["staging"]


class TestVersionBump:
    def test_version_is_0_2_0(self):
        import carrot_ai

        assert carrot_ai.__version__ == "0.2.0"
