"""Tests for 12 Catholic priest workflow scenarios.

Covers homily prep, confession preparation, Eucharist theology, RCIA,
marriage prep, lectionary, anointing of the sick, papacy, Marian theology,
Christology, Maccabees/Hanukkah, and seven sacraments chain.

Each scenario tests a multi-tool workflow a Catholic priest would use
in pastoral ministry. Tests are designed to validate that tools work
together (not crash, return expected types) rather than verify specific
theological content.
"""
from __future__ import annotations

import pytest


# =============================================================================
# IMPORT GUARDS — import everything with try/except, following project conventions
# =============================================================================

# --- Canon (local only, always available) ---
try:
    from accordance_parser.canon import (
        parse_reference, CANON_CATHOLIC, chapter_count,
    )
    _has_canon = True
except Exception:
    _has_canon = False

# --- Bible API ---
try:
    from accordance_parser.bible_api import get_verse
    _has_bible_api = True
except Exception:
    _has_bible_api = False

# --- Morphology (local) ---
try:
    from accordance_parser.morphology import get_morphology, describe_robinson
    _has_morphology = True
except Exception:
    _has_morphology = False

# --- Lectionary (local) ---
try:
    from accordance_parser.lectionary import (
        get_lectionary_for_date_string, _LECTIONARY,
    )
    _has_lectionary = True
except Exception:
    _has_lectionary = False

# --- mcp_multi_tools (standalone tools that may need server for real results) ---
try:
    from accordance_services.tools.text import (
        get_verse_range, get_book_list,
    )
    _has_multi_tools = True
except Exception:
    _has_multi_tools = False

# --- mcp_acc2_tools (standalone) ---
try:
    from accordance_services.tools.acc2 import find_ot_quotations
    _has_acc2_tools = True
except Exception:
    _has_acc2_tools = False

# --- Search tools (may need server for real results) ---
try:
    from accordance_services.tools.search import search_verses_by_term
    _has_search_tools = True
except Exception:
    _has_search_tools = False

# --- MCP server tools (heavy import — may fail if FastMCP/uvicorn not available) ---
_has_mcp_server = False
_mcp_server_import_error = ""
try:
    from accordance_mcp_server import (
        search_all,
        search_commentaries,
        compare_translations,
        find_cross_references,
        study_strongs_number,
        interlinear_display,
        get_nabre_verse,
        compare_catholic_translations,
        daily_mass_readings,
    )
    _has_mcp_server = True
except Exception as e:
    _mcp_server_import_error = str(e)


# --- Network detection (for tools that call bolls.life API) ---
_has_network = False
try:
    from accordance_parser.bible_api import get_verse
    r = get_verse("Genesis 1:1", "KJV")
    if r and r.text:
        _has_network = True
except Exception:
    pass


# =============================================================================
# HELPER: Check that a result string is not a traceback
# =============================================================================

def _no_traceback(text: str) -> bool:
    """Ensure the text does not contain a Python traceback."""
    return "Traceback (most recent call last)" not in text


# =============================================================================
# HELPER: Determine if MCP server tools can actually execute (not just import)
# =============================================================================

def _mcp_server_functional() -> bool:
    """Return True if MCP server tools return real data (not error strings)."""
    if not _has_mcp_server:
        return False
    try:
        # Check a quick call that goes through API
        result = get_nabre_verse("Genesis 1:1")
        return len(result) > 50 and "Error" not in result and _no_traceback(result)
    except Exception:
        return False


