"""
Fuzz tests for utility functions using Hypothesis.

These tests verify that text processing and parsing functions
handle arbitrary input without crashing.
"""

from hypothesis import given, settings, strategies as st

from local_deep_research.utilities.search_utilities import (
    extract_links_from_search_results,
    format_links_to_markdown,
    remove_think_tags,
)


class TestSearchUtilitiesFuzzing:
    """Fuzz tests for search utility functions."""

    @given(text=st.text(max_size=10000))
    @settings(max_examples=200)
    def test_remove_think_tags_no_crash(self, text):
        """Test that remove_think_tags never crashes on arbitrary input."""
        result = remove_think_tags(text)
        # Should always return a string
        assert isinstance(result, str)

    @given(
        text=st.text(max_size=5000).map(
            lambda x: f"<think>{x}</think>content<think>more{x}</think>"
        )
    )
    @settings(max_examples=100)
    def test_remove_think_tags_removes_tags(self, text):
        """Test that think tags are properly removed."""
        result = remove_think_tags(text)
        assert "<think>" not in result
        assert "</think>" not in result

    @given(
        search_results=st.lists(
            st.fixed_dictionaries(
                {
                    "title": st.one_of(st.none(), st.text(max_size=500)),
                    "link": st.one_of(st.none(), st.text(max_size=1000)),
                    "index": st.one_of(st.none(), st.text(max_size=50)),
                }
            ),
            max_size=100,
        )
    )
    @settings(max_examples=200)
    def test_extract_links_no_crash(self, search_results):
        """Test that extract_links_from_search_results handles arbitrary dicts."""
        result = extract_links_from_search_results(search_results)
        # Should always return a list
        assert isinstance(result, list)
        # All items should be dicts with expected keys
        for item in result:
            assert isinstance(item, dict)
            assert "title" in item
            assert "url" in item

    @given(
        links=st.lists(
            st.fixed_dictionaries(
                {
                    "title": st.text(max_size=200),
                    "url": st.text(max_size=500),
                    "index": st.text(max_size=20),
                }
            ),
            max_size=50,
        )
    )
    @settings(max_examples=100)
    def test_format_links_to_markdown_no_crash(self, links):
        """Test that format_links_to_markdown handles arbitrary link data."""
        result = format_links_to_markdown(links)
        # Should always return a string
        assert isinstance(result, str)

    @given(search_results=st.just([]))
    def test_extract_links_empty_input(self, search_results):
        """Test that empty input returns empty list."""
        result = extract_links_from_search_results(search_results)
        assert result == []

    @given(search_results=st.just(None))
    def test_extract_links_none_input(self, search_results):
        """Test that None input returns empty list."""
        result = extract_links_from_search_results(search_results)
        assert result == []

    @given(
        search_results=st.lists(
            st.fixed_dictionaries(
                {
                    "unexpected_key": st.text(max_size=100),
                    "another_key": st.integers(),
                }
            ),
            max_size=20,
        )
    )
    @settings(max_examples=50)
    def test_extract_links_missing_keys(self, search_results):
        """Test handling of dicts with missing expected keys."""
        result = extract_links_from_search_results(search_results)
        # Should not crash, returns empty list when required keys missing
        assert isinstance(result, list)
