"""
Tests for provider adapters.

Validates:
- OpenAI adapter translate_request / translate_response round-trips
- Pricing lookup
- Stream chunk parsing
"""

import pytest

from proxy.adapters.openai import OpenAIAdapter
from proxy.schemas import (
    ChatCompletionRequest,
    ChatMessage,
    TokenPricing,
)


@pytest.fixture
def adapter():
    return OpenAIAdapter(base_url="https://api.openai.com")


class TestOpenAIAdapterRequest:
    def test_translate_request_url(self, adapter):
        req = ChatCompletionRequest(
            model="gpt-4o",
            messages=[ChatMessage(role="user", content="hello")],
        )
        url, headers, body = adapter.translate_request(req, api_key="sk-test")

        assert url == "https://api.openai.com/v1/chat/completions"
        assert headers["Authorization"] == "Bearer sk-test"
        assert body["model"] == "gpt-4o"
        assert len(body["messages"]) == 1
        assert body["messages"][0]["role"] == "user"
        assert body["messages"][0]["content"] == "hello"

    def test_translate_request_streaming(self, adapter):
        req = ChatCompletionRequest(
            model="gpt-4o",
            messages=[ChatMessage(role="user", content="hi")],
            stream=True,
        )
        _, _, body = adapter.translate_request(req, api_key="sk-test")

        assert body["stream"] is True
        assert body["stream_options"]["include_usage"] is True

    def test_translate_request_with_system_prompt(self, adapter):
        req = ChatCompletionRequest(
            model="gpt-4o",
            messages=[
                ChatMessage(role="system", content="You are helpful."),
                ChatMessage(role="user", content="hello"),
            ],
        )
        _, _, body = adapter.translate_request(req, api_key="sk-test")

        assert len(body["messages"]) == 2
        assert body["messages"][0]["role"] == "system"


class TestOpenAIAdapterResponse:
    def test_translate_response(self, adapter):
        body = {
            "id": "chatcmpl-abc123",
            "object": "chat.completion",
            "created": 1700000000,
            "model": "gpt-4o",
            "choices": [
                {
                    "index": 0,
                    "message": {"role": "assistant", "content": "Hello!"},
                    "finish_reason": "stop",
                }
            ],
            "usage": {
                "prompt_tokens": 10,
                "completion_tokens": 5,
                "total_tokens": 15,
            },
        }
        response = adapter.translate_response(200, {}, body)

        assert response.id == "chatcmpl-abc123"
        assert response.model == "gpt-4o"
        assert response.choices[0].message.content == "Hello!"
        assert response.usage.prompt_tokens == 10
        assert response.usage.completion_tokens == 5

    def test_translate_response_with_tool_calls(self, adapter):
        body = {
            "id": "chatcmpl-abc123",
            "object": "chat.completion",
            "created": 1700000000,
            "model": "gpt-4o",
            "choices": [
                {
                    "index": 0,
                    "message": {
                        "role": "assistant",
                        "content": None,
                        "tool_calls": [
                            {
                                "id": "call_1",
                                "type": "function",
                                "function": {"name": "get_weather"},
                            }
                        ],
                    },
                    "finish_reason": "tool_calls",
                }
            ],
            "usage": {"prompt_tokens": 20, "completion_tokens": 10, "total_tokens": 30},
        }
        response = adapter.translate_response(200, {}, body)
        assert response.choices[0].message.tool_calls is not None
        assert response.choices[0].finish_reason == "tool_calls"


class TestOpenAIAdapterStreaming:
    def test_parse_stream_chunk(self, adapter):
        raw = '{"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1700000000,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}'
        chunk = adapter.parse_stream_chunk(raw)

        assert chunk is not None
        assert chunk.choices[0].delta.content == "Hello"
        assert chunk.choices[0].finish_reason is None

    def test_parse_done_returns_none(self, adapter):
        assert adapter.parse_stream_chunk("[DONE]") is None

    def test_parse_empty_returns_none(self, adapter):
        assert adapter.parse_stream_chunk("") is None

    def test_parse_invalid_json_returns_none(self, adapter):
        assert adapter.parse_stream_chunk("not json") is None


