"""
Performance tests for citation formatter to ensure it handles large documents efficiently.
"""

import time
import pytest
from local_deep_research.text_optimization.citation_formatter import (
    CitationFormatter,
    CitationMode,
)


class TestCitationPerformance:
    """Test performance of citation formatter with large documents."""

    def test_many_citations_performance(self):
        """Test performance with many citations."""
        # Generate content with 1000 citations
        citations = []
        sources = []

        for i in range(1, 1001):
            # Mix up citation patterns
            if i % 3 == 0:
                citations.append(f"Multiple [{i}] citations [{i}] here [{i}]")
            else:
                citations.append(f"Single citation [{i}]")

            sources.append(f"""[{i}] Source {i} Title
URL: https://example{i % 100}.com/paper/{i}""")

        content = f"""# Large Document Performance Test

{" ".join(citations)}

## Sources

{chr(10).join(sources)}"""

        formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)

        start_time = time.time()
        result = formatter.format_document(content)
        end_time = time.time()

        processing_time = end_time - start_time

        # Should complete in reasonable time (less than 5 seconds for 1000 citations)
        assert processing_time < 5.0, (
            f"Processing took {processing_time:.2f}s, which is too slow"
        )

        # Should have formatted all citations
        for i in range(100):
            assert f"[example{i}.com]" in result

    def test_long_document_performance(self):
        """Test performance with very long documents."""
        # Create a 100KB document
        paragraphs = []

        for i in range(200):
            paragraph = f"""
This is paragraph {i} with some citations [{i % 50 + 1}] and more text to make
it longer. The citation [{i % 50 + 1}] appears multiple times in this paragraph.
Sometimes we reference [{(i + 1) % 50 + 1}] as well. This helps test performance
with realistic document sizes and citation patterns.
"""
            paragraphs.append(paragraph)

        # Add sources
        sources = []
        for i in range(1, 51):
            sources.append(f"""[{i}] Academic Paper {i}
URL: https://journal{i % 10}.com/article/{i}""")

        content = f"""# Very Long Document

{"".join(paragraphs)}

## Sources

{chr(10).join(sources)}"""

        formatter = CitationFormatter(mode=CitationMode.DOMAIN_ID_HYPERLINKS)

        start_time = time.time()
        result = formatter.format_document(content)
        end_time = time.time()

        processing_time = end_time - start_time

        # Should handle large documents efficiently
        assert processing_time < 10.0, (
            f"Processing took {processing_time:.2f}s for large document"
        )

        # Verify formatting worked
        assert "[journal0.com" in result
        assert "[journal9.com" in result

    def test_deeply_nested_markdown_performance(self):
        """Test performance with deeply nested markdown structures."""
        # Create nested lists with citations
        nested_content = """# Document with Nested Structure

"""

        for i in range(10):
            nested_content += f"{'  ' * i}- Level {i} item [{i + 1}]\n"
            nested_content += (
                f"{'  ' * i}  - Sub-item with citation [{i + 11}]\n"
            )
            nested_content += f"{'  ' * i}    - Deep sub-item [{i + 21}]\n"

        # Add complex markdown
        nested_content += """
| Header 1 [31] | Header 2 [32] | Header 3 [33] |
|---------------|---------------|---------------|
| Cell [34]     | Cell [35]     | Cell [36]     |
| Cell [37]     | Cell [38]     | Cell [39]     |

> Blockquote level 1 [40]
>> Blockquote level 2 [41]
>>> Blockquote level 3 [42]

"""

        # Add sources
        sources = []
        for i in range(1, 43):
            sources.append(
                f"[{i}] Source {i}\nURL: https://site{i % 5}.com/{i}"
            )

        content = nested_content + "\n## Sources\n\n" + "\n\n".join(sources)

        formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)

        start_time = time.time()
        result = formatter.format_document(content)
        end_time = time.time()

        processing_time = end_time - start_time

        # Should handle complex structure efficiently
        assert processing_time < 2.0, (
            f"Processing complex structure took {processing_time:.2f}s"
        )

        # Verify citations in various contexts were formatted
        assert "[site0.com]" in result
        assert "[site4.com]" in result

    def test_repeated_formatting_performance(self):
        """Test performance when formatting the same document multiple times."""
        content = """# Document

Citations [1] and [2] and [3].

## Sources

[1] First
URL: https://first.com

[2] Second
URL: https://second.com

[3] Third
URL: https://third.com"""

        formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)

        # Format 100 times
        start_time = time.time()
        for _ in range(100):
            formatter.format_document(content)
        end_time = time.time()

        total_time = end_time - start_time
        avg_time = total_time / 100

        # Average time should be very fast
        assert avg_time < 0.01, (
            f"Average formatting time {avg_time:.4f}s is too slow"
        )

    def test_citation_modes_performance_comparison(self):
        """Compare performance across different citation modes."""
        # Create test document
        citations = [f"Citation [{i}]" for i in range(1, 101)]
        sources = [
            f"[{i}] Source {i}\nURL: https://domain{i % 20}.com/{i}"
            for i in range(1, 101)
        ]

        content = f"""# Performance Test

{" ".join(citations)}

## Sources

{chr(10).join(sources)}"""

        modes = [
            CitationMode.NUMBER_HYPERLINKS,
            CitationMode.DOMAIN_HYPERLINKS,
            CitationMode.DOMAIN_ID_HYPERLINKS,
            CitationMode.DOMAIN_ID_ALWAYS_HYPERLINKS,
            CitationMode.NO_HYPERLINKS,
        ]

        times = {}

        for mode in modes:
            formatter = CitationFormatter(mode=mode)

            start_time = time.time()
            formatter.format_document(content)
            end_time = time.time()

            times[mode.value] = end_time - start_time

        # All modes should complete quickly
        for mode_name, duration in times.items():
            assert duration < 1.0, f"Mode {mode_name} took {duration:.3f}s"

        # Performance shouldn't vary drastically between modes
        # Exclude NO_HYPERLINKS from comparison as it does minimal processing
        times_without_no_hyperlinks = {
            k: v for k, v in times.items() if k != "no_hyperlinks"
        }

        if times_without_no_hyperlinks:
            max_time = max(times_without_no_hyperlinks.values())
            min_time = min(times_without_no_hyperlinks.values())
            # Allow more variance as some modes do more work
            if min_time > 0:
                assert max_time / min_time < 10.0, (
                    f"Performance varies too much between modes (excluding no_hyperlinks): {times_without_no_hyperlinks}"
                )

        # Verify NO_HYPERLINKS is indeed the fastest
        if "no_hyperlinks" in times:
            no_hyperlinks_time = times["no_hyperlinks"]
            other_times = [v for k, v in times.items() if k != "no_hyperlinks"]
            if other_times:
                # NO_HYPERLINKS should be faster or comparable to the fastest other mode
                assert no_hyperlinks_time <= min(other_times) * 2, (
                    "NO_HYPERLINKS mode should be among the fastest modes"
                )

    def test_memory_efficiency_large_content(self):
        """Test that formatter doesn't use excessive memory."""
        # Create a large document (10MB+)
        large_text = "This is a test paragraph. " * 10000

        content = f"""# Large Document

{large_text}

Citation at the end [1].

## Sources

[1] Only Source
URL: https://example.com/source"""

        formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)

        # Should handle large content without issues
        try:
            start_time = time.time()
            result = formatter.format_document(content)
            end_time = time.time()

            # Should complete even with large content
            assert "[example.com]" in result
            assert end_time - start_time < 5.0

        except MemoryError:
            pytest.fail("Formatter used too much memory")

    @pytest.mark.parametrize("num_sources", [10, 50, 100, 500])
    def test_scaling_with_source_count(self, num_sources):
        """Test how performance scales with number of sources."""
        # Create content with varying number of sources
        citations = []
        sources = []

        # Each source cited 3 times
        for i in range(1, num_sources + 1):
            citations.extend([f"[{i}]", f"[{i}]", f"[{i}]"])
            sources.append(f"[{i}] Source {i}\nURL: https://example.com/{i}")

        content = f"""# Scaling Test

Citations: {" ".join(citations)}

## Sources

{chr(10).join(sources)}"""

        formatter = CitationFormatter(mode=CitationMode.DOMAIN_ID_HYPERLINKS)

        start_time = time.time()
        formatter.format_document(content)
        end_time = time.time()

        processing_time = end_time - start_time

        # Time should scale roughly linearly with source count
        expected_max_time = num_sources * 0.01  # 10ms per source max
        assert processing_time < expected_max_time, (
            f"Processing {num_sources} sources took {processing_time:.3f}s, "
            f"expected < {expected_max_time:.3f}s"
        )

    def test_regex_performance_edge_cases(self):
        """Test performance with content that might cause regex issues."""
        # Create content with patterns that could cause backtracking
        tricky_patterns = [
            "[" * 100 + "1" + "]" * 100,  # Many brackets
            "[[[[1]]]]",  # Nested brackets
            "[1][2][3][4][5]" * 50,  # Many consecutive citations
            "[1] " + "." * 1000 + " [2]",  # Long spans between citations
        ]

        sources = """
[1] Source 1
URL: https://one.com

[2] Source 2
URL: https://two.com

[3] Source 3
URL: https://three.com

[4] Source 4
URL: https://four.com

[5] Source 5
URL: https://five.com"""

        for pattern in tricky_patterns:
            content = f"# Test\n\n{pattern}\n\n## Sources\n{sources}"

            formatter = CitationFormatter(mode=CitationMode.DOMAIN_HYPERLINKS)

            start_time = time.time()
            try:
                formatter.format_document(content)
                end_time = time.time()

                # Should complete quickly even with tricky patterns
                assert end_time - start_time < 1.0

            except Exception as e:
                pytest.fail(f"Failed on pattern: {pattern[:50]}... Error: {e}")
