"""
Verify Hermeneia inline-ref detection correctly identifies
Hermeneia AF/OT2/Q/2PS modules and builds them with >0 verse-referenced entries.

These modules were previously misdetected as "generic" in production;
inline-ref-based detection now recovers them automatically.

Run with: pytest test_prototype_hermeneia_detection.py -v
"""

import os
import pytest
from accordance_parser.commentary_module import CommentaryModule

# ---------------------------------------------------------------------------
# Module paths (same as test_audit_commentaries_b.py)
# ---------------------------------------------------------------------------

_MODULE_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "modules", "Tools")

_BUGGY_MODULES = {
    "Hermeneia AF":    os.path.join(_MODULE_DIR, "Hermeneia AF.atool", "Hermeneia AF"),
    "Hermeneia OT2":   os.path.join(_MODULE_DIR, "Hermeneia OT2.atool", "Hermeneia OT2"),
    "Hermeneia Q":     os.path.join(_MODULE_DIR, "Hermeneia Q.atool", "Hermeneia Q"),
    "Hermeneia2 PS":   os.path.join(_MODULE_DIR, "Hermeneia2 PS.atool", "Hermeneia2 PS"),
}

# Reference modules that should continue to work correctly
_CONTROL_MODULES = {
    "Hermeneia NT-21": os.path.join(_MODULE_DIR, "Hermeneia NT-21.atool", "Hermeneia NT-21"),
    "Hermeneia NT2":   os.path.join(_MODULE_DIR, "Hermeneia NT2.atool", "Hermeneia NT2"),
    "Hermeneia OT-19": os.path.join(_MODULE_DIR, "Hermeneia OT-19.atool", "Hermeneia OT-19"),
}

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

_cache = {}

def _load(name, module_map):
    """Load a CommentaryModule (cached for test reuse)."""
    if name not in _cache:
        path = module_map[name]
        assert os.path.exists(path), f"Module file missing: {path}"
        cm = CommentaryModule(path)
        _cache[name] = cm
    return _cache[name]


def _verse_entry_count(mod):
    """Count entries that have chapter > 0 (actual verse references, not intros)."""
    return sum(1 for e in mod._entries if e[1] > 0)


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------


class TestHermeneiaDetection:
    """Verify that inline-ref detection correctly classifies
    Hermeneia AF/OT2/Q/2PS as hermeneia."""

    @pytest.mark.parametrize("name", sorted(_BUGGY_MODULES.keys()))
    def test_format_is_hermeneia(self, name):
        """Module should report format='hermeneia'."""
        mod = _load(name, _BUGGY_MODULES)

        # These four modules should now always detect as hermeneia.
        assert mod.format == "hermeneia", (
            f"{name}: expected 'hermeneia', got {mod.format!r}"
        )

    @pytest.mark.parametrize("name", sorted(_BUGGY_MODULES.keys()))
    def test_has_positive_entries(self, name):
        """Module should have >0 entries (verse-referenced, not generic sections)."""
        mod = _load(name, _BUGGY_MODULES)
        total = len(mod._entries)
        verse_entries = _verse_entry_count(mod)
        assert total > 0, f"{name}: 0 entries total"
        assert verse_entries > 0, (
            f"{name}: {total} total entries but 0 verse-referenced (all ch=0)"
        )

    @pytest.mark.parametrize("name", sorted(_BUGGY_MODULES.keys()))
    def test_has_book_boundaries(self, name):
        """Module should have detected book boundaries."""
        mod = _load(name, _BUGGY_MODULES)
        assert len(mod._book_boundaries) >= 1, (
            f"{name}: expected >=1 books, got {len(mod._book_boundaries)}"
        )

    @pytest.mark.parametrize("name", sorted(_BUGGY_MODULES.keys()))
    def test_entry_structure(self, name):
        """Entries should follow the Hermeneia tuple structure:
        (book, chapter, vs_start, vs_end, offset)."""
        mod = _load(name, _BUGGY_MODULES)
        for entry in mod._entries[:5]:
            assert len(entry) == 5, f"Bad entry tuple: {entry}"
            book, ch, vs_start, vs_end, offset = entry
            assert isinstance(book, str), f"Book not str: {book!r}"
            assert isinstance(ch, int), f"Chapter not int: {ch}"
            assert ch >= 0, f"Chapter negative: {ch}"
            assert isinstance(vs_start, int), f"vs_start not int: {vs_start}"
            assert isinstance(offset, int), f"Offset not int: {offset}"

    @pytest.mark.parametrize("name", sorted(_BUGGY_MODULES.keys()))
    def test_section_retrieval(self, name):
        """get_section() should return readable text for a known reference."""
        mod = _load(name, _BUGGY_MODULES)
        # Use the known reference for each module
        known_refs = {
            "Hermeneia AF":  "Exodus 1:1",
            "Hermeneia OT2": "Genesis 1:1",
            "Hermeneia Q":   "Ecclesiastes 1:1",
            "Hermeneia2 PS": "Psalms 1:1",
        }
        ref = known_refs[name]
        text = mod.get_section(ref)
        assert text, f"{name}: get_section({ref!r}) returned empty"
        assert len(text.strip()) > 50, (
            f"{name}: section too short ({len(text.strip())} chars)"
        )
        # Should not contain generic-fallback error messages
        assert "[Note:" not in text, (
            f"{name}: got fallback note instead of direct match"
        )
        assert "[Invalid section" not in text, (
            f"{name}: got generic section error"
        )


