"""Tests for Greek/Hebrew language tools — morphology, encoding, interlinear."""
from __future__ import annotations
import pytest

# --- Canon ---
try:
    from accordance_parser.canon import parse_reference
    _has_canon = True
except Exception:
    _has_canon = False

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

# --- Encoding ---
try:
    from accordance_parser.encoding import (
        decode_always, decode_hebrew_always,
    )
    _has_encoding = True
except Exception:
    _has_encoding = False

# --- Network detection ---
_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


# =====================================================================
# LOCAL TESTS — Morphology code descriptions
# =====================================================================

@pytest.mark.skipif(not _has_morphology, reason="Morphology not available")
class TestRobinsonCodeDescriptions:
    """S-T-9, S-L-3, S-L-4, S-L-5: Robinson Greek morphology code descriptions."""

    def test_present_active_indicative(self):
        desc = describe_robinson("V-PAI-3S")
        assert "Present" in desc
        assert "Active" in desc
        assert "Indicative" in desc

    def test_aorist_active_indicative(self):
        desc = describe_robinson("V-AAI-3S")
        assert "Aorist" in desc
        assert "Active" in desc
        assert "Indicative" in desc

    def test_perfect_active_indicative(self):
        desc = describe_robinson("V-XAI-3S")
        assert "Perfect" in desc
        assert "Active" in desc

    def test_present_active_imperative(self):
        desc = describe_robinson("V-PAM-2P")
        assert "Present" in desc
        assert "Imperative" in desc

    def test_aorist_active_imperative(self):
        desc = describe_robinson("V-AAM-2S")
        assert "Aorist" in desc
        assert "Imperative" in desc

    def test_present_active_participle(self):
        desc = describe_robinson("V-PAP-NSM")
        assert "Present" in desc
        assert "Participle" in desc

    def test_perfect_passive_participle(self):
        desc = describe_robinson("V-XPP-NSF")
        assert "Perfect" in desc or "Passive" in desc or "Participle" in desc

    def test_aorist_passive_subjunctive(self):
        desc = describe_robinson("V-APS-3S")
        assert "Aorist" in desc or "Passive" in desc or "Subjunctive" in desc

    def test_nominative_noun(self):
        desc = describe_robinson("N-NSM")
        assert "Nominative" in desc or "Noun" in desc

    def test_dative_feminine(self):
        desc = describe_robinson("N-DSF")
        assert "Dative" in desc or "Feminine" in desc

    def test_unknown_code_returns_string(self):
        desc = describe_robinson("X-UNKNOWN-123")
        assert isinstance(desc, str)
        assert len(desc) > 0

    def test_empty_string_handled(self):
        desc = describe_robinson("")
        assert isinstance(desc, str)


@pytest.mark.skipif(not _has_morphology, reason="Morphology not available")
class TestHebrewMorphDescriptions:
    """S-P-8, S-L-9: Hebrew OSHB morphology code descriptions."""

    def test_qal_perfect(self):
        desc = describe_hebrew_morph("HVqp3ms")
        assert isinstance(desc, str)
        assert len(desc) > 0
        assert "Qal" in desc or "Perfect" in desc or "Verb" in desc

    def test_qal_imperfect(self):
        desc = describe_hebrew_morph("HVqi3ms")
        assert isinstance(desc, str)
        assert len(desc) > 0

    def test_qal_imperative(self):
        desc = describe_hebrew_morph("HVqv2ms")
        assert isinstance(desc, str)
        assert len(desc) > 0

    def test_noun_code(self):
        desc = describe_hebrew_morph("HNcmsa")
        assert isinstance(desc, str)
        assert len(desc) > 0

    def test_empty_code(self):
        desc = describe_hebrew_morph("")
        assert isinstance(desc, str)


# =====================================================================
# LOCAL TESTS — Encoding (Greek and Hebrew)
# =====================================================================

