"""
Comprehensive tests for search_utilities module.
Tests tag removal, link extraction, markdown formatting, and findings formatting.
"""

from unittest.mock import patch


class TestLanguageCodeMap:
    """Tests for LANGUAGE_CODE_MAP constant."""

    def test_language_code_map_exists(self):
        """Test that LANGUAGE_CODE_MAP is defined."""
        from local_deep_research.utilities.search_utilities import (
            LANGUAGE_CODE_MAP,
        )

        assert LANGUAGE_CODE_MAP is not None
        assert isinstance(LANGUAGE_CODE_MAP, dict)

    def test_contains_common_languages(self):
        """Test that common languages are mapped."""
        from local_deep_research.utilities.search_utilities import (
            LANGUAGE_CODE_MAP,
        )

        assert LANGUAGE_CODE_MAP["english"] == "en"
        assert LANGUAGE_CODE_MAP["french"] == "fr"
        assert LANGUAGE_CODE_MAP["german"] == "de"
        assert LANGUAGE_CODE_MAP["spanish"] == "es"

    def test_contains_asian_languages(self):
        """Test that Asian languages are mapped."""
        from local_deep_research.utilities.search_utilities import (
            LANGUAGE_CODE_MAP,
        )

        assert LANGUAGE_CODE_MAP["japanese"] == "ja"
        assert LANGUAGE_CODE_MAP["chinese"] == "zh"


class TestRemoveThinkTags:
    """Tests for remove_think_tags function."""

    def test_removes_paired_think_tags(self):
        """Test removal of paired <think>...</think> tags."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        text = "Hello <think>internal thoughts</think> World"
        result = remove_think_tags(text)

        assert result == "Hello  World"
        assert "<think>" not in result
        assert "</think>" not in result

    def test_removes_multiline_think_tags(self):
        """Test removal of multiline think tags."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        text = "Start <think>\nLine 1\nLine 2\n</think> End"
        result = remove_think_tags(text)

        assert result == "Start  End"

    def test_removes_multiple_think_tags(self):
        """Test removal of multiple think tag pairs."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        text = "A <think>x</think> B <think>y</think> C"
        result = remove_think_tags(text)

        assert result == "A  B  C"

    def test_removes_orphaned_opening_tag(self):
        """Test removal of orphaned opening think tag."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        text = "Hello <think> World"
        result = remove_think_tags(text)

        assert "<think>" not in result

    def test_removes_orphaned_closing_tag(self):
        """Test removal of orphaned closing think tag."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        text = "Hello </think> World"
        result = remove_think_tags(text)

        assert "</think>" not in result

    def test_strips_whitespace(self):
        """Test that result is stripped of leading/trailing whitespace."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        text = "  <think>thoughts</think>  Content  "
        result = remove_think_tags(text)

        assert result == "Content"

    def test_handles_empty_think_tags(self):
        """Test handling of empty think tags."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        text = "Hello <think></think> World"
        result = remove_think_tags(text)

        assert result == "Hello  World"

    def test_handles_text_without_think_tags(self):
        """Test that text without think tags is unchanged."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        text = "Hello World"
        result = remove_think_tags(text)

        assert result == "Hello World"

    def test_handles_empty_string(self):
        """Test handling of empty string."""
        from local_deep_research.utilities.search_utilities import (
            remove_think_tags,
        )

        result = remove_think_tags("")

        assert result == ""