# =============================================================================
# SCENARIO 1: S-P-01 — Homily Prep: Trinity Sunday
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP01HomilyPrepTrinitySunday:
    """S-P-01: Homily preparation workflow for Trinity Sunday.

    Chain: daily_mass_readings → get_nabre_verse → compare_catholic_translations
           → study_strongs_number (G3439 = μονογενής).
    """

    def test_daily_mass_readings_returns_structure(self):
        """daily_mass_readings should return markdown with readings keys."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = daily_mass_readings("2026-05-31")  # Trinity Sunday 2026
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)
        # Should mention readings, season, or date
        lower = result.lower()
        assert any(w in lower for w in ("reading", "gospel", "psalm", "trinity", "may"))

    def test_nabre_verse_resolves_gospel_reading(self):
        """NABRE verse retrieval for a typical Trinity Sunday Gospel (John 3:16)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("John 3:16")
        assert isinstance(result, str)
        assert len(result) > 20
        assert "John 3:16" in result or "God" in result

    def test_compare_catholic_translations_works(self):
        """compare_catholic_translations should return multi-translation output."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = compare_catholic_translations("John 3:16")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)
        # Should have a table or mention at least one translation
        assert "NABRE" in result or "NRSVCE" in result or "DRB" in result

    def test_study_strongs_g3439(self):
        """study_strongs_number G3439 (μονογενής — 'only-begotten') should return study data."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = study_strongs_number("G3439")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 2: S-P-02 — Confession / Examination of Conscience
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP02ConfessionExamination:
    """S-P-02: Confession preparation — search "repent", Luke 15:18, morphology, commentary.

    Chain: search_verses_by_term("repent") → get_nabre_verse("Luke 15:18")
           → get_morphology("Luke 15:18") → search_commentaries("John 20:23").
    """

    def test_search_repent_returns_results(self):
        """search_verses_by_term should return results for 'repent'."""
        if not _has_search_tools:
            pytest.skip("search_verses_by_term not importable")
        result = search_verses_by_term("repent", max_results=10)
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)
        # If server is functional, should have verse results
        # Skip content check if index is still building (transient state)
        if "Error" not in result and "not available" not in result.lower() and "still building" not in result.lower():
            lower = result.lower()
            assert "repent" in lower or "verse" in lower

    def test_nabre_luke_15_18_prodigal_son(self):
        """Luke 15:18 (Prodigal Son — confession)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("Luke 15:18")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "father" in lower or "sin" in lower or "heaven" in lower

    def test_morphology_luke_15_18(self):
        """get_morphology should return morphology entries for Luke 15:18."""
        if not _has_morphology:
            pytest.skip("Morphology not available")
        entries = get_morphology("Luke 15:18")
        assert isinstance(entries, list)
        # NT verse should have at least some morphology entries
        if len(entries) > 0:
            entry = entries[0]
            assert hasattr(entry, "word") or hasattr(entry, "lemma")

    def test_search_commentaries_john_20_23(self):
        """search_commentaries for John 20:23 (forgiveness of sins)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = search_commentaries("John 20:23")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 3: S-P-03 — Eucharist: John 6 Real Presence
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP03EucharistJohn6:
    """S-P-03: Eucharist theology — John 6:53-58 real presence.

    Chain: get_verse_range(NABRE, "John 6:53-58") → get_morphology("John 6:54")
           → compare_catholic_translations("John 6:54") → search_commentaries("John 6:53").
    """

    def test_verse_range_john_6_53_58_returns_text(self):
        """get_verse_range should return NABRE text for John 6:53-58."""
        if not _has_multi_tools:
            pytest.skip("mcp_multi_tools not importable")
        result = get_verse_range("NABRE", "John 6:53", "John 6:58")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)
        # If successful, should contain "flesh" or "blood" or verse numbers
        lower = result.lower()
        if "error" not in lower:
            assert any(w in lower for w in ("flesh", "blood", "life", "**53**", "**54**"))

    def test_morphology_john_6_54_includes_robinson(self):
        """get_morphology for John 6:54 should return entries with Robinson codes."""
        if not _has_morphology:
            pytest.skip("Morphology not available")
        entries = get_morphology("John 6:54")
        assert isinstance(entries, list)
        if len(entries) > 0:
            entry = entries[0]
            assert hasattr(entry, "word") or hasattr(entry, "lemma")

    def test_compare_catholic_translations_john_6_54(self):
        """compare_catholic_translations for John 6:54."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = compare_catholic_translations("John 6:54")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)

    def test_search_commentaries_john_6_53(self):
        """search_commentaries for John 6:53 (Eucharist)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = search_commentaries("John 6:53")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 4: S-P-04 — RCIA: Sirach (Deuterocanonical)
