"""Tests for search_strategy service functions.

Tests cover:
- format_search_strategy() with various strategy dict configurations
- pubmed_syntax() Europe PMC -> PubMed field tag conversion
- europe_pmc_syntax() PubMed -> Europe PMC field tag conversion
"""
import pytest
from app.services.search_strategy import (
    format_search_strategy,
    pubmed_syntax,
    europe_pmc_syntax,
)


# ── format_search_strategy ──────────────────────────────────────────


@pytest.mark.asyncio
async def test_format_search_strategy_basic():
    """Minimal strategy dict with one query returns properly formatted output."""
    strategy = {
        "database": "PubMed",
        "date": "2026-07-08",
        "queries": [
            {"query": '"lung cancer"[tiab]', "results": 123},
        ],
    }
    expected = (
        '# Search Strategy — PubMed\n'
        '# Date: 2026-07-08\n'
        '\n'
        '## Database\n'
        'PubMed\n'
        '\n'
        '## Search Queries\n'
        '#1\n'
        '  "lung cancer"[tiab] — 123 results'
    )
    result = format_search_strategy(strategy, language="en")
    assert result == expected


@pytest.mark.asyncio
async def test_format_search_strategy_full():
    """Full strategy with filters, multiple queries, MeSH terms, and notes."""
    strategy = {
        "database": "PubMed",
        "date": "2026-07-08",
        "queries": [
            {
                "query": '"Lung Neoplasms"[MAJR]',
                "results": 342,
                "precision": "majr",
            },
            {
                "query": '"lung cancer"[Title/Abstract]',
                "results": 581,
                "precision": "broad",
            },
        ],
        "filters": {"year_range": "2024:2026", "languages": ["en"]},
        "mesh_terms_used": ["Lung Neoplasms", "Breast Neoplasms"],
        "search_notes": "Only randomized controlled trials",
    }
    expected = (
        '# Search Strategy — PubMed\n'
        '# Date: 2026-07-08\n'
        '\n'
        '## Database\n'
        'PubMed\n'
        '\n'
        '## Year Range\n'
        '2024:2026\n'
        '\n'
        '## Language Restriction\n'
        'en\n'
        '\n'
        '## Search Queries\n'
        '#1 [Precision: MeSH Major Topic]\n'
        '  "Lung Neoplasms"[MAJR] — 342 results\n'
        '#2 [Precision: Title/Abstract]\n'
        '  "lung cancer"[Title/Abstract] — 581 results\n'
        '\n'
        '## MeSH Terms Used\n'
        'Lung Neoplasms; Breast Neoplasms\n'
        '\n'
        '## Notes\n'
        'Only randomized controlled trials'
    )
    result = format_search_strategy(strategy, language="en")
    assert result == expected


@pytest.mark.asyncio
async def test_format_search_strategy_pubmed_syntax():
    """target='pubmed' triggers pubmed_syntax() conversion on query strings."""
    strategy = {
        "database": "PubMed",
        "date": "2026-07-08",
        "queries": [
            {
                "query": '"Lung Neoplasms"[MAJR]',
                "results": 342,
                "precision": "majr",
                "target": "pubmed",
            },
            {
                "query": '"lung cancer"[Title/Abstract]',
                "results": 581,
                "precision": "broad",
                "target": "pubmed",
            },
        ],
    }
    expected = (
        '# Search Strategy — PubMed\n'
        '# Date: 2026-07-08\n'
        '\n'
        '## Database\n'
        'PubMed\n'
        '\n'
        '## Search Queries\n'
        '#1 [Precision: MeSH Major Topic]\n'
        '  "Lung Neoplasms"[MAJR] — 342 results\n'
        '#2 [Precision: Title/Abstract]\n'
        '  "lung cancer"[tiab] — 581 results'
    )
    result = format_search_strategy(strategy, language="en")
    assert result == expected


@pytest.mark.asyncio
async def test_format_search_strategy_europe_pmc_syntax():
    """Europe PMC query strings pass through unchanged without target flag."""
    strategy = {
        "database": "Europe PMC",
        "date": "2026-07-08",
        "queries": [
            {
                "query": 'TITLE:"lung cancer"',
                "results": 581,
                "precision": "broad",
            },
        ],
    }
    expected = (
        '# Search Strategy — Europe PMC\n'
        '# Date: 2026-07-08\n'
        '\n'
        '## Database\n'
        'Europe PMC\n'
        '\n'
        '## Search Queries\n'
        '#1 [Precision: Title/Abstract]\n'
        '  TITLE:"lung cancer" — 581 results'
    )
    result = format_search_strategy(strategy, language="en")
    assert result == expected


