"""
Tests for citation export formats (RIS, LaTeX, Quarto) to ensure
they handle edge cases correctly.
"""

import pytest
from local_deep_research.text_optimization.citation_formatter import (
    CitationFormatter,
    CitationMode,
    RISExporter,
    LaTeXExporter,
    QuartoExporter,
)


class TestCitationExportFormats:
    """Test various export formats for citations."""

    def test_ris_export_with_multiple_citations(self):
        """Test RIS export handles multiple citations to same source."""
        content = """# Research Report

Multiple citations [1] to same [1] source [1]. And another [2].

## Sources

[1] Machine Learning Paper
URL: https://arxiv.org/abs/2023.12345

[2] Nature Article
URL: https://nature.com/articles/s41586-023-06789-9"""

        exporter = RISExporter()
        ris_output = exporter.export_to_ris(content)

        # Should have exactly 2 RIS entries (not 3)
        assert ris_output.count("TY  - ELEC") == 2
        assert ris_output.count("ER  -") == 2

        # Should include both URLs
        assert "https://arxiv.org/abs/2023.12345" in ris_output
        assert "https://nature.com/articles/s41586-023-06789-9" in ris_output

    def test_ris_export_with_special_characters(self):
        """Test RIS export handles special characters properly."""
        content = """# Research Report

Citation [1] with special chars.

## Sources

[1] Paper with Special Chars: Ñoño, Müller & 中文
URL: https://example.com/special-chars?param=value&other=test"""

        exporter = RISExporter()
        ris_output = exporter.export_to_ris(content)

        # Should handle special characters
        assert "Ñoño" in ris_output
        assert "Müller" in ris_output
        assert "中文" in ris_output
        assert "param=value&other=test" in ris_output

    def test_latex_export_with_equations(self):
        """Test LaTeX export with equations in content."""
        content = r"""# Research Report

The equation $E = mc^2$ from [1] shows mass-energy equivalence.

Consider the integral $$\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}$$ from [2].

## Sources

[1] Einstein's Original Paper
URL: https://physics.org/einstein-1905

[2] Mathematical Methods
URL: https://math.edu/integrals"""

        exporter = LaTeXExporter()
        latex_output = exporter.export_to_latex(content)

        # Should preserve math mode
        assert r"$E = mc^2$" in latex_output
        assert r"$$\int_0^\infty" in latex_output

        # Should have proper bibliography
        assert r"\bibitem{1}" in latex_output
        assert r"\bibitem{2}" in latex_output

    def test_latex_export_special_characters_escaping(self):
        """Test LaTeX export properly escapes special characters."""
        content = """# Research Report

Citation [1] with special LaTeX chars: $, %, &, #, _, {, }.

## Sources

[1] Paper & Title with % Special # Chars
URL: https://example.com/paper_with_underscore"""

        exporter = LaTeXExporter()
        latex_output = exporter.export_to_latex(content)

        # Should escape special LaTeX characters in text
        assert r"\%" in latex_output
        assert r"\&" in latex_output
        assert r"\#" in latex_output
        assert (
            r"\_" in latex_output or "_" in latex_output
        )  # URLs might not be escaped

    def test_quarto_export_with_metadata(self):
        """Test Quarto export includes proper metadata."""
        content = """# Deep Learning Research Report

This reviews [1] and extends [2].

## Sources

[1] Attention Is All You Need
URL: https://arxiv.org/abs/1706.03762

[2] BERT: Pre-training of Deep Bidirectional Transformers
URL: https://arxiv.org/abs/1810.04805"""

        exporter = QuartoExporter()
        quarto_output = exporter.export_to_quarto(content)

        # Should have YAML frontmatter
        assert "---" in quarto_output
        assert "title:" in quarto_output
        assert "bibliography:" in quarto_output

        # Should extract title
        assert "Deep Learning Research Report" in quarto_output

        # Should have citations in Quarto format
        assert "[@ref1]" in quarto_output or "@ref1" in quarto_output
        assert "[@ref2]" in quarto_output or "@ref2" in quarto_output

    def test_export_with_missing_sources_section(self):
        """Test export formats handle missing sources section gracefully."""
        content = """# Research Report

This has citations [1] and [2] but no sources section."""

        # Test RIS
        ris_exporter = RISExporter()
        ris_output = ris_exporter.export_to_ris(content)
        assert ris_output == ""  # Should return empty for no sources

        # Test LaTeX
        latex_exporter = LaTeXExporter()
        latex_output = latex_exporter.export_to_latex(content)
        assert "bibliography" not in latex_output.lower()

        # Test Quarto
        quarto_exporter = QuartoExporter()
        quarto_output = quarto_exporter.export_to_quarto(content)
        # Should still have content but no bibliography
        assert "This has citations" in quarto_output

    def test_export_with_duplicate_urls(self):
        """Test export formats handle duplicate URLs correctly."""
        content = """# Report

Cite [1] and [2].

## Sources

[1] First Title
URL: https://same.url/paper

[2] Different Title Same URL
URL: https://same.url/paper"""

        # RIS should have separate entries
        ris_exporter = RISExporter()
        ris_output = ris_exporter.export_to_ris(content)
        assert ris_output.count("TY  - ELEC") == 2
        # The fixed exporter emits clean RIS records only (no echo of the
        # raw source text), so the shared URL appears once per entry → 2.
        assert ris_output.count("https://same.url/paper") == 2

        # LaTeX should have separate bibitems
        latex_exporter = LaTeXExporter()
        latex_output = latex_exporter.export_to_latex(content)
        assert r"\bibitem{1}" in latex_output
        assert r"\bibitem{2}" in latex_output

    def test_export_preserves_markdown_structure(self):
        """Test that exports preserve document structure."""
        content = """# Main Title

## Introduction

This is **bold** and *italic* text [1].

### Subsection

- List item [2]
- Another item
  - Nested [3]

## Sources

[1] Source One
URL: https://one.com

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

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

        # Test LaTeX preserves structure
        latex_exporter = LaTeXExporter()
        latex_output = latex_exporter.export_to_latex(content)
        assert r"\section" in latex_output
        assert r"\subsection" in latex_output
        assert r"\textbf{bold}" in latex_output
        assert r"\textit{italic}" in latex_output
        assert r"\begin{itemize}" in latex_output

    def test_quarto_bibliography_generation(self):
        """Test Quarto generates proper bibliography entries."""
        content = """# Research