# =============================================================================


@pytest.mark.skipif(not _has_multi_tools, reason="mcp_multi_tools not importable")
class TestSP04RCIASirach:
    """S-P-04: RCIA using Sirach — Catholic canon, deuterocanonical verse.

    Chain: get_book_list("catholic") → get_nabre_verse("Sirach 6:14")
           → search_verses_by_term("faithful friend") → compare_catholic_translations("Sirach 6:14").
    """

    def test_catholic_book_list_has_73_books_including_sirach(self):
        """get_book_list('catholic') should show 73 books with Sirach."""
        result = get_book_list("catholic")
        assert isinstance(result, str)
        assert "**Total Books:** 73" in result
        assert "Sirach" in result or "Sir" in result

    @pytest.mark.skipif(not _has_network, reason="Requires network")
    def test_nabre_sirach_6_14_returns_text(self):
        """Sirach 6:14 (faithful friend) should return NABRE text."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("Sirach 6:14")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "friend" in lower or "faithful" in lower or "sirach" in lower

    @pytest.mark.skipif(not _has_network, reason="Requires network")
    def test_search_faithful_friend_returns_results(self):
        """search_verses_by_term for 'faithful friend'."""
        if not _has_search_tools:
            pytest.skip("search_verses_by_term not importable")
        result = search_verses_by_term("faithful friend", max_results=10)
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)

    @pytest.mark.skipif(not _has_network, reason="Requires network")
    def test_compare_catholic_translations_sirach_6_14(self):
        """compare_catholic_translations for Sirach 6:14."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = compare_catholic_translations("Sirach 6:14")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 5: S-P-05 — Marriage Prep: Tobit 8
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP05MarriageTobit:
    """S-P-05: Marriage preparation using Tobit 8:4-8.

    Chain: get_verse_range(NABRE, "Tobit 8:4-8") → compare_catholic_translations("Tobit 8:6")
           → find_cross_references("Tobit 8:6").
    """

    def test_verse_range_tobit_8_4_8_returns_text(self):
        """get_verse_range should return NABRE text for Tobit 8:4-8."""
        if not _has_multi_tools:
            pytest.skip("mcp_multi_tools not importable")
        result = get_verse_range("NABRE", "Tobit 8:4", "Tobit 8:8")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)
        lower = result.lower()
        if "error" not in lower:
            assert any(w in lower for w in ("pray", "wife", "tobiah", "sarah", "**4**", "**5**"))

    def test_compare_catholic_translations_tobit_8_6(self):
        """compare_catholic_translations for Tobit 8:6."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = compare_catholic_translations("Tobit 8:6")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)

    def test_find_cross_references_tobit_8_6(self):
        """find_cross_references for Tobit 8:6."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = find_cross_references("Tobit 8:6")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 6: S-P-06 — Lectionary: Ordinary Time
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP06LectionaryOrdinaryTime:
    """S-P-06: Lectionary for Ordinary Time.

    Chain: daily_mass_readings → find_ot_quotations("Mark 12:10")
           → search_all("cornerstone").
    """

    def test_daily_mass_readings_ordinary_time_date(self):
        """daily_mass_readings for a 2026 date should return structure."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        # June 10, 2026 — a Wednesday in Ordinary Time
        result = daily_mass_readings("2026-06-10")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)

    def test_find_ot_quotations_mark_12_10(self):
        """find_ot_quotations for Mark 12:10 (cornerstone from Psalm 118)."""
        if not _has_acc2_tools:
            pytest.skip("acc2 tools not importable")
        result = find_ot_quotations("Mark 12:10")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)

    def test_search_all_cornerstone_returns_results(self):
        """search_all('cornerstone') should return results."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        # search_all may return "Search index not available" if no index built
        result = search_all("cornerstone", max_results=10)
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 7: S-P-07 — Anointing of the Sick
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP07AnointingOfTheSick:
    """S-P-07: Anointing of the Sick — James 5:14.

    Chain: get_nabre_verse("James 5:14") → get_morphology("James 5:14")
           → compare_catholic_translations("James 5:14") → search_commentaries("James 5:14").
    """

    def test_nabre_james_5_14(self):
        """James 5:14 (anointing the sick)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("James 5:14")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "sick" in lower or "anoint" in lower or "oil" in lower

    def test_morphology_james_5_14(self):
        """get_morphology for James 5:14 should return entries."""
        if not _has_morphology:
            pytest.skip("Morphology not available")
        entries = get_morphology("James 5:14")
        assert isinstance(entries, list)
        if len(entries) > 0:
            # Should have attributes with morphological data
            entry = entries[0]
            assert hasattr(entry, "word") or hasattr(entry, "lemma") or hasattr(entry, "morph_code")

    def test_compare_catholic_translations_james_5_14(self):
        """compare_catholic_translations for James 5:14."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = compare_catholic_translations("James 5:14")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)

    def test_search_commentaries_james_5_14(self):
        """search_commentaries for James 5:14."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = search_commentaries("James 5:14")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 8: S-P-08 — Papacy: Matthew 16:18
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP08PapacyMatthew16:
    """S-P-08: Papacy — Matthew 16:18 (Tu es Petrus).

    Chain: get_nabre_verse("Matthew 16:18") → interlinear_display("Matthew 16:18")
           → study_strongs_number("G4074") → search_commentaries("Matthew 16:18").
    """

    def test_nabre_matthew_16_18(self):
        """Matthew 16:18 (Peter/rock)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("Matthew 16:18")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "peter" in lower or "rock" in lower or "church" in lower

    def test_interlinear_display_matthew_16_18(self):
        """interlinear_display for Matthew 16:18 should return annotated table."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = interlinear_display("Matthew 16:18")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)

    def test_study_strongs_g4074_petros(self):
        """study_strongs_number G4074 (Πέτρος — Peter/Rock)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = study_strongs_number("G4074")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)

    def test_search_commentaries_matthew_16_18(self):
        """search_commentaries for Matthew 16:18 (papacy)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = search_commentaries("Matthew 16:18")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 9: S-P-09 — Marian Theology: Luke 1:28 and Judith 13:18
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP09MarianTheology:
    """S-P-09: Marian theology — Luke 1:28 (Annunciation) and Judith 13:18.

    Chain: get_nabre_verse("Luke 1:28") → get_morphology("Luke 1:28")
           → study_strongs_number("G5487") → get_nabre_verse("Judith 13:18").
    """

    def test_nabre_luke_1_28_annunciation(self):
        """Luke 1:28 (Hail Mary / Annunciation)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("Luke 1:28")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "favored" in lower or "hail" in lower or "lord" in lower

    def test_morphology_luke_1_28(self):
        """get_morphology for Luke 1:28."""
        if not _has_morphology:
            pytest.skip("Morphology not available")
        entries = get_morphology("Luke 1:28")
        assert isinstance(entries, list)
        if len(entries) > 0:
            entry = entries[0]
            assert hasattr(entry, "word") or hasattr(entry, "lemma")

    def test_study_strongs_g5487_charitoo(self):
        """study_strongs_number G5487 (χαριτόω — 'highly favored')."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = study_strongs_number("G5487")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)

    def test_nabre_judith_13_18(self):
        """Judith 13:18 (blessed among women — Marian type)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("Judith 13:18")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "blessed" in lower or "judith" in lower or "woman" in lower


