"""Session 76 — Daily life / parish ministry scenario tests for Accordance Port.

Scenarios:
  S1  — Lent-to-Easter Multi-Day Liturgical Chain (S-P-17)
  S2  — Catholic Social Teaching Proof-Text Chain (Amos + Matthew + James)
  S3  — RCIA Bible Timeline: Covenants Through Salvation History
  S4  — Spanish Bilingual Ministry: John 3:16 Across Languages
  S5  — Book of Ruth: Full Parish Small-Group Study
  S6  — Pericope Adulterae Text-Critical Chain (S-P-15)
  S7  — RCIA Eucharist Catechesis (S-P-19 adapted)
  S8  — Liturgical Season Theme: Empty Tomb → Cross-References
  S9  — Comprehensive Commentator Comparison on a Catholic Doctrine

All tests are skippable if required modules/network are not available.
Tests are concrete, callable, and ≤15 lines each.
"""
from __future__ import annotations

import pytest


# =============================================================================
# IMPORT GUARDS — try importing every dependency
# =============================================================================

# --- Canon (local) ---
try:
    from accordance_parser.canon import (
        resolve_book,
    )
    _has_canon = True
except Exception:
    _has_canon = False

# --- Bible API (local cache for KJV, network for others) ---
try:
    from accordance_parser.bible_api import get_verse
    _has_bible_api = True
except Exception:
    _has_bible_api = False

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

# --- Multi-tools (local) ---
try:
    from accordance_services.tools.text import (
        get_book_list,
        get_chapter_list,
        get_verse_range,
    )
    from accordance_services.tools.commentary import compare_commentaries
    _has_multi_tools = True
except Exception:
    _has_multi_tools = False

# --- Strong's search tools (local) ---
try:
    from accordance_services.tools.strongs import search_verses_by_strongs
    _has_strongs_tools = True
except Exception:
    _has_strongs_tools = False

# --- MCP server tools (depends on FastMCP/uvicorn) ---
_has_mcp_server = False
try:
    from accordance_mcp_server import (
        compare_catholic_translations,
        compare_translations,
        find_cross_references,
        search_all,
        search_commentaries,
        search_dictionary,
        study_strongs_number,
        get_commentary_text,
    )
    _has_mcp_server = True
except Exception:
    pass


# =============================================================================
# NETWORK DETECTION
# =============================================================================

_has_network = False
try:
    from accordance_parser.bible_api import get_verse as _gv
    r = _gv("Genesis 1:1", "KJV")
    if r and r.text:
        _has_network = True
except Exception:
    pass


# =============================================================================
# HELPERS
# =============================================================================

def _str_ok(text: str) -> bool:
    """Return True if text is a non-empty string with no Python traceback."""
    if not isinstance(text, str):
        return False
    if not text.strip():
        return False
    if "Traceback (most recent call last)" in text:
        return False
    return True


# =============================================================================
# S1 — LENT-TO-EASTER MULTI-DAY LITURGICAL CHAIN (S-P-17)
# =============================================================================

