"""Regression tests for _extract_tool_arg_preview function.

Tests the fix for preview semantics:
1) first arg non-string, later string -> later string chosen
2) no string args -> empty string
3) long string truncation behavior (>72 chars)
"""

import pytest
from pydantic_ai.messages import ToolCallPart

from anima.shell.agent_interact import _extract_tool_arg_preview


class TestExtractToolArgPreview:
    """Tests for _extract_tool_arg_preview function."""

    def test_first_arg_non_string_later_string(self) -> None:
        """Regression: first arg non-string, later string -> later string chosen."""
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args={"query": 12345, "text": "hello world"},
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == "hello world"

    def test_first_arg_string_returns_first_string(self) -> None:
        """First string argument should be returned."""
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args={"text": "first", "other": "second"},
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == "first"

    def test_no_string_args_returns_empty(self) -> None:
        """Regression: no string args -> empty string."""
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args={"count": 42, "enabled": True, "ratio": 3.14},
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == ""

    def test_long_string_truncation(self) -> None:
        """Regression: long string >72 chars -> truncated with ellipsis."""
        long_string = "x" * 100
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args={"text": long_string},
        )
        result = _extract_tool_arg_preview(tool_call)
        assert len(result) == 75  # 72 chars + "..."
        assert result.endswith("...")
        assert result == "x" * 72 + "..."

    def test_exactly_72_chars_no_truncation(self) -> None:
        """String exactly 72 chars should not be truncated."""
        exactly_72 = "a" * 72
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args={"text": exactly_72},
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == exactly_72

    def test_empty_args_returns_empty(self) -> None:
        """Empty args should return empty string."""
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args={},
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == ""

    def test_none_args_returns_empty(self) -> None:
        """None args should return empty string."""
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args=None,
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == ""

    def test_mixed_args_with_string_before_non_string(self) -> None:
        """String argument appears before non-string, should return the string."""
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args={"message": "hello", "count": 5},
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == "hello"

    def test_non_string_args_then_string_later(self) -> None:
        """Non-string args first, then string later - should find the string."""
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args={"id": 1, "name": "test_name", "value": 3.5},
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == "test_name"

    def test_string_args_raw_json_string_input(self) -> None:
        """Raw JSON string args get parsed by args_as_dict()."""
        # Note: args_as_dict() parses JSON strings, so '{"key": "value"}'
        # becomes {'key': 'value'}, and the first string value 'value' is returned
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args='{"key": "value"}',
        )
        result = _extract_tool_arg_preview(tool_call)
        assert result == "value"

    def test_long_raw_string_truncation(self) -> None:
        """Long raw string should be truncated."""
        long_string = "y" * 100
        tool_call = ToolCallPart(
            tool_name="test_tool",
            args=long_string,
        )
        result = _extract_tool_arg_preview(tool_call)
        assert len(result) == 75  # 72 + "..."
        assert result.endswith("...")