# =============================================================================
# SCENARIO 10: S-P-10 — Christology: John 1:1
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP10ChristologyJohn1:
    """S-P-10: Christology — John 1:1 (the Word).

    Chain: interlinear_display("John 1:1") → get_morphology("John 1:1")
           → study_strongs_number("G3056") → compare_translations("John 1:1").
    """

    def test_interlinear_display_john_1_1(self):
        """interlinear_display for John 1:1."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = interlinear_display("John 1:1")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)

    def test_morphology_john_1_1(self):
        """get_morphology for John 1:1."""
        if not _has_morphology:
            pytest.skip("Morphology not available")
        entries = get_morphology("John 1:1")
        assert isinstance(entries, list)
        if len(entries) > 0:
            # John 1:1 is a NT verse — should have Greek morphology
            assert len(entries) > 0

    def test_study_strongs_g3056_logos(self):
        """study_strongs_number G3056 (λόγος — Word)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = study_strongs_number("G3056")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)

    def test_compare_translations_john_1_1(self):
        """compare_translations for John 1:1 across multiple translations."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = compare_translations("John 1:1", translations="KJV,ESV,NASB,NIV")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)
        # Should mention at least one translation name
        assert "KJV" in result or "ESV" in result or "NASB" in result


# =============================================================================
# SCENARIO 11: S-P-11 — Maccabees / Hanukkah
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP11MaccabeesHanukkah:
    """S-P-11: Hanukkah — 1 Maccabees 4:59 and John 10:22.

    Chain: get_nabre_verse("1 Maccabees 4:59")
           → find_cross_references("1 Maccabees 4:59")
           → get_nabre_verse("John 10:22") → compare_catholic_translations("1 Maccabees 4:59").
    """

    def test_nabre_1macc_4_59(self):
        """1 Maccabees 4:59 (Hanukkah institution)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("1 Maccabees 4:59")
        assert isinstance(result, str)
        assert len(result) > 10

    def test_find_cross_references_1macc_4_59(self):
        """find_cross_references for 1 Maccabees 4:59."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = find_cross_references("1 Maccabees 4:59")
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)

    def test_nabre_john_10_22_hanukkah(self):
        """John 10:22 (Feast of Dedication = Hanukkah)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("John 10:22")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "dedication" in lower or "feast" in lower or "winter" in lower

    def test_compare_catholic_translations_1macc_4_59(self):
        """compare_catholic_translations for 1 Maccabees 4:59."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = compare_catholic_translations("1 Maccabees 4:59")
        assert isinstance(result, str)
        assert len(result) > 20
        assert _no_traceback(result)


# =============================================================================
# SCENARIO 12: S-P-12 — RCIA: Seven Sacraments Chain
# =============================================================================


@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestSP12RCIASevenSacraments:
    """S-P-12: RCIA instruction — sacramental Bible references.

    Chain: search_verses_by_term("baptized") → get_nabre_verse("Matthew 28:19")
           → search_verses_by_term("forgive sins") → get_nabre_verse("Acts 8:17").
    """

    def test_search_baptized_returns_results(self):
        """search_verses_by_term for 'baptized'."""
        if not _has_search_tools:
            pytest.skip("search_verses_by_term not importable")
        result = search_verses_by_term("baptized", max_results=10)
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)

    def test_nabre_matthew_28_19_great_commission(self):
        """Matthew 28:19 (baptism in Trinitarian formula)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("Matthew 28:19")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "baptiz" in lower or "nations" in lower or "father" in lower

    def test_search_forgive_sins_returns_results(self):
        """search_verses_by_term for 'forgive sins'."""
        if not _has_search_tools:
            pytest.skip("search_verses_by_term not importable")
        result = search_verses_by_term("forgive sins", max_results=10)
        assert isinstance(result, str)
        assert len(result) > 0
        assert _no_traceback(result)

    def test_nabre_acts_8_17_confirmation(self):
        """Acts 8:17 (laying on of hands — Confirmation)."""
        if not _has_mcp_server:
            pytest.skip("MCP server not importable")
        result = get_nabre_verse("Acts 8:17")
        assert isinstance(result, str)
        assert len(result) > 10
        lower = result.lower()
        assert "hand" in lower or "spirit" in lower or "holy" in lower