class TestHermeneiaNoRegressions:
    """Ensure Hermeneia detection does NOT regress modules that already work."""

    @pytest.mark.parametrize("name", sorted(_CONTROL_MODULES.keys()))
    def test_control_modules_still_hermeneia(self, name):
        """NT-21, NT2, OT-19 should remain hermeneia (no change from production)."""
        mod = _load(name, _CONTROL_MODULES)
        assert mod.format == "hermeneia", (
            f"{name}: expected 'hermeneia', got {mod.format!r}"
        )

    @pytest.mark.parametrize("name", sorted(_CONTROL_MODULES.keys()))
    def test_control_modules_have_entries(self, name):
        """NT-21, NT2, OT-19 should still have verse-referenced entries."""
        mod = _load(name, _CONTROL_MODULES)
        verse_entries = _verse_entry_count(mod)
        assert verse_entries > 0, (
            f"{name}: 0 verse-referenced entries"
        )


# ---------------------------------------------------------------------------
# Standalone diagnostic output (run directly with python)
# ---------------------------------------------------------------------------

if __name__ == "__main__":
    print("=== Hermeneia Detection Diagnostic ===\n")

    # Clear cache for fresh loads
    _cache.clear()

    for name, path in _BUGGY_MODULES.items():
        print(f"--- {name} ---")
        if not os.path.exists(path):
            print(f"  SKIPPED: file not found at {path}")
            continue
        cm = CommentaryModule(path)
        fmt = cm.format
        n_total = len(cm._entries)
        n_verse = _verse_entry_count(cm)
        n_books = len(cm._book_boundaries)
        books = cm.list_books()[:10]
        print(f"  Format:     {fmt}")
        print(f"  Entries:    {n_total} total, {n_verse} verse-referenced")
        print(f"  Books:      {n_books} ({[b for b, _ in books]})")

        # Show first 5 verse entries
        verse_entries = [e for e in cm._entries if e[1] > 0]
        if verse_entries:
            print("  First entries:")
            for e in verse_entries[:5]:
                print(f"    {e[0]} {e[1]}:{e[2]}-{e[3]} @offset={e[4]}")

        cm.close()
        print()

    # Control check
    print("--- Control modules (should still work) ---")
    for name, path in _CONTROL_MODULES.items():
        if not os.path.exists(path):
            print(f"  {name}: SKIPPED (not found)")
            continue
        cm = CommentaryModule(path)
        n_verse = _verse_entry_count(cm)
        print(f"  {name}: format={cm.format}, {n_verse} verse entries")
        cm.close()