@pytest.mark.asyncio
async def test_format_search_strategy_zh():
    """Chinese language output with translated section headers and labels."""
    strategy = {
        "database": "PubMed",
        "date": "2026-07-08",
        "queries": [
            {
                "query": '"lung cancer"[tiab]',
                "results": 123,
                "precision": "broad",
            },
        ],
    }
    expected = (
        '# 检索策略 — PubMed\n'
        '# 检索日期: 2026-07-08\n'
        '\n'
        '## 数据库\n'
        'PubMed\n'
        '\n'
        '## 检索式\n'
        '#1 [精度: 标题/摘要]\n'
        '  "lung cancer"[tiab] — 123 篇'
    )
    result = format_search_strategy(strategy, language="zh")
    assert result == expected


@pytest.mark.asyncio
async def test_format_search_strategy_empty():
    """Empty dict and None both return empty string."""
    assert format_search_strategy({}, language="en") == ""
    assert format_search_strategy(None, language="en") == ""


@pytest.mark.asyncio
async def test_format_search_strategy_no_queries():
    """Strategy dict without queries key, or with empty queries, returns empty string."""
    assert format_search_strategy({"database": "PubMed"}, language="en") == ""
    assert format_search_strategy({"database": "PubMed", "date": "2026-07-08"}, language="en") == ""
    assert format_search_strategy({"queries": []}, language="en") == ""


@pytest.mark.asyncio
async def test_format_search_strategy_mixed_fields():
    """Single query with mixed field labels (MeSH + Title/Abstract) preserved as-is."""
    strategy = {
        "database": "PubMed",
        "date": "2026-07-08",
        "queries": [
            {
                "query": '"Breast Neoplasms"[MeSH] AND "breast cancer"[Title/Abstract]',
                "results": 500,
            },
        ],
    }
    expected = (
        '# Search Strategy — PubMed\n'
        '# Date: 2026-07-08\n'
        '\n'
        '## Database\n'
        'PubMed\n'
        '\n'
        '## Search Queries\n'
        '#1\n'
        '  "Breast Neoplasms"[MeSH] AND "breast cancer"[Title/Abstract] — 500 results'
    )
    result = format_search_strategy(strategy, language="en")
    assert result == expected


# ── pubmed_syntax ───────────────────────────────────────────────────


@pytest.mark.asyncio
async def test_pubmed_syntax():
    """Europe PMC field tags converted to PubMed equivalents."""
    # Title/Abstract -> tiab
    assert pubmed_syntax('lung cancer[Title/Abstract]') == 'lung cancer[tiab]'
    # MAJR stays the same (same label in both systems)
    assert pubmed_syntax('"Lung Neoplasms"[MAJR]') == '"Lung Neoplasms"[MAJR]'
    # Author -> au
    assert pubmed_syntax('Smith J[Author]') == 'Smith J[au]'
    # Year -> dp
    assert pubmed_syntax('2024:2026[Year]') == '2024:2026[dp]'
    # DOI -> doi
    assert pubmed_syntax('10.1000/xyz[DOI]') == '10.1000/xyz[doi]'
    # PUBMED -> pmid
    assert pubmed_syntax('12345[PUBMED]') == '12345[pmid]'
    # Unknown tag passes through unchanged
    assert pubmed_syntax('lung cancer[ALL]') == 'lung cancer[ALL]'
    # PMCID -> pmc
    assert pubmed_syntax('PMC12345[PMCID]') == 'PMC12345[pmc]'
    # Journal -> ta
    assert pubmed_syntax('"Nat Rev Cancer"[Journal]') == '"Nat Rev Cancer"[ta]'


@pytest.mark.asyncio
async def test_pubmed_syntax_uppercase_variant():
    """Uppercase variants like [TITLE/ABSTRACT] also get converted."""
    assert pubmed_syntax('lung cancer[TITLE/ABSTRACT]') == 'lung cancer[tiab]'


# ── europe_pmc_syntax ───────────────────────────────────────────────


@pytest.mark.asyncio
async def test_europe_pmc_syntax():
    """PubMed field tags converted to Europe PMC equivalents."""
    # au -> Author
    assert europe_pmc_syntax('Smith J[au]') == 'Smith J[Author]'
    # MAJR stays the same
    assert europe_pmc_syntax('"Lung Neoplasms"[MAJR]') == '"Lung Neoplasms"[MAJR]'
    # MeSH stays the same
    assert europe_pmc_syntax('"Breast Neoplasms"[MeSH]') == '"Breast Neoplasms"[MeSH]'
    # dp -> Year
    assert europe_pmc_syntax('2024:2026[dp]') == '2024:2026[Year]'
    # doi -> DOI
    assert europe_pmc_syntax('10.1000/xyz[doi]') == '10.1000/xyz[DOI]'
    # pmid -> PUBMED
    assert europe_pmc_syntax('12345[pmid]') == '12345[PUBMED]'
    # pmc -> PMCID
    assert europe_pmc_syntax('PMC12345[pmc]') == 'PMC12345[PMCID]'
    # ta -> Journal
    assert europe_pmc_syntax('"Nat Rev Cancer"[ta]') == '"Nat Rev Cancer"[Journal]'
    # Unknown tag passes through unchanged
    assert europe_pmc_syntax('lung cancer[ALL]') == 'lung cancer[ALL]'