# =============================================================================
# LOCAL TESTS — Canon reference parsing for all 12 scenario passages
# =============================================================================


@pytest.mark.skipif(not _has_canon, reason="Canon not available")
class TestPriestScenarioReferenceParsing:
    """Verify all key references from the 12 scenarios parse correctly."""

    def test_parse_s01_trinity_john_3_16(self):
        r = parse_reference("John 3:16", "catholic")
        assert r is not None

    def test_parse_s02_luke_15_18(self):
        r = parse_reference("Luke 15:18", "catholic")
        assert r is not None

    def test_parse_s02_john_20_23(self):
        r = parse_reference("John 20:23", "catholic")
        assert r is not None

    def test_parse_s03_john_6_53_58(self):
        for v in range(53, 59):
            r = parse_reference(f"John 6:{v}", "catholic")
            assert r is not None

    def test_parse_s04_sirach_6_14(self):
        r = parse_reference("Sirach 6:14", "catholic")
        assert r is not None
        assert r.book_osis == "Sir"

    def test_parse_s05_tobit_8_4_6(self):
        for v in (4, 6):
            r = parse_reference(f"Tobit 8:{v}", "catholic")
            assert r is not None
            assert r.book_osis == "Tob"

    def test_parse_s06_mark_12_10(self):
        r = parse_reference("Mark 12:10", "catholic")
        assert r is not None

    def test_parse_s07_james_5_14(self):
        r = parse_reference("James 5:14", "catholic")
        assert r is not None

    def test_parse_s08_matthew_16_18(self):
        r = parse_reference("Matthew 16:18", "catholic")
        assert r is not None

    def test_parse_s09_luke_1_28(self):
        r = parse_reference("Luke 1:28", "catholic")
        assert r is not None

    def test_parse_s09_judith_13_18(self):
        r = parse_reference("Judith 13:18", "catholic")
        assert r is not None
        assert r.book_osis == "Jdt"

    def test_parse_s10_john_1_1(self):
        r = parse_reference("John 1:1", "catholic")
        assert r is not None

    def test_parse_s11_1macc_4_59(self):
        r = parse_reference("1 Maccabees 4:59", "catholic")
        assert r is not None
        assert r.book_osis == "1Macc"

    def test_parse_s11_john_10_22(self):
        r = parse_reference("John 10:22", "catholic")
        assert r is not None

    def test_parse_s12_matthew_28_19(self):
        r = parse_reference("Matthew 28:19", "catholic")
        assert r is not None

    def test_parse_s12_acts_8_17(self):
        r = parse_reference("Acts 8:17", "catholic")
        assert r is not None