@pytest.mark.skipif(not _has_lectionary, reason="Lectionary module not available")
class TestS1_LentToEasterChain:
    """S1: 5 key dates spanning Lent through Easter 2026, chaining to cross-refs."""

    LENT_EASTER_DATES = {
        "2026-02-18": "Ash Wednesday",
        "2026-03-29": "Palm Sunday",
        "2026-04-02": "Holy Thursday",
        "2026-04-03": "Good Friday",
        "2026-04-05": "Easter Sunday",
    }

    def test_all_five_dates_return_readings(self):
        """All 5 Lent-to-Easter dates return structured lectionary data."""
        for date_str, label in self.LENT_EASTER_DATES.items():
            result = get_lectionary_for_date_string(date_str)
            assert result is not None, f"Missing lectionary for {label} ({date_str})"
            season, readings = result
            assert isinstance(season, str) and len(season) > 0
            for key in ["first", "gospel"]:
                assert key in readings, f"Missing '{key}' for {label}"
                assert readings[key].strip(), f"Empty '{key}' for {label}"

    def test_ash_wednesday_differs_from_easter(self):
        """Ash Wednesday readings (Joel 2) differ from Easter Sunday readings."""
        aw = get_lectionary_for_date_string("2026-02-18")
        es = get_lectionary_for_date_string("2026-04-05")
        assert aw is not None and es is not None
        _, aw_readings = aw
        _, es_readings = es
        assert aw_readings["first"] != es_readings["first"]
        assert aw_readings["gospel"] != es_readings["gospel"]

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_easter_gospel_chain_to_crossrefs(self):
        """Chain Easter gospel → cross-refs → verify result is non-empty."""
        result = get_lectionary_for_date_string("2026-04-05")
        assert result is not None
        _, readings = result
        gospel_ref = readings["gospel"]
        xref = find_cross_references(gospel_ref)
        assert isinstance(xref, str) and len(xref) > 0
        assert "Traceback" not in xref


# =============================================================================
# S2 — CATHOLIC SOCIAL TEACHING PROOF-TEXT CHAIN
# =============================================================================

@pytest.mark.skipif(not _has_network, reason="Requires network for NABRE")
class TestS2_CatholicSocialTeaching:
    """S2: Amos 5:21-24 + Matthew 25:35-40 + James 2:14-17 — social teaching chain."""

    def test_amos_5_21_24_nabre(self):
        """Amos 5:21-24 — 'let justice roll down like waters'."""
        result = get_verse("Amos 5:21-24", "NABRE")
        assert result is not None and result.text
        assert any(w in result.text.lower() for w in ["hate", "despise", "righteousness", "justice", "waters"])

    def test_matthew_25_35_40_nabre(self):
        """Matthew 25:35-40 — 'I was hungry and you gave me food'."""
        result = get_verse("Matthew 25:35-40", "NABRE")
        assert result is not None and result.text
        assert any(w in result.text.lower() for w in ["hungry", "thirsty", "prison"])

    def test_james_2_14_17_nabre(self):
        """James 2:14-17 — 'faith without works is dead'."""
        result = get_verse("James 2:14-17", "NABRE")
        assert result is not None and result.text
        assert any(w in result.text.lower() for w in ["faith", "works", "dead"])

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_compare_catholic_matthew_25_40(self):
        """compare_catholic_translations on Matthew 25:40 returns NABRE/NRSVCE/DRB."""
        result = compare_catholic_translations("Matthew 25:40")
        assert _str_ok(result)
        assert "NABRE" in result

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_search_commentaries_james_2_17(self):
        """search_commentaries('James 2:17') returns entries."""
        result = search_commentaries("James 2:17")
        assert isinstance(result, str) and len(result) > 0

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_find_crossrefs_amos_5_24(self):
        """find_cross_references('Amos 5:24') returns non-empty result."""
        result = find_cross_references("Amos 5:24")
        assert isinstance(result, str) and len(result) > 0

    @pytest.mark.skipif(not _has_canon, reason="Canon module not available")
    def test_amos_is_minor_prophet(self):
        """Amos resolves via canon — verify it's a distinct book class."""
        book = resolve_book("Amos")
        assert book is not None
        assert book.osis == "Amos"
        # Amos is a Minor Prophet (distinct from Gospels/Epistles)
        assert "Amos" in str(book.osis)


# =============================================================================
# S3 — RCIA BIBLE TIMELINE: COVENANTS THROUGH SALVATION HISTORY
# =============================================================================

