from types import SimpleNamespace

import pytest

from provider.google_client import GoogleClient, _normalize_schema
from provider.base import Message, MessageRole, ToolDefinition


def test_gemini_extract_tool_calls_from_fake_response():
    # Create a minimal client instance without calling __init__ (no google-genai dependency needed).
    c = object.__new__(GoogleClient)

    fc = SimpleNamespace(name="do_thing", args={"x": 1})
    part = SimpleNamespace(function_call=fc, thought_signature=None)
    content = SimpleNamespace(parts=[part])
    cand = SimpleNamespace(content=content)
    resp = SimpleNamespace(candidates=[cand])

    tool_calls = GoogleClient._extract_tool_calls(c, resp)
    assert len(tool_calls) == 1
    assert tool_calls[0].name == "do_thing"
    assert tool_calls[0].arguments == {"x": 1}


def test_gemini_function_declarations_schema_passthrough():
    # This test only verifies schema normalization; it shouldn't require SDK types.
    tools = [
        ToolDefinition(
            name="add",
            description="adds",
            parameters={
                "type": "object",
                "properties": {
                    "a": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additional_properties": {"type": "string"},
                        },
                    }
                },
            },
        )
    ]

    params = _normalize_schema(tools[0].parameters)
    # additional_properties 和 additionalProperties 都应被移除
    assert "additional_properties" not in str(params)
    assert "additionalProperties" not in str(params)


@pytest.mark.asyncio
async def test_count_tokens_fallback_on_error():
    """count_tokens 在 API 调用失败时应 fallback 到基类的字符估算"""
    c = object.__new__(GoogleClient)
    # 模拟一个会抛异常的 _client（无真实 SDK 客户端）
    c._client = SimpleNamespace(
        models=SimpleNamespace(
            count_tokens=lambda **kw: (_ for _ in ()).throw(RuntimeError("fake error")),
        )
    )
    c._types = SimpleNamespace()
    c.model = "gemini-2.0-flash"

    messages = [
        Message(role=MessageRole.USER, content="Hello, this is a test message."),
    ]

    print("\n--- 测试: count_tokens fallback ---")
    result = await c.count_tokens(messages=messages)
    print(f"  fallback 估算值: {result}")

    # 基类估算: len("Hello, this is a test message.") // 4 = 7
    assert isinstance(result, int)
    assert result > 0, f"fallback 结果应 > 0，实际: {result}"