# =============================================================================
# LOCAL TESTS — Catholic canon structure validation for priest scenarios
# =============================================================================


@pytest.mark.skipif(not _has_canon, reason="Canon not available")
class TestPriestScenarioCanonStructure:
    """Verify key canon facts that support the 12 priest scenarios."""

    def test_catholic_canon_has_tobit(self):
        names = {b.osis for b in CANON_CATHOLIC.books}
        assert "Tob" in names

    def test_catholic_canon_has_judith(self):
        names = {b.osis for b in CANON_CATHOLIC.books}
        assert "Jdt" in names

    def test_catholic_canon_has_sirach(self):
        names = {b.osis for b in CANON_CATHOLIC.books}
        assert "Sir" in names

    def test_catholic_canon_has_1macc(self):
        names = {b.osis for b in CANON_CATHOLIC.books}
        assert "1Macc" in names

    def test_john_has_21_chapters(self):
        assert chapter_count("John", CANON_CATHOLIC) == 21

    def test_matthew_has_28_chapters(self):
        assert chapter_count("Matt", CANON_CATHOLIC) == 28

    def test_luke_has_24_chapters(self):
        assert chapter_count("Luke", CANON_CATHOLIC) == 24

    def test_acts_has_28_chapters(self):
        assert chapter_count("Acts", CANON_CATHOLIC) == 28

    def test_tobit_has_14_chapters(self):
        assert chapter_count("Tob", CANON_CATHOLIC) == 14

    def test_judith_has_16_chapters(self):
        assert chapter_count("Jdt", CANON_CATHOLIC) == 16

    def test_1macc_has_16_chapters(self):
        assert chapter_count("1Macc", CANON_CATHOLIC) == 16


