"""
Unit tests for OpenAI integration helpers.
No openai package or network required — tests pure helper functions.
"""
import types
from visibe.integrations.openai import (
    _extract_prompt,
    _extract_tool_calls,
    _extract_response_prompt,
    _extract_response_output_text,
    _extract_response_tools,
    _has_responses_api,
)


# ------------------------------------------------------------------
# _extract_prompt
# ------------------------------------------------------------------

def test_extract_prompt_simple():
    messages = [{"role": "user", "content": "Hello!"}]
    assert _extract_prompt(messages) == "Hello!"


def test_extract_prompt_multi_turn_returns_last_user():
    messages = [
        {"role": "user", "content": "First question"},
        {"role": "assistant", "content": "First answer"},
        {"role": "user", "content": "Second question"},
    ]
    assert _extract_prompt(messages) == "Second question"


def test_extract_prompt_no_user_message():
    messages = [{"role": "system", "content": "You are helpful."}]
    assert _extract_prompt(messages) == ""


def test_extract_prompt_empty_list():
    assert _extract_prompt([]) == ""


def test_extract_prompt_multimodal_content():
    messages = [
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "What is this?"},
                {"type": "image_url", "image_url": {"url": "..."}},
            ],
        }
    ]
    result = _extract_prompt(messages)
    assert "What is this?" in result


def test_extract_prompt_truncated_to_500():
    long_content = "x" * 1000
    messages = [{"role": "user", "content": long_content}]
    result = _extract_prompt(messages)
    assert len(result) <= 500


# ------------------------------------------------------------------
# _extract_tool_calls
# ------------------------------------------------------------------

def _make_response(tool_calls=None, content="Hello"):
    """Build a minimal mock OpenAI response."""
    tc_list = []
    for name, args in (tool_calls or []):
        fn = types.SimpleNamespace(name=name, arguments=args)
        tc_list.append(types.SimpleNamespace(function=fn))

    msg = types.SimpleNamespace(
        content=content if not tc_list else None,
        tool_calls=tc_list if tc_list else None,
    )
    choice = types.SimpleNamespace(message=msg)
    return types.SimpleNamespace(choices=[choice])


def test_extract_tool_calls_none():
    response = _make_response(content="I can help with that.")
    tools = _extract_tool_calls(response)
    assert tools == []


def test_extract_tool_calls_single():
    response = _make_response(tool_calls=[("get_weather", '{"city": "Paris"}')])
    tools = _extract_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_tool_calls_multiple():
    response = _make_response(tool_calls=[
        ("search", '{"query": "python"}'),
        ("calculate", '{"expr": "2+2"}'),
    ])
    tools = _extract_tool_calls(response)
    assert len(tools) == 2
    names = {t["tool_name"] for t in tools}
    assert names == {"search", "calculate"}


def test_extract_tool_calls_no_choices():
    response = types.SimpleNamespace(choices=[])
    tools = _extract_tool_calls(response)
    assert tools == []


# ------------------------------------------------------------------
# _extract_response_prompt
# ------------------------------------------------------------------

def test_extract_response_prompt_string():
    result = _extract_response_prompt("Tell me a joke.")
    assert result == "Tell me a joke."


def test_extract_response_prompt_list_finds_user():
    input_data = [
        {"role": "system", "content": "Be helpful."},
        {"role": "user", "content": "What is 2+2?"},
    ]
    result = _extract_response_prompt(input_data)
    assert "2+2" in result


def test_extract_response_prompt_string_truncated():
    long_input = "x" * 2000
    result = _extract_response_prompt(long_input)
    assert len(result) <= 1000


def test_extract_response_prompt_non_string_fallback():
    result = _extract_response_prompt({"role": "user"})
    assert isinstance(result, str)


# ------------------------------------------------------------------
# _extract_response_output_text
# ------------------------------------------------------------------

def _make_response_api_response(text):
    """Build a minimal mock Responses API response."""
    content_item = types.SimpleNamespace(type="output_text", text=text)
    output_item = types.SimpleNamespace(type="message", content=[content_item])
    return types.SimpleNamespace(output=[output_item])


def test_extract_response_output_text_basic():
    response = _make_response_api_response("The answer is 42.")
    result = _extract_response_output_text(response)
    assert result == "The answer is 42."


def test_extract_response_output_text_empty():
    response = types.SimpleNamespace(output=[])
    result = _extract_response_output_text(response)
    assert result == ""


def test_extract_response_output_text_no_output_attr():
    response = types.SimpleNamespace()
    result = _extract_response_output_text(response)
    assert result == ""


# ------------------------------------------------------------------
# _extract_response_tools
# ------------------------------------------------------------------

def test_extract_response_tools_function_call():
    tool_item = types.SimpleNamespace(
        type="function_call",
        name="get_weather",
        arguments='{"city": "NYC"}',
        call_id="call_123",
    )
    response = types.SimpleNamespace(output=[tool_item])
    tools = _extract_response_tools(response)
    assert len(tools) == 1
    assert tools[0]["tool_name"] == "get_weather"
    assert tools[0]["status"] == "success"


def test_extract_response_tools_web_search():
    tool_item = types.SimpleNamespace(type="web_search_call", status="completed")
    response = types.SimpleNamespace(output=[tool_item])
    tools = _extract_response_tools(response)
    assert len(tools) == 1
    assert tools[0]["tool_name"] == "web_search"


def test_extract_response_tools_none():
    response = types.SimpleNamespace(output=[])
    tools = _extract_response_tools(response)
    assert tools == []


# ------------------------------------------------------------------
# _has_responses_api
# ------------------------------------------------------------------

def test_has_responses_api_true():
    responses = types.SimpleNamespace(create=lambda: None)
    client = types.SimpleNamespace(responses=responses)
    assert _has_responses_api(client) is True


def test_has_responses_api_false_no_attr():
    client = types.SimpleNamespace()
    assert _has_responses_api(client) is False


def test_has_responses_api_false_no_create():
    client = types.SimpleNamespace(responses=types.SimpleNamespace())
    assert _has_responses_api(client) is False