@pytest.mark.skipif(not _has_multi_tools, reason="Multi-tools not available")
class TestS3_RCIA_Bible_Timeline:
    """S3: Covenants study — Noahic, Abrahamic — via book/chapter/verse/cross-ref."""

    def test_get_book_list_catholic_returns_73(self):
        """get_book_list('catholic') returns 73 books."""
        result = get_book_list(canon="catholic")
        assert "73" in result

    def test_get_chapter_list_genesis_returns_50(self):
        """get_chapter_list('Genesis', canon='catholic') returns 50 chapters."""
        result = get_chapter_list("Genesis", canon="catholic")
        assert "50" in result

    @pytest.mark.skipif(not _has_network, reason="Requires network for NABRE verse range")
    def test_genesis_9_1_17_noahic_covenant_range(self):
        """get_verse_range('NABRE', 'Genesis 9:1', 'Genesis 9:17') returns covenant text."""
        result = get_verse_range("NABRE", "Genesis 9:1", "Genesis 9:17")
        assert _str_ok(result)
        assert any(w in result.lower() for w in ["covenant", "rainbow", "flood", "noah"])

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_search_all_covenant_10_results(self):
        """search_all('covenant', max_results=10) returns results across modules."""
        result = search_all("covenant", max_results=10)
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_find_crossrefs_genesis_17_7_abrahamic(self):
        """find_cross_references('Genesis 17:7') returns Abrahamic covenant links."""
        result = find_cross_references("Genesis 17:7")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result


# =============================================================================
# S4 — SPANISH BILINGUAL MINISTRY: JOHN 3:16 ACROSS LANGUAGES
# =============================================================================

@pytest.mark.skipif(not _has_network, reason="Requires network for translations")
class TestS4_SpanishBilingualMinistry:
    """S4: John 3:16 in NABRE, LBLA, NBLH — bilingual ministry tool chain."""

    def test_john_3_16_nabre_returns_text(self):
        """John 3:16 NABRE returns 'God so loved the world'."""
        result = get_verse("John 3:16", "NABRE")
        assert result is not None and result.text
        assert "world" in result.text.lower()

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_compare_translations_john_3_16_with_lbla_nblh(self):
        """compare_translations with LBLA, NBLH, NABRE for John 3:16."""
        result = compare_translations("John 3:16", "LBLA,NBLH,NABRE")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_search_commentaries_john_3_16(self):
        """search_commentaries('John 3:16') returns entries (may include Spanish)."""
        result = search_commentaries("John 3:16")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_search_dictionary_amor_spanish(self):
        """search_dictionary('amor') — Spanish dict search works or degrades cleanly."""
        result = search_dictionary("amor")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result


# =============================================================================
# S5 — BOOK OF RUTH: FULL PARISH SMALL-GROUP STUDY
# =============================================================================

@pytest.mark.skipif(not _has_multi_tools, reason="Multi-tools not available")
class TestS5_BookOfRuth:
    """S5: Full Book of Ruth study — book list, chapters, full verse range, commentary."""

    def test_get_book_list_catholic_includes_ruth(self):
        """get_book_list('catholic') includes Ruth (verify position)."""
        result = get_book_list(canon="catholic")
        assert "Ruth" in result

    def test_get_chapter_list_ruth_returns_4(self):
        """get_chapter_list('Ruth', canon='catholic') returns 4 chapters."""
        result = get_chapter_list("Ruth", canon="catholic")
        assert "4" in result

    @pytest.mark.skipif(not _has_network, reason="Requires network for NABRE verse range")
    def test_get_verse_range_ruth_full_book(self):
        """get_verse_range('NABRE', 'Ruth 1:1', 'Ruth 4:22') returns full book."""
        result = get_verse_range("NABRE", "Ruth 1:1", "Ruth 4:22")
        assert _str_ok(result)
        assert any(w in result.lower() for w in ["naomi", "ruth", "boaz"])

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_search_commentaries_ruth_1_16(self):
        """search_commentaries('Ruth 1:16') returns commentary entries."""
        result = search_commentaries("Ruth 1:16")
        assert isinstance(result, str) and len(result) > 0

    @pytest.mark.skipif(not _has_network, reason="Requires network for NABRE")
    def test_ruth_1_16_text_correct_your_people_my_people(self):
        """Ruth 1:16 NABRE — 'your people shall be my people' text is correct."""
        result = get_verse("Ruth 1:16", "NABRE")
        assert result is not None and result.text
        text = result.text.lower()
        assert any(phrase in text for phrase in ["your people", "my people", "your god", "my god"])