# =============================================================================
# LOCAL TESTS — Morphology descriptions (no network needed)
# =============================================================================


@pytest.mark.skipif(not _has_morphology, reason="Morphology not available")
class TestPriestScenarioMorphologyLocal:
    """Verify morphology description utilities work for scenario-related codes."""

    def test_describe_present_active_participle(self):
        """G5487 (χαριτόω) in Luke 1:28 is a perfect passive participle."""
        desc = describe_robinson("V-XPP-NSF")
        assert len(desc) > 0

    def test_describe_present_active_indicative(self):
        """Common verb form for many NT verses."""
        desc = describe_robinson("V-PAI-3S")
        assert len(desc) > 0
        assert "Present" in desc

    def test_describe_nominative_noun(self):
        """Noun form common in John 1:1."""
        desc = describe_robinson("N-NSM")
        assert len(desc) > 0

    def test_describe_aorist_passive_subjunctive(self):
        """Used in sacramental passages."""
        desc = describe_robinson("V-APS-3S")
        assert len(desc) > 0

    def test_describe_unknown_code_returns_string(self):
        """Unknown Robinson codes should not crash."""
        desc = describe_robinson("X-UNKNOWN-XYZ")
        assert isinstance(desc, str)
        assert len(desc) > 0


# =============================================================================
# LOCAL TESTS — Lectionary structure
# =============================================================================


@pytest.mark.skipif(not _has_lectionary, reason="Lectionary not available")
class TestPriestScenarioLectionaryLocal:
    """Verify lectionary has entries covering the liturgical calendar."""

    def test_lectionary_has_entries(self):
        """The hardcoded lectionary should have entries."""
        assert isinstance(_LECTIONARY, dict)
        assert len(_LECTIONARY) > 0

    def test_lectionary_trinity_or_ordinary_time_exists(self):
        """At least one date in May/June 2026 should yield readings."""
        for date_str in ["2026-05-25", "2026-05-31", "2026-06-01"]:
            try:
                result = get_lectionary_for_date_string(date_str)
                if result is not None:
                    title, readings = result
                    assert len(title) > 0
                    assert isinstance(readings, dict)
                    break
            except Exception:
                continue
        # If none returned, that's OK — lectionary data may not cover these dates


# =============================================================================
# IMPORTS SMOKE TEST
# =============================================================================


class TestImportAvailability:
    """Document which tools are importable (informational, not failing)."""

    def test_canon_importable(self):
        assert _has_canon, "Canon module should always be available"

    def test_bible_api_importable(self):
        assert _has_bible_api, "Bible API should always be importable"

    def test_morphology_importable(self):
        assert _has_morphology, "Morphology should always be importable"

    def test_multi_tools_importable(self):
        assert _has_multi_tools, "mcp_multi_tools should be importable"

    def test_acc2_tools_importable(self):
        assert _has_acc2_tools, "mcp_acc2_tools should be importable"

    def test_search_tools_importable(self):
        assert _has_search_tools, "mcp_search_tools should be importable"

    def test_mcp_server_import_status(self):
        """Report MCP server import status — may fail if FastMCP not installed."""
        if not _has_mcp_server:
            pytest.skip(f"MCP server not importable: {_mcp_server_import_error}")

    def test_network_status(self):
        """Report whether bolls.life API is reachable."""
        if not _has_network:
            pytest.skip("Network/API not available — bolls.life may be unreachable")


# =============================================================================
# Runner
# =============================================================================

if __name__ == "__main__":
    pytest.main([__file__, "-v"])
