"""
test_nvidia_chat.py - NvidiaProvider.chat() 測試

2026-03-29 ogt: 模組化重構 - 測試移至 NvidiaProvider
符合 feedback_lewooogo_modular_enforcement.md 規範

測試策略 (遵循 feedback_no_mock_testing.md):
- 使用真實 NVIDIA API (需 NVIDIA_API_KEY)
- 跳過條件: 無 API Key 時跳過
"""

import json
import os

import pytest

from src.core.config import get_settings
from src.services.nvidia_provider import NvidiaProvider, get_nvidia_provider

settings = get_settings()


@pytest.fixture
def nvidia_provider():
    """建立 NvidiaProvider 實例"""
    return NvidiaProvider()


@pytest.mark.asyncio
@pytest.mark.skipif(
    not os.getenv("NVIDIA_API_KEY") and not settings.NVIDIA_API_KEY,
    reason="NVIDIA_API_KEY not configured",
)
async def test_chat_success(nvidia_provider):
    """
    測試 chat() 成功回應

    驗證:
    - 回應格式正確 (4-tuple)
    - success = True
    - total_tokens > 0
    - cost_usd = 0 (免費 tier)
    """
    prompt = """你是一個 JSON 產生器。請回傳以下格式:
    {"status": "ok", "message": "test"}
    只回傳 JSON，不要其他內容。"""

    response, success, total_tokens, cost_usd = await nvidia_provider.chat(prompt)

    assert success is True, f"Expected success, got error: {response}"
    assert isinstance(response, str)
    assert len(response) > 0
    assert total_tokens > 0, "Expected token count > 0"
    assert cost_usd == 0.0, "Expected $0 for free tier"


@pytest.mark.asyncio
async def test_chat_no_api_key():
    """
    測試無 API Key 時的處理

    驗證:
    - success = False
    - 回傳適當錯誤訊息
    """
    # 建立沒有 API Key 的 provider
    provider = NvidiaProvider(api_key=None)

    response, success, total_tokens, cost_usd = await provider.chat("test")

    assert success is False
    assert "not configured" in response.lower()
    assert total_tokens == 0
    assert cost_usd == 0.0


@pytest.mark.asyncio
@pytest.mark.skipif(
    not os.getenv("NVIDIA_API_KEY") and not settings.NVIDIA_API_KEY,
    reason="NVIDIA_API_KEY not configured",
)
async def test_chat_json_response(nvidia_provider):
    """
    測試 JSON 格式回應

    驗證:
    - 回應是有效 JSON
    """
    prompt = """回傳一個 JSON 物件，包含:
    - action: "NO_ACTION"
    - reason: "測試"
    只回傳 JSON。"""

    response, success, _, _ = await nvidia_provider.chat(prompt)

    assert success is True

    # 驗證是有效 JSON
    try:
        data = json.loads(response)
        assert isinstance(data, dict)
    except json.JSONDecodeError:
        pytest.fail(f"Response is not valid JSON: {response[:200]}")


@pytest.mark.asyncio
@pytest.mark.skipif(
    not os.getenv("NVIDIA_API_KEY") and not settings.NVIDIA_API_KEY,
    reason="NVIDIA_API_KEY not configured",
)
async def test_chat_uses_model_registry(nvidia_provider):
    """
    測試使用 ModelRegistry 取得模型

    驗證:
    - 使用 models.json 中定義的 rca 模型
    """
    from src.services.model_registry import get_model_registry

    registry = get_model_registry()
    expected_model = registry.get_model("nvidia", "rca")

    # 模型應該是 llama-3.1-nemotron-70b-instruct
    assert "nemotron" in expected_model.lower()
    assert "70b" in expected_model or "mini" in expected_model


@pytest.mark.asyncio
def test_get_nvidia_provider_singleton():
    """
    測試單例模式

    驗證:
    - get_nvidia_provider() 返回同一實例
    """
    provider1 = get_nvidia_provider()
    provider2 = get_nvidia_provider()

    assert provider1 is provider2


@pytest.mark.asyncio
@pytest.mark.skipif(
    not os.getenv("NVIDIA_API_KEY") and not settings.NVIDIA_API_KEY,
    reason="NVIDIA_API_KEY not configured",
)
async def test_chat_includes_otel_tracing(nvidia_provider):
    """
    測試 OTEL 追蹤整合

    驗證:
    - chat() 執行時有 OTEL span
    """
    # 這個測試主要驗證代碼不會拋出異常
    prompt = '{"test": true}'
    response, success, _, _ = await nvidia_provider.chat(prompt)

    # 只要沒有拋出異常就算通過
    assert isinstance(response, str)