class TestOpenAIPricing:
    def test_known_model_pricing(self, adapter):
        pricing = adapter.get_pricing("gpt-4o")
        assert pricing.input_cost_per_1k > 0
        assert pricing.output_cost_per_1k > 0
        assert pricing.cached_input_cost_per_1k > 0
        assert pricing.cached_input_cost_per_1k < pricing.input_cost_per_1k

    def test_unknown_model_returns_zero_pricing(self, adapter):
        pricing = adapter.get_pricing("unknown-model-xyz")
        assert pricing.input_cost_per_1k == 0.0
        assert pricing.output_cost_per_1k == 0.0

    def test_mini_model_is_cheaper(self, adapter):
        pricing_4o = adapter.get_pricing("gpt-4o")
        pricing_mini = adapter.get_pricing("gpt-4o-mini")
        assert pricing_mini.input_cost_per_1k < pricing_4o.input_cost_per_1k


# ---------------------------------------------------------------------------
# Gemini adapter (Phase 1 LLM expansion)
# ---------------------------------------------------------------------------


class TestGeminiAdapter:
    def test_get_adapter_gemini(self):
        from proxy.adapters import get_adapter

        adapter = get_adapter("gemini")
        assert adapter.name == "gemini"
        assert "generativelanguage.googleapis.com" in adapter.base_url

    def test_translate_request_url_and_key(self):
        from proxy.adapters.gemini import GeminiAdapter

        adapter = GeminiAdapter(
            base_url="https://generativelanguage.googleapis.com/v1beta"
        )
        req = ChatCompletionRequest(
            model="gemini-1.5-flash",
            messages=[ChatMessage(role="user", content="hello")],
        )
        url, headers, body = adapter.translate_request(req, api_key="test-key")

        assert "key=test-key" in url
        assert "models/gemini-1.5-flash:generateContent" in url
        assert body["contents"] == [
            {"role": "user", "parts": [{"text": "hello"}]}
        ]
        assert "generationConfig" in body
        assert body["generationConfig"]["maxOutputTokens"] == 8192

    def test_translate_request_streaming_uses_stream_endpoint(self):
        from proxy.adapters.gemini import GeminiAdapter

        adapter = GeminiAdapter(
            base_url="https://generativelanguage.googleapis.com/v1beta"
        )
        req = ChatCompletionRequest(
            model="gemini-1.5-pro",
            messages=[ChatMessage(role="user", content="hi")],
            stream=True,
        )
        url, _, _ = adapter.translate_request(req, api_key="k")

        assert "streamGenerateContent" in url
        assert "alt=sse" in url

    def test_translate_response(self):
        from proxy.adapters.gemini import GeminiAdapter

        adapter = GeminiAdapter(
            base_url="https://generativelanguage.googleapis.com/v1beta"
        )
        body = {
            "candidates": [
                {
                    "content": {"parts": [{"text": "Hi back!"}], "role": "model"},
                    "finishReason": "STOP",
                }
            ],
            "usageMetadata": {
                "promptTokenCount": 5,
                "candidatesTokenCount": 3,
                "totalTokenCount": 8,
            },
        }
        response = adapter.translate_response(200, {}, body)

        assert response.choices[0].message.content == "Hi back!"
        assert response.usage.prompt_tokens == 5
        assert response.usage.completion_tokens == 3

    def test_get_pricing(self):
        from proxy.adapters.gemini import GeminiAdapter

        adapter = GeminiAdapter(
            base_url="https://generativelanguage.googleapis.com/v1beta"
        )
        pricing = adapter.get_pricing("gemini-1.5-flash")
        assert pricing.input_cost_per_1k > 0
        assert pricing.output_cost_per_1k > 0
