"""Tests for BibTeX formatting."""

from arxivy.formatters.bibtex import (
    _escape_latex,
    _generate_citation_key,
    _normalize_to_ascii,
    format_bibtex,
    format_bibtex_batch,
)
from arxivy.models import Author, Paper


class TestNormalizeToAscii:
    def test_ascii_unchanged(self):
        assert _normalize_to_ascii("hello world") == "hello world"

    def test_unicode_normalized(self):
        assert _normalize_to_ascii("café") == "cafe"
        assert _normalize_to_ascii("naïve") == "naive"

    def test_accented_names(self):
        assert _normalize_to_ascii("José García") == "Jose Garcia"


class TestEscapeLatex:
    def test_ampersand(self):
        assert _escape_latex("Smith & Jones") == r"Smith \& Jones"

    def test_percent(self):
        assert _escape_latex("100% accurate") == r"100\% accurate"

    def test_special_chars(self):
        assert _escape_latex("$10") == r"\$10"
        assert _escape_latex("#1") == r"\#1"
        assert _escape_latex("under_score") == r"under\_score"

    def test_braces(self):
        assert _escape_latex("{test}") == r"\{test\}"

    def test_empty_string(self):
        assert _escape_latex("") == ""

    def test_none_returns_empty(self):
        assert _escape_latex(None) == ""


class TestGenerateCitationKey:
    def test_standard_paper(self):
        paper = Paper(
            authors=[Author(name="Ashish Vaswani")],
            published="2017-06-12T17:57:34Z",
            title="Attention Is All You Need",
        )
        assert _generate_citation_key(paper) == "vaswani2017attention"

    def test_skips_stopwords(self):
        paper = Paper(
            authors=[Author(name="John Doe")],
            published="2020-01-01T00:00:00Z",
            title="The Art of Programming",
        )
        assert _generate_citation_key(paper) == "doe2020art"

    def test_no_authors(self):
        paper = Paper(published="2020-01-01T00:00:00Z", title="Anonymous Paper")
        assert _generate_citation_key(paper) == "unknown2020anonymous"

    def test_no_published_date(self):
        paper = Paper(authors=[Author(name="Jane Smith")], title="Timeless Work")
        assert _generate_citation_key(paper) == "smithnodatetimeless"

    def test_no_title(self):
        paper = Paper(authors=[Author(name="Jane Smith")], published="2020-01-01T00:00:00Z")
        assert _generate_citation_key(paper) == "smith2020paper"

    def test_unicode_author(self):
        paper = Paper(
            authors=[Author(name="José García")],
            published="2020-01-01T00:00:00Z",
            title="Test Paper",
        )
        assert _generate_citation_key(paper) == "garcia2020test"

    def test_multi_word_last_name(self):
        paper = Paper(
            authors=[Author(name="Vincent van Gogh")],
            published="1888-01-01T00:00:00Z",
            title="Sunflowers",
        )
        assert _generate_citation_key(paper) == "gogh1888sunflowers"


class TestFormatBibtex:
    def test_misc_entry_without_journal(self):
        paper = Paper(
            arxiv_id="1706.03762",
            title="Attention Is All You Need",
            authors=[Author(name="Ashish Vaswani"), Author(name="Noam Shazeer")],
            published="2017-06-12T17:57:34Z",
            primary_category="cs.CL",
            summary="A great paper.",
            abstract_url="http://arxiv.org/abs/1706.03762v7",
        )
        bib = format_bibtex(paper)

        assert "@misc{vaswani2017attention" in bib
        assert "title = {Attention Is All You Need}" in bib
        assert "author = {Ashish Vaswani and Noam Shazeer}" in bib
        assert "year = {2017}" in bib
        assert "eprint = {1706.03762}" in bib
        assert "archiveprefix = {arXiv}" in bib
        assert "primaryclass = {cs.CL}" in bib

    def test_article_entry_with_journal(self):
        paper = Paper(
            arxiv_id="1706.03762",
            title="Attention Is All You Need",
            authors=[Author(name="Ashish Vaswani")],
            published="2017-06-12T17:57:34Z",
            primary_category="cs.CL",
            journal_ref="NeurIPS 2017",
            doi="10.48550/arXiv.1706.03762",
        )
        bib = format_bibtex(paper)

        assert "@article{vaswani2017attention" in bib
        assert "journal = {NeurIPS 2017}" in bib
        assert "doi = {10.48550/arXiv.1706.03762}" in bib

    def test_escapes_special_chars_in_title(self):
        paper = Paper(
            arxiv_id="0000.00000",
            title="100% Accuracy & More",
            published="2021-01-01T00:00:00Z",
        )
        bib = format_bibtex(paper)
        assert r"100\% Accuracy \& More" in bib

    def test_includes_url(self):
        paper = Paper(
            arxiv_id="1706.03762",
            title="Test",
            published="2017-01-01T00:00:00Z",
            abstract_url="http://arxiv.org/abs/1706.03762v7",
        )
        bib = format_bibtex(paper)
        assert "url = {http://arxiv.org/abs/1706.03762v7}" in bib

    def test_truncates_long_abstract(self):
        paper = Paper(
            arxiv_id="0000.00000",
            title="Test",
            published="2020-01-01T00:00:00Z",
            summary="x" * 2000,
        )
        bib = format_bibtex(paper)
        assert "..." in bib
        # The abstract field value should be at most ~1000 chars
        assert len(bib) < 2500


class TestFormatBibtexBatch:
    def test_multiple_papers(self):
        papers = [
            Paper(
                arxiv_id="1706.03762",
                title="First Paper",
                authors=[Author(name="Author One")],
                published="2017-01-01T00:00:00Z",
                primary_category="cs.CL",
            ),
            Paper(
                arxiv_id="2010.11929",
                title="Second Paper",
                authors=[Author(name="Author Two")],
                published="2020-01-01T00:00:00Z",
                primary_category="cs.CV",
            ),
        ]
        output = format_bibtex_batch(papers)
        assert output.count("@misc") == 2
        assert "First Paper" in output
        assert "Second Paper" in output

    def test_skips_none_papers(self):
        papers = [
            Paper(
                arxiv_id="1706.03762",
                title="Valid",
                published="2020-01-01T00:00:00Z",
            ),
            None,
        ]
        output = format_bibtex_batch(papers)
        assert output.count("@misc") == 1

    def test_empty_list(self):
        assert format_bibtex_batch([]) == ""
