"""
Unit tests for the Bedrock integration helpers.
No AWS credentials or backend required.
"""
from visibe.integrations.bedrock import (
    _extract_bedrock_prompt,
    _extract_bedrock_output,
    _extract_bedrock_usage,
    _extract_bedrock_tool_calls,
    _extract_bedrock_model,
    _detect_provider_from_model,
)
from visibe.client import _is_bedrock_client


# ------------------------------------------------------------------
# Prompt extraction
# ------------------------------------------------------------------

def test_extract_bedrock_prompt_basic():
    kwargs = {
        "messages": [
            {"role": "user", "content": [{"text": "What is 2 + 2?"}]}
        ]
    }
    result = _extract_bedrock_prompt(kwargs)
    assert result == "What is 2 + 2?"


def test_extract_bedrock_prompt_with_system():
    kwargs = {
        "system": [{"text": "You are a math tutor."}],
        "messages": [
            {"role": "user", "content": [{"text": "What is 2 + 2?"}]}
        ],
    }
    result = _extract_bedrock_prompt(kwargs)
    assert "[system] You are a math tutor." in result
    assert "What is 2 + 2?" in result


def test_extract_bedrock_prompt_empty():
    result = _extract_bedrock_prompt({})
    assert result == ""


def test_extract_bedrock_prompt_multi_turn_returns_last():
    kwargs = {
        "messages": [
            {"role": "user", "content": [{"text": "Hello"}]},
            {"role": "assistant", "content": [{"text": "Hi there"}]},
            {"role": "user", "content": [{"text": "What is 3 + 3?"}]},
        ]
    }
    result = _extract_bedrock_prompt(kwargs)
    # Should return the last user message
    assert "3 + 3" in result


# ------------------------------------------------------------------
# Output extraction
# ------------------------------------------------------------------

def test_extract_bedrock_output_text():
    response = {
        "output": {
            "message": {
                "role": "assistant",
                "content": [{"text": "The answer is 4."}],
            }
        },
        "usage": {"inputTokens": 10, "outputTokens": 5},
    }
    result = _extract_bedrock_output(response)
    assert result == "The answer is 4."


def test_extract_bedrock_output_empty_response():
    result = _extract_bedrock_output({})
    assert result == ""


def test_extract_bedrock_output_multiple_content_blocks():
    response = {
        "output": {
            "message": {
                "role": "assistant",
                "content": [
                    {"text": "First part."},
                    {"text": " Second part."},
                ],
            }
        }
    }
    result = _extract_bedrock_output(response)
    assert "First part" in result


# ------------------------------------------------------------------
# Usage extraction
# ------------------------------------------------------------------

def test_extract_bedrock_usage_standard():
    response = {"usage": {"inputTokens": 150, "outputTokens": 42}}
    input_t, output_t = _extract_bedrock_usage(response)
    assert input_t == 150
    assert output_t == 42


def test_extract_bedrock_usage_missing():
    input_t, output_t = _extract_bedrock_usage({})
    assert input_t == 0
    assert output_t == 0


def test_extract_bedrock_usage_zero_tokens():
    response = {"usage": {"inputTokens": 0, "outputTokens": 0}}
    input_t, output_t = _extract_bedrock_usage(response)
    assert input_t == 0
    assert output_t == 0


# ------------------------------------------------------------------
# Tool call extraction
# ------------------------------------------------------------------

def test_extract_bedrock_tool_calls_single():
    response = {
        "output": {
            "message": {
                "role": "assistant",
                "content": [
                    {
                        "toolUse": {
                            "toolUseId": "abc123",
                            "name": "get_weather",
                            "input": {"city": "Paris"},
                        }
                    },
                    {"text": "Let me check the weather."},
                ],
            }
        }
    }
    tools = _extract_bedrock_tool_calls(response)
    assert len(tools) == 1
    assert tools[0]["tool_name"] == "get_weather"
    assert tools[0]["status"] == "success"
    assert "Paris" in tools[0]["input"]


def test_extract_bedrock_tool_calls_none():
    response = {
        "output": {
            "message": {
                "role": "assistant",
                "content": [{"text": "No tool needed."}],
            }
        }
    }
    tools = _extract_bedrock_tool_calls(response)
    assert tools == []


def test_extract_bedrock_tool_calls_empty_response():
    tools = _extract_bedrock_tool_calls({})
    assert tools == []


# ------------------------------------------------------------------
# Model ID extraction
# ------------------------------------------------------------------

def test_extract_bedrock_model_simple():
    kwargs = {"modelId": "anthropic.claude-3-haiku-20240307-v1:0"}
    result = _extract_bedrock_model(kwargs)
    assert result == "anthropic.claude-3-haiku-20240307-v1:0"


def test_extract_bedrock_model_arn():
    kwargs = {
        "modelId": (
            "arn:aws:bedrock:us-east-1:123456789:"
            "inference-profile/anthropic.claude-3-haiku-20240307-v1:0"
        )
    }
    result = _extract_bedrock_model(kwargs)
    assert result == "anthropic.claude-3-haiku-20240307-v1:0"


def test_extract_bedrock_model_missing():
    result = _extract_bedrock_model({})
    assert result == "unknown"


# ------------------------------------------------------------------
# Provider detection
# ------------------------------------------------------------------

def test_detect_provider_anthropic():
    assert _detect_provider_from_model("anthropic.claude-3-haiku-20240307-v1:0") == "anthropic"


def test_detect_provider_meta():
    assert _detect_provider_from_model("meta.llama3-70b-instruct-v1:0") == "meta"


def test_detect_provider_mistral():
    assert _detect_provider_from_model("mistral.mistral-large-2402-v1:0") == "mistral"


def test_detect_provider_amazon():
    assert _detect_provider_from_model("amazon.nova-pro-v1:0") == "amazon"


def test_detect_provider_cohere():
    assert _detect_provider_from_model("cohere.command-r-plus-v1:0") == "cohere"


def test_detect_provider_ai21():
    assert _detect_provider_from_model("ai21.jamba-1.5-large-v1:0") == "ai21"


def test_detect_provider_unknown():
    assert _detect_provider_from_model("unknown-model") == "bedrock"


# ------------------------------------------------------------------
# Client type detection
# ------------------------------------------------------------------

def test_is_bedrock_client_rejects_string():
    assert not _is_bedrock_client("a string")


def test_is_bedrock_client_rejects_int():
    assert not _is_bedrock_client(42)


def test_is_bedrock_client_rejects_none():
    assert not _is_bedrock_client(None)


def test_is_bedrock_client_rejects_object():
    assert not _is_bedrock_client(object())
