"""Tests for the Fireworks AI OpenAI-chat provider."""

from unittest.mock import AsyncMock, MagicMock

import pytest

from free_claude_code.application.errors import InvalidRequestError
from free_claude_code.config.constants import ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS
from free_claude_code.config.provider_catalog import FIREWORKS_DEFAULT_BASE
from free_claude_code.core.anthropic.models import Message, MessagesRequest
from free_claude_code.providers.base import ProviderConfig
from free_claude_code.providers.openai_chat import OpenAIChatProvider
from tests.providers.support import (
    REASONING_OFF,
    passthrough_rate_limiter,
    profiled_provider,
    reasoning_for,
)


@pytest.fixture
def fireworks_provider():
    return profiled_provider(
        "fireworks",
        ProviderConfig(
            api_key="test_fireworks_key",
            base_url=FIREWORKS_DEFAULT_BASE,
            rate_limit=10,
            rate_window=60,
        ),
        rate_limiter=passthrough_rate_limiter(),
    )


def test_init_uses_openai_chat_provider(fireworks_provider):
    assert isinstance(fireworks_provider, OpenAIChatProvider)
    assert fireworks_provider._api_key == "test_fireworks_key"
    assert fireworks_provider._base_url == FIREWORKS_DEFAULT_BASE


def test_base_url_constant():
    assert FIREWORKS_DEFAULT_BASE == "https://api.fireworks.ai/inference/v1"


def test_build_request_body_openai_chat_shape(fireworks_provider):
    request = MessagesRequest(
        model="accounts/fireworks/models/glm-5p1",
        max_tokens=100,
        messages=[Message(role="user", content="Hello")],
        system="System prompt",
    )

    body = fireworks_provider._build_request_body(
        request, reasoning=reasoning_for(request)
    )

    assert body["model"] == "accounts/fireworks/models/glm-5p1"
    assert body["max_tokens"] == 100
    assert body["messages"] == [
        {"role": "system", "content": "System prompt"},
        {"role": "user", "content": "Hello"},
    ]


def test_build_request_body_default_max_tokens(fireworks_provider):
    request = MessagesRequest(
        model="m",
        messages=[Message(role="user", content="x")],
    )

    body = fireworks_provider._build_request_body(
        request, reasoning=reasoning_for(request)
    )

    assert body["max_tokens"] == ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS


def test_replay_is_independent_of_current_turn_reasoning_control():
    provider = profiled_provider(
        "fireworks",
        ProviderConfig(
            api_key="k",
            base_url=FIREWORKS_DEFAULT_BASE,
            rate_limit=1,
            rate_window=1,
        ),
        rate_limiter=passthrough_rate_limiter(),
    )
    request = MessagesRequest.model_validate(
        {
            "model": "m",
            "messages": [
                {
                    "role": "assistant",
                    "content": [{"type": "thinking", "thinking": "hidden"}],
                }
            ],
        }
    )

    body = provider._build_request_body(request, reasoning=REASONING_OFF)

    assert body["messages"][0]["reasoning_content"] == "hidden"
    assert body["reasoning_effort"] == "none"


def test_build_request_body_preserves_validated_extra_body(fireworks_provider):
    request = MessagesRequest.model_validate(
        {
            "model": "m",
            "messages": [{"role": "user", "content": "x"}],
            "extra_body": {"custom_param": "value"},
        }
    )

    body = fireworks_provider._build_request_body(
        request, reasoning=reasoning_for(request)
    )

    assert body["extra_body"] == {"custom_param": "value"}


def test_build_request_body_rejects_reserved_extra_body_keys(fireworks_provider):
    request = MessagesRequest.model_validate(
        {
            "model": "m",
            "messages": [{"role": "user", "content": "x"}],
            "extra_body": {"temperature": 0.1},
        }
    )

    with pytest.raises(InvalidRequestError, match="extra_body must not override"):
        fireworks_provider._build_request_body(
            request, reasoning=reasoning_for(request)
        )


@pytest.mark.asyncio
async def test_cleanup_closes_openai_client(fireworks_provider):
    fireworks_provider._client = MagicMock()
    fireworks_provider._client.close = AsyncMock()

    await fireworks_provider.cleanup()

    fireworks_provider._client.close.assert_awaited_once()
