from __future__ import annotations

from unittest.mock import MagicMock, patch

from behave import given, then, when

from cleveragents.providers.llm.anthropic_provider import AnthropicChatProvider

# Shared step definitions (I have sample provider domain inputs, plan generation graph steps)
# are registered by features/steps/provider_shared_steps.py which Behave loads automatically.
# Helper functions are duplicated here to avoid cross-module import issues with Behave's exec_file.


def _register_cleanup(context, cleanup):
    if hasattr(context, "add_cleanup"):
        context.add_cleanup(cleanup)
    else:
        cleanup_handlers = getattr(context, "_cleanup_handlers", [])
        cleanup_handlers.append(cleanup)
        context._cleanup_handlers = cleanup_handlers


@then('the Anthropic provider creation should fail with "{message}"')
def step_assert_anthropic_provider_error_no_error_keyword(context, message):
    """Variant of the error assertion step without the word 'error' in the step text."""
    error = getattr(context, "anthropic_provider_error", None)
    assert error is not None, "Expected the provider to raise an error"
    assert isinstance(error, ValueError)
    assert str(error) == message


@when(
    'I create an Anthropic chat provider with API key "{api_key}" and model "{model_id}" with custom overrides'
)
def step_create_anthropic_provider_with_custom_overrides(context, api_key, model_id):
    patcher = patch("cleveragents.providers.llm.anthropic_provider.ChatAnthropic")
    context.chat_anthropic_patcher = patcher
    mock_chat_anthropic_class = patcher.start()
    _register_cleanup(context, patcher.stop)
    mock_chat_anthropic_instance = MagicMock(name="ChatAnthropicInstance")
    mock_chat_anthropic_instance.get_num_tokens = MagicMock(return_value=0)
    mock_chat_anthropic_class.return_value = mock_chat_anthropic_instance

    # Store custom overrides for later assertion
    context.anthropic_custom_overrides = {"temperature": 0.5, "max_tokens": 1024}

    context.provider = AnthropicChatProvider(
        api_key=api_key,
        model=model_id,
        **context.anthropic_custom_overrides,
    )
    context.chat_anthropic_class = mock_chat_anthropic_class
    context.chat_anthropic_instance = mock_chat_anthropic_instance


@then("the Anthropic provider should apply the custom overrides to ChatAnthropic")
def step_assert_anthropic_custom_overrides(context):
    assert context.chat_anthropic_call is not None, (
        "ChatAnthropic should have been called"
    )
    _, call_kwargs = context.chat_anthropic_call
    overrides = getattr(context, "anthropic_custom_overrides", {})
    for key, value in overrides.items():
        assert key in call_kwargs, f"Expected {key} in ChatAnthropic kwargs"
        assert call_kwargs[key] == value, (
            f"Expected ChatAnthropic kwargs[{key!r}] to equal {value!r}"
        )


@given("the Google provider token estimator returns {token_count:d} tokens")
def step_google_token_estimator(context, token_count):
    context.google_token_count = token_count


@then("the Google provider response token count should equal {expected:d}")
def step_assert_google_token_count(context, expected):
    assert context.response is not None
    assert context.response.token_count == expected