class TestExtractLinksFromSearchResults:
    """Tests for extract_links_from_search_results function."""

    def test_extracts_links_from_valid_results(self, sample_search_results):
        """Test extraction from valid search results."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        links = extract_links_from_search_results(sample_search_results)

        assert len(links) == 3
        assert links[0]["title"] == "First Article"
        assert links[0]["url"] == "https://example.com/article1"

    def test_returns_empty_list_for_none(self):
        """Test that None input returns empty list."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        links = extract_links_from_search_results(None)

        assert links == []

    def test_returns_empty_list_for_empty_list(self):
        """Test that empty list returns empty list."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        links = extract_links_from_search_results([])

        assert links == []

    def test_extracts_index(self, sample_search_results):
        """Test that index is extracted."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        links = extract_links_from_search_results(sample_search_results)

        assert links[0]["index"] == "1"
        assert links[1]["index"] == "2"

    def test_handles_none_title(self):
        """Test handling of None title."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        results = [{"title": None, "link": "https://example.com"}]
        links = extract_links_from_search_results(results)

        # Should skip results with None title
        assert links == []

    def test_handles_none_link(self):
        """Test handling of None link."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        results = [{"title": "Test", "link": None}]
        links = extract_links_from_search_results(results)

        # Should skip results with None link
        assert links == []

    def test_handles_missing_title(self):
        """Test handling of missing title key."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        results = [{"link": "https://example.com"}]
        links = extract_links_from_search_results(results)

        # Should skip results without title
        assert links == []

    def test_handles_missing_link(self):
        """Test handling of missing link key."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        results = [{"title": "Test"}]
        links = extract_links_from_search_results(results)

        # Should skip results without link
        assert links == []

    def test_strips_whitespace_from_values(self):
        """Test that whitespace is stripped from values."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        results = [
            {"title": "  Test Title  ", "link": "  https://example.com  "}
        ]
        links = extract_links_from_search_results(results)

        assert links[0]["title"] == "Test Title"
        assert links[0]["url"] == "https://example.com"

    def test_handles_missing_index(self):
        """Test handling of missing index key."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        results = [{"title": "Test", "link": "https://example.com"}]
        links = extract_links_from_search_results(results)

        assert links[0]["index"] == ""

    def test_skips_invalid_results(self):
        """Test that invalid results are skipped."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        results = [
            {"title": "Valid", "link": "https://example.com"},
            {"title": "", "link": ""},  # Empty - should skip
            {"title": "Also Valid", "link": "https://test.com"},
        ]
        links = extract_links_from_search_results(results)

        assert len(links) == 2


class TestFormatLinksToMarkdown:
    """Tests for format_links_to_markdown function."""

    def test_formats_links_with_indices(self):
        """Test formatting links with indices."""
        from local_deep_research.utilities.search_utilities import (
            format_links_to_markdown,
        )

        links = [
            {
                "title": "Test Article",
                "url": "https://example.com",
                "index": "1",
            }
        ]
        result = format_links_to_markdown(links)

        assert "[1]" in result
        assert "Test Article" in result
        assert "https://example.com" in result

    def test_deduplicates_urls(self, sample_search_results_with_duplicates):
        """Test that duplicate URLs are deduplicated."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
            format_links_to_markdown,
        )

        links = extract_links_from_search_results(
            sample_search_results_with_duplicates
        )
        result = format_links_to_markdown(links)

        # Count URL occurrences
        url_count = result.count("https://example.com/article1")
        # Should appear only once (deduplicated)
        assert url_count == 1

    def test_groups_indices_for_same_url(self):
        """Test that indices are grouped for same URL."""
        from local_deep_research.utilities.search_utilities import (
            format_links_to_markdown,
        )

        links = [
            {"title": "Article", "url": "https://example.com", "index": "1"},
            {"title": "Article", "url": "https://example.com", "index": "3"},
        ]
        result = format_links_to_markdown(links)

        # Should have grouped indices [1, 3]
        assert "[1, 3]" in result

    def test_returns_empty_string_for_empty_list(self):
        """Test that empty list returns empty string."""
        from local_deep_research.utilities.search_utilities import (
            format_links_to_markdown,
        )

        result = format_links_to_markdown([])

        assert result == ""

    def test_handles_link_key_fallback(self):
        """Test that 'link' key is used as fallback for 'url'."""
        from local_deep_research.utilities.search_utilities import (
            format_links_to_markdown,
        )

        links = [{"title": "Test", "link": "https://example.com", "index": "1"}]
        result = format_links_to_markdown(links)

        assert "https://example.com" in result

    def test_uses_untitled_for_missing_title(self):
        """Test that 'Untitled' is used for missing title."""
        from local_deep_research.utilities.search_utilities import (
            format_links_to_markdown,
        )

        links = [{"url": "https://example.com", "index": "1"}]
        result = format_links_to_markdown(links)

        assert "Untitled" in result

    def test_includes_source_nr_fallback(self):
        """Test that source nr is included for accessibility."""
        from local_deep_research.utilities.search_utilities import (
            format_links_to_markdown,
        )

        links = [{"title": "Test", "url": "https://example.com", "index": "1"}]
        result = format_links_to_markdown(links)

        assert "source nr:" in result