Citation [1].

## Sources

[1] 2023 AI Paper by Smith, J. and Doe, J.
URL: https://ai-journal.com/2023/paper"""

        exporter = QuartoExporter()
        quarto_output = exporter.export_to_quarto(content)

        # Should generate a references section
        assert "references:" in quarto_output.lower() or "@" in quarto_output

    def test_export_with_malformed_content(self):
        """Test exports handle malformed content gracefully."""
        content = """# Report

[1] [2 [3]] [[4]

## Sources

[1 Source One
URL: https://one.com

[2] Source Two
No URL

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

        # All exporters should handle this without crashing
        exporters = [RISExporter(), LaTeXExporter(), QuartoExporter()]

        for exporter in exporters:
            try:
                if isinstance(exporter, RISExporter):
                    output = exporter.export_to_ris(content)
                elif isinstance(exporter, LaTeXExporter):
                    output = exporter.export_to_latex(content)
                elif isinstance(exporter, QuartoExporter):
                    output = exporter.export_to_quarto(content)
                assert output is not None
            except Exception as e:
                pytest.fail(
                    f"{exporter.__class__.__name__} failed on malformed content: {e}"
                )

    def test_ris_export_field_extraction(self):
        """Test RIS export extracts various metadata fields."""
        content = """# Report

Citation [1].

## Sources

[1] Deep Learning in Nature 2023 by LeCun, Y., Bengio, Y., & Hinton, G.
Published in Nature Machine Intelligence, Volume 5, Pages 123-145
DOI: 10.1038/s42256-023-00001-2
URL: https://nature.com/articles/s42256-023-00001-2"""

        exporter = RISExporter()
        ris_output = exporter.export_to_ris(content)

        # Should extract various fields
        assert "TI  - Deep Learning in Nature 2023" in ris_output
        assert "AU  - LeCun, Y." in ris_output or "LeCun" in ris_output
        assert "PY  - 2023" in ris_output
        assert "DO  - 10.1038/s42256-023-00001-2" in ris_output

    def test_concurrent_export_formats(self):
        """Test that different export formats can be used concurrently."""
        content = """# Research

Multiple [1] citations [1] here [2].

## Sources

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

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

        # Format for different uses
        formatter_domain = CitationFormatter(
            mode=CitationMode.DOMAIN_HYPERLINKS
        )
        formatted_domain = formatter_domain.format_document(content)

        formatter_number = CitationFormatter(
            mode=CitationMode.NUMBER_HYPERLINKS
        )
        formatted_number = formatter_number.format_document(content)

        # Export to different formats
        ris_output = RISExporter().export_to_ris(content)
        latex_output = LaTeXExporter().export_to_latex(content)
        quarto_output = QuartoExporter().export_to_quarto(content)

        # All should work independently
        assert "[first.com]" in formatted_domain
        assert "[[1]](https://first.com)" in formatted_number
        assert "TY  - ELEC" in ris_output
        assert r"\bibitem" in latex_output
        assert "bibliography" in quarto_output or "@" in quarto_output
