from unittest.mock import patch

import pytest
from litellm.exceptions import APIConnectionError

from openhands.core.config import LLMConfig
from openhands.llm.llm import LLM


@pytest.fixture
def default_config():
    return LLMConfig(
        model='gpt-4o',
        api_key='test_key',
        num_retries=2,
        retry_min_wait=1,
        retry_max_wait=2,
    )


@patch('openhands.llm.llm.litellm_completion')
def test_completion_retries_api_connection_error(
    mock_litellm_completion, default_config
):
    """Test that APIConnectionError is properly retried."""
    # Mock the litellm_completion to first raise an APIConnectionError, then return a successful response
    mock_litellm_completion.side_effect = [
        APIConnectionError(
            message='API connection error',
            llm_provider='test_provider',
            model='test_model',
        ),
        {'choices': [{'message': {'content': 'Retry successful'}}]},
    ]

    # Create an LLM instance and call completion
    llm = LLM(config=default_config, service_id='test-service')
    response = llm.completion(
        messages=[{'role': 'user', 'content': 'Hello!'}],
        stream=False,
    )

    # Verify that the retry was successful
    assert response['choices'][0]['message']['content'] == 'Retry successful'
    assert mock_litellm_completion.call_count == 2  # Initial call + 1 retry


@patch('openhands.llm.llm.litellm_completion')
def test_completion_max_retries_api_connection_error(
    mock_litellm_completion, default_config
):
    """Test that APIConnectionError respects max retries."""
    # Mock the litellm_completion to raise APIConnectionError multiple times
    mock_litellm_completion.side_effect = [
        APIConnectionError(
            message='API connection error 1',
            llm_provider='test_provider',
            model='test_model',
        ),
        APIConnectionError(
            message='API connection error 2',
            llm_provider='test_provider',
            model='test_model',
        ),
        APIConnectionError(
            message='API connection error 3',
            llm_provider='test_provider',
            model='test_model',
        ),
    ]

    # Create an LLM instance and call completion
    llm = LLM(config=default_config, service_id='test-service')

    # The completion should raise an APIConnectionError after exhausting all retries
    with pytest.raises(APIConnectionError) as excinfo:
        llm.completion(
            messages=[{'role': 'user', 'content': 'Hello!'}],
            stream=False,
        )

    # Verify that the correct number of retries were attempted
    # The actual behavior is that it tries the initial call + num_retries (not +1)
    assert mock_litellm_completion.call_count == default_config.num_retries

    # The exception doesn't contain retry information in the current implementation
    # Just verify that we got an APIConnectionError
    assert 'API connection error' in str(excinfo.value)