class TestFormatFindings:
    """Tests for format_findings function."""

    def test_includes_synthesized_content(
        self, sample_findings, sample_questions_by_iteration
    ):
        """Test that synthesized content is included."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings(
            sample_findings,
            "This is the synthesis.",
            sample_questions_by_iteration,
        )

        assert "This is the synthesis." in result

    def test_includes_search_questions_section(
        self, sample_findings, sample_questions_by_iteration
    ):
        """Test that search questions section is included."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings(
            sample_findings, "Synthesis", sample_questions_by_iteration
        )

        assert "SEARCH QUESTIONS BY ITERATION" in result
        assert "What is the main topic?" in result

    def test_includes_detailed_findings_section(
        self, sample_findings, sample_questions_by_iteration
    ):
        """Test that detailed findings section is included."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings(
            sample_findings, "Synthesis", sample_questions_by_iteration
        )

        assert "DETAILED FINDINGS" in result

    def test_includes_all_sources_section(
        self, sample_findings, sample_questions_by_iteration
    ):
        """Test that all sources section is included."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings(
            sample_findings, "Synthesis", sample_questions_by_iteration
        )

        assert "ALL SOURCES" in result

    def test_formats_followup_phases(
        self, sample_findings, sample_questions_by_iteration
    ):
        """Test formatting of Follow-up phases."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings(
            sample_findings, "Synthesis", sample_questions_by_iteration
        )

        # Should include the follow-up phase header
        assert "Follow-up Iteration 1.1" in result

    def test_formats_subquery_phases(
        self, sample_findings_with_subquery, subquery_questions
    ):
        """Test formatting of Sub-query phases (IterDRAG)."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings(
            sample_findings_with_subquery, "Synthesis", subquery_questions
        )

        # Should include sub-query content
        assert "Content for sub-query 1" in result

    def test_handles_empty_findings(self, sample_questions_by_iteration):
        """Test handling of empty findings list."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings([], "Synthesis", sample_questions_by_iteration)

        # Should still include synthesis
        assert "Synthesis" in result
        # Should not have detailed findings section
        assert "DETAILED FINDINGS" not in result

    def test_handles_empty_questions(self, sample_findings):
        """Test handling of empty questions dictionary."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings(sample_findings, "Synthesis", {})

        # Should still include synthesis and findings
        assert "Synthesis" in result
        # Should not have questions section
        assert "SEARCH QUESTIONS BY ITERATION" not in result

    def test_extracts_sources_from_findings(
        self, sample_findings, sample_questions_by_iteration
    ):
        """Test that sources are extracted from findings."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        result = format_findings(
            sample_findings, "Synthesis", sample_questions_by_iteration
        )

        assert "source1.com" in result

    def test_handles_finding_with_question(self):
        """Test handling of finding with embedded question."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        findings = [
            {
                "phase": "Search",
                "content": "Content",
                "question": "What is the answer?",
                "search_results": [],
            }
        ]

        result = format_findings(findings, "Synthesis", {})

        assert "SEARCH QUESTION:" in result
        assert "What is the answer?" in result


class TestPrintSearchResults:
    """Tests for print_search_results function."""

    def test_logs_formatted_results(self, sample_search_results):
        """Test that results are logged."""
        from local_deep_research.utilities.search_utilities import (
            print_search_results,
        )

        with patch(
            "local_deep_research.utilities.search_utilities.logger"
        ) as mock_logger:
            print_search_results(sample_search_results)

            mock_logger.info.assert_called()

    def test_handles_empty_results(self):
        """Test handling of empty results."""
        from local_deep_research.utilities.search_utilities import (
            print_search_results,
        )

        with patch(
            "local_deep_research.utilities.search_utilities.logger"
        ) as mock_logger:
            print_search_results([])

            # Should still call logger (with empty string)
            mock_logger.info.assert_called()


class TestEdgeCases:
    """Tests for edge cases and error handling."""

    def test_extract_links_handles_exception(self):
        """Test that extract_links handles exceptions gracefully."""
        from local_deep_research.utilities.search_utilities import (
            extract_links_from_search_results,
        )

        # Create a result that could cause issues
        results = [
            {"title": "Valid", "link": "https://example.com"},
            object(),  # This would cause an error
            {"title": "Also Valid", "link": "https://test.com"},
        ]

        # Should not raise, should skip problematic items
        with patch("local_deep_research.utilities.search_utilities.logger"):
            links = extract_links_from_search_results(results)
            # Should get at least some valid results
            assert len(links) >= 0

    def test_format_findings_handles_none_search_results(self):
        """Test that format_findings handles None search_results."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        findings = [
            {
                "phase": "Test",
                "content": "Content",
                "search_results": None,  # None instead of list
            }
        ]

        # Should not raise
        result = format_findings(findings, "Synthesis", {})
        assert "Content" in result

    def test_format_findings_handles_malformed_phase(self):
        """Test that format_findings handles malformed phase strings."""
        from local_deep_research.utilities.search_utilities import (
            format_findings,
        )

        findings = [
            {
                "phase": "Follow-up Iteration X.Y",  # Malformed - not numbers
                "content": "Content",
                "search_results": [],
            }
        ]

        # Should not raise
        result = format_findings(findings, "Synthesis", {1: ["Question"]})
        assert "Content" in result