# =============================================================================
# S6 — PERICOPE ADULTERAE TEXT-CRITICAL CHAIN (S-P-15)
# =============================================================================

@pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
class TestS6_PericopeAdulterae:
    """S6: Text-critical chain — NA28/LXX apparatus, translations, NABRE handling."""

    def test_get_commentary_na28_apparatus_john_7_53(self):
        """get_commentary_text('NA28 Apparatus', 'John 7:53') returns content."""
        result = get_commentary_text("NA28 Apparatus", "John 7:53")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    def test_get_commentary_lxx_apparatus_daniel_13_1(self):
        """get_commentary_text('LXX Apparatus', 'Daniel 13:1') returns Susanna content."""
        result = get_commentary_text("LXX Apparatus", "Daniel 13:1")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_network, reason="Requires network for translations")
    def test_compare_translations_john_7_53_kjv_esv_nasb(self):
        """compare_translations for John 7:53 in KJV, ESV, NASB."""
        result = compare_translations("John 7:53", "KJV,ESV,NASB")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result
        # KJV includes the pericope; ESV may bracket it
        assert any(label in result for label in ["KJV", "ESV", "NASB"])

    @pytest.mark.skipif(not _has_network, reason="Requires network")
    def test_nabre_pericope_adulterae_bracketed(self):
        """John 7:53 NABRE may return None (NABRE brackets it); KJV has the pericope."""
        result = get_verse("John 7:53", "NABRE")
        if result is None:
            result = get_verse("John 7:53", "KJV")
        assert result is not None and result.text
        assert isinstance(result.text, str)


# =============================================================================
# S7 — RCIA EUCHARIST CATECHESIS (S-P-19 adapted)
# =============================================================================

@pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
class TestS7_EucharistCatechesis:
    """S7: Eucharist topic search, John 6 bread-of-life, Strong's G5315 study."""

    def test_search_all_eucharist_10_results(self):
        """search_all('Eucharist', max_results=10) returns cross-module results."""
        result = search_all("Eucharist", max_results=10)
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_network, reason="Requires network for NABRE")
    def test_john_6_53_58_bread_of_life_discourse(self):
        """John 6:53-58 NABRE returns 'eat my flesh / drink my blood'."""
        result = get_verse("John 6:53-58", "NABRE")
        assert result is not None and result.text
        text = result.text.lower()
        assert any(w in text for w in ["flesh", "blood", "eat", "drink", "life"])

    def test_study_strongs_G5315_esthio(self):
        """study_strongs_number('G5315') returns entry for ἐσθίω (eat)."""
        result = study_strongs_number("G5315")
        assert _str_ok(result)
        assert "G5315" in result or "5315" in result or "def" in result.lower()

    @pytest.mark.skipif(not _has_strongs_tools, reason="Strong's tools not available")
    def test_search_verses_by_strongs_G5315(self):
        """search_verses_by_strongs('G5315', max_results=15) finds verses."""
        result = search_verses_by_strongs("G5315", max_results=15)
        assert isinstance(result, str) and len(result) > 0

    @pytest.mark.skipif(not _has_network, reason="Requires network")
    def test_compare_catholic_john_6_53(self):
        """compare_catholic_translations('John 6:53') returns NABRE/NRSVCE/DRB."""
        result = compare_catholic_translations("John 6:53")
        assert _str_ok(result)
        assert "NABRE" in result


# =============================================================================
# S8 — LITURGICAL SEASON THEME: EMPTY TOMB → CROSS-REFERENCES
# =============================================================================