@pytest.mark.skipif(not _has_encoding, reason="Encoding not available")
class TestGreekEncoding:
    """S-T-11: Greek polytonic Unicode encoding."""

    def test_alpha_acute(self):
        # alpha (a) + acute accent (0xC0) -> ά
        result = decode_always(b"a\xc0")
        assert "\u03ac" in result  # ά

    def test_alpha_smooth_breathing(self):
        # alpha + smooth breathing -> ἀ
        result = decode_always(b"a\xee")
        assert "\u1f00" in result or "\u1f01" in result or "ἀ" in result or "ἁ" in result

    def test_alpha_rough_breathing(self):
        result = decode_always(b"a\xe1")
        # Single Unicode character may have len 1
        assert len(result) >= 1

    def test_eta_circumflex(self):
        # eta + circumflex -> ῆ
        result = decode_always(b"h\xcf")
        assert "\u1fc6" in result or "ῆ" in result or len(result) >= 1

    def test_epsilon_smooth_acute(self):
        # epsilon + smooth+acute -> ἔ
        result = decode_always(b"e\xa6")
        assert len(result) >= 1

    def test_decode_handles_ascii(self):
        """decode passes through ASCII (decode_always maps to Greek)."""
        from accordance_parser.encoding import decode
        result = decode(b"logos")
        assert "logos" in result

    def test_decode_mixed_greek_english(self):
        """Mixed Greek and English should decode cleanly."""
        from accordance_parser.encoding import decode
        result = decode(b"a\xc0 logos")
        assert "logos" in result
        assert len(result) >= len("a logos")

    def test_decode_returns_str(self):
        result = decode_always(b"test")
        assert isinstance(result, str)


@pytest.mark.skipif(not _has_encoding, reason="Encoding not available")
class TestHebrewEncoding:
    """S-T-11: Hebrew pointed Unicode encoding."""

    def test_aleph_qamats(self):
        # aleph (a) + qamats (0xB6) -> אָ
        result = decode_hebrew_always(b"a\xb6")
        assert "\u05d0" in result  # aleph
        assert "\u05b8" in result or "\u05b6" in result  # vowel point

    def test_aleph_segol(self):
        result = decode_hebrew_always(b"a\xeb")
        assert "\u05d0" in result

    def test_bet_dagesh(self):
        result = decode_hebrew_always(b"b\xc9")
        assert "\u05d1" in result  # bet

    def test_shin_dot(self):
        result = decode_hebrew_always(b"v\xa5")
        assert "\u05e9" in result  # shin

    def test_hebrew_returns_str(self):
        result = decode_hebrew_always(b"abgd")
        assert isinstance(result, str)
        assert len(result) >= 4


# =====================================================================
# LOCAL TESTS — Reference parsing for language-study passages
# =====================================================================

@pytest.mark.skipif(not _has_canon, reason="Canon not available")
class TestLanguageVerseReferences:
    """S-P-8, S-T-9, S-T-10, S-T-11, S-L-3, S-L-4, S-L-9: Reference parsing."""

    def test_matthew_16_18(self):
        r = parse_reference("Matthew 16:18", "catholic")
        assert r is not None
        assert r.book_osis == "Matt"

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

    def test_psalm_51_10(self):
        r = parse_reference("Psalm 51:10", "catholic")
        assert r is not None

    def test_hebrews_11_4(self):
        r = parse_reference("Hebrews 11:4", "catholic")
        assert r is not None
        assert r.book_osis == "Heb"

    def test_hebrews_11_17(self):
        r = parse_reference("Hebrews 11:17", "catholic")
        assert r is not None
        assert r.book_osis == "Heb"

    def test_1thess_5_14(self):
        r = parse_reference("1 Thessalonians 5:14", "catholic")
        assert r is not None

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

    def test_exodus_34_6(self):
        r = parse_reference("Exodus 34:6", "catholic")
        assert r is not None

    def test_deuteronomy_6_4(self):
        r = parse_reference("Deuteronomy 6:4", "catholic")
        assert r is not None


# =====================================================================
# NETWORK-DEPENDENT TESTS
# =====================================================================

@pytest.mark.skipif(not _has_network, reason="Requires network")
class TestVerseTextGreek:
    """S-T-11: Verse text retrieval for Greek passages."""

    def test_tischendorf_john_1_34(self):
        r = get_verse("John 1:34", "TISCH")
        if r is not None and r.text:
            # Should contain Greek characters
            has_greek = any(ord(c) > 127 for c in r.text)
            assert has_greek or len(r.text) > 5

    def test_wlc_deut_6_4(self):
        r = get_verse("Deuteronomy 6:4", "WLC")
        if r is not None and r.text:
            has_hebrew = any(ord(c) > 127 for c in r.text)
            assert has_hebrew or len(r.text) > 5