@pytest.mark.skipif(not _has_lectionary, reason="Lectionary module not available")
class TestS8_EmptyTombCrossRefs:
    """S8: Easter Sunday lectionary → gospel text → cross-refs → commentary chain."""

    def test_easter_sunday_returns_gospel_with_resurrection(self):
        """2026-04-05 Easter Sunday returns gospel with resurrection account."""
        result = get_lectionary_for_date_string("2026-04-05")
        assert result is not None
        season, readings = result
        gospel = readings["gospel"]
        assert "John" in gospel or "Matthew" in gospel or "Mark" in gospel or "Luke" in gospel
        assert "Easter" in season or "Resurrection" in season or "Sunday" in season

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_easter_crossrefs_from_gospel(self):
        """find_cross_references on Easter gospel returns non-empty result."""
        result = get_lectionary_for_date_string("2026-04-05")
        assert result is not None
        _, readings = result
        xref = find_cross_references(readings["gospel"])
        assert isinstance(xref, str) and len(xref) > 0

    @pytest.mark.skipif(not _has_network, reason="Requires network for NABRE")
    def test_easter_readings_contain_resurrection_language(self):
        """Easter gospel text contains 'tomb', 'risen', or 'resurrection'."""
        result = get_lectionary_for_date_string("2026-04-05")
        assert result is not None
        _, readings = result
        verse = get_verse(readings["gospel"], "NABRE")
        assert verse is not None and verse.text
        text = verse.text.lower()
        assert any(w in text for w in ["tomb", "risen", "resurrection", "empty", "alive"])

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_easter_chain_lectionary_to_commentary(self):
        """Chain: lectionary gospel → search_commentaries returns results."""
        result = get_lectionary_for_date_string("2026-04-05")
        assert result is not None
        _, readings = result
        comm = search_commentaries(readings["gospel"])
        assert isinstance(comm, str) and len(comm) > 0
        assert "Traceback" not in comm


# =============================================================================
# S9 — COMPREHENSIVE COMMENTATOR COMPARISON ON A CATHOLIC DOCTRINE
# =============================================================================

@pytest.mark.skipif(not _has_multi_tools, reason="Multi-tools not available")
class TestS9_CommentaryComparisonPetrinePrimacy:
    """S9: compare_commentaries on Matthew 16:18, Catholic SB-3 + Hermeneia NT-21."""

    def test_compare_commentaries_matthew_16_18_three_modules(self):
        """compare_commentaries with 3+ modules on Matthew 16:18 returns distinct text."""
        result = compare_commentaries("Matthew 16:18", "Catholic SB-3, Hermeneia NT-21, JFB")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_get_commentary_catholic_sb3_matthew_16_18(self):
        """get_commentary_text('Catholic SB-3', 'Matthew 16:18') returns Petrine content."""
        result = get_commentary_text("Catholic SB-3", "Matthew 16:18")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_get_commentary_hermeneia_nt21_matthew_16_18(self):
        """get_commentary_text('Hermeneia NT-21', 'Matthew 16:18') returns content."""
        result = get_commentary_text("Hermeneia NT-21", "Matthew 16:18")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_mcp_server, reason="MCP server tools not available")
    def test_search_dictionary_petros_lexicon(self):
        """search_dictionary('petros') or 'petra' in Greek lexicons returns results."""
        result = search_dictionary("petros")
        if isinstance(result, str) and len(result.strip()) == 0:
            result = search_dictionary("petra")
        assert isinstance(result, str) and len(result) > 0
        assert "Traceback" not in result

    @pytest.mark.skipif(not _has_network, reason="Requires network for NABRE")
    def test_matthew_16_18_text_upon_this_rock(self):
        """Matthew 16:18 NABRE — 'upon this rock I will build my church'."""
        result = get_verse("Matthew 16:18", "NABRE")
        assert result is not None and result.text
        text = result.text.lower()
        assert "rock" in text or "church" in text or "peter" in text
