"""
Edge case and error handling tests for KJV Study API

Fixtures are imported from conftest.py
"""
import pytest


class TestErrorHandling:
    """Tests for error handling and edge cases"""

    def test_invalid_book_name(self, client):
        """Test verse endpoint with non-existent book"""
        response = client.get("/api/verse/NotABook/1/1")
        assert response.status_code == 404

    def test_invalid_chapter_number(self, client):
        """Test verse endpoint with invalid chapter"""
        response = client.get("/api/verse/Genesis/999/1")
        assert response.status_code == 404

    def test_invalid_verse_number(self, client):
        """Test verse endpoint with invalid verse"""
        response = client.get("/api/verse/John/3/999")
        assert response.status_code == 404

    def test_negative_chapter(self, client):
        """Test verse endpoint with negative chapter"""
        response = client.get("/api/verse/Genesis/-1/1")
        assert response.status_code in [404, 422, 500]

    def test_negative_verse(self, client):
        """Test verse endpoint with negative verse"""
        response = client.get("/api/verse/Genesis/1/-1")
        assert response.status_code in [404, 422, 500]

    def test_zero_chapter(self, client):
        """Test verse endpoint with zero chapter"""
        response = client.get("/api/verse/Genesis/0/1")
        assert response.status_code in [404, 422, 500]

    def test_zero_verse(self, client):
        """Test verse endpoint with zero verse"""
        response = client.get("/api/verse/Genesis/1/0")
        assert response.status_code in [404, 422, 500]


class TestVerseRangeEdgeCases:
    """Tests for verse range edge cases"""

    def test_reversed_verse_range(self, client):
        """Test verse range with start > end"""
        response = client.get("/api/verse-range/John/3/16/1")
        # Should handle reversed ranges gracefully - 404 is acceptable (no verses found)
        assert response.status_code in [200, 400, 404, 422, 500]

    def test_single_verse_range(self, client):
        """Test verse range with start = end"""
        response = client.get("/api/verse-range/John/3/16/16")
        assert response.status_code == 200
        if response.status_code == 200:
            data = response.json()
            assert len(data["verses"]) == 1

    def test_large_verse_range(self, client):
        """Test verse range spanning many verses"""
        response = client.get("/api/verse-range/Psalms/119/1/176")
        assert response.status_code == 200
        data = response.json()
        assert len(data["verses"]) == 176

    def test_verse_range_exceeds_chapter(self, client):
        """Test verse range that goes beyond chapter length"""
        response = client.get("/api/verse-range/John/3/1/999")
        # Should handle gracefully, possibly returning up to last verse
        assert response.status_code in [200, 404, 422]


class TestBookAbbreviations:
    """Comprehensive tests for book name abbreviations"""

    def test_old_testament_abbreviations(self, client):
        """Test various Old Testament book abbreviations"""
        abbreviations = {
            "Gen": "Genesis",
            "Exo": "Exodus",
            "Lev": "Leviticus",
            "Num": "Numbers",
            "Deut": "Deuteronomy",
            "Josh": "Joshua",
            "Ps": "Psalms",
            "Prov": "Proverbs",
            "Isa": "Isaiah",
            "Jer": "Jeremiah",
            "Ezek": "Ezekiel",
            "Dan": "Daniel",
        }

        for abbrev, full_name in abbreviations.items():
            response = client.get(f"/api/books/{abbrev}")
            assert response.status_code in [200, 404]
            if response.status_code == 200:
                data = response.json()
                # Response has "name" field, not "book"
                assert data["name"] == full_name

    def test_new_testament_abbreviations(self, client):
        """Test various New Testament book abbreviations"""
        abbreviations = {
            "Matt": "Matthew",
            "Rom": "Romans",
            "Cor": "Corinthians",
            "Gal": "Galatians",
            "Eph": "Ephesians",
            "Phil": "Philippians",
            "Col": "Colossians",
            "Thess": "Thessalonians",
            "Heb": "Hebrews",
            "Jas": "James",
            "Rev": "Revelation",
        }

        for abbrev, full_name in abbreviations.items():
            response = client.get(f"/api/books/{abbrev}")
            # Some abbreviations might need more context (like 1 Cor vs 2 Cor)
            assert response.status_code in [200, 404]

    def test_numbered_book_abbreviations(self, client):
        """Test abbreviations for numbered books"""
        test_cases = [
            ("1 Sam", "I Samuel"),
            ("2 Sam", "II Samuel"),
            ("1 Kings", "I Kings"),
            ("2 Kings", "II Kings"),
            ("1 Cor", "I Corinthians"),
            ("2 Cor", "II Corinthians"),
        ]

        for abbrev, expected in test_cases:
            response = client.get(f"/api/verse/{abbrev}/1/1")
            if response.status_code == 200:
                data = response.json()
                # Book name might be in Roman numerals or Arabic numerals
                assert "Samuel" in data["book"] or "Corinthians" in data["book"] or "Kings" in data["book"]


class TestSearchFunctionality:
    """Comprehensive search tests"""

    def test_search_common_words(self, client):
        """Test search for common biblical words"""
        common_words = ["love", "faith", "hope", "peace", "righteousness"]

        for word in common_words:
            response = client.get(f"/api/search?q={word}")
            assert response.status_code == 200
            data = response.json()
            assert data["total"] > 0
            assert len(data["results"]) > 0

    def test_search_phrase(self, client):
        """Test search for a phrase"""
        response = client.get("/api/search?q=God so loved the world")
        assert response.status_code == 200
        data = response.json()
        assert data["total"] > 0

    def test_search_case_insensitive(self, client):
        """Test search is case insensitive"""
        response1 = client.get("/api/search?q=LOVE&limit=10")
        response2 = client.get("/api/search?q=love&limit=10")

        assert response1.status_code == 200
        assert response2.status_code == 200

        # Results should be similar for case-insensitive search
        data1 = response1.json()
        data2 = response2.json()
        assert data1["total"] > 0
        assert data2["total"] > 0

    def test_search_very_short_query(self, client):
        """Test search with very short query"""
        response = client.get("/api/search?q=a")
        assert response.status_code == 200
        # Might return empty or filtered results for very short queries

    def test_search_special_characters(self, client):
        """Test search with special characters"""
        response = client.get("/api/search?q=love?")
        assert response.status_code == 200

    def test_search_with_zero_limit(self, client):
        """Test search with limit=0"""
        response = client.get("/api/search?q=love&limit=0")
        assert response.status_code == 200

    def test_search_with_large_limit(self, client):
        """Test search with very large limit"""
        response = client.get("/api/search?q=love&limit=10000")
        assert response.status_code == 200
        data = response.json()
        # Should handle large limits gracefully


class TestBookBoundaries:
    """Tests for book boundaries and edge cases"""

    def test_shortest_book(self, client):
        """Test the shortest book (2 John or 3 John)"""
        response = client.get("/api/books/III John/text")
        assert response.status_code == 200
        data = response.json()
        assert data["total_chapters"] == 1
        assert data["total_verses"] > 0

    def test_longest_book(self, client):
        """Test the longest book (Psalms)"""
        response = client.get("/api/books/Psalms")
        assert response.status_code == 200
        data = response.json()
        assert data["total_chapters"] == 150

    def test_first_book(self, client):
        """Test first book of the Bible"""
        response = client.get("/api/books/Genesis")
        assert response.status_code == 200
        data = response.json()
        assert data["name"] == "Genesis"

    def test_last_book(self, client):
        """Test last book of the Bible"""
        response = client.get("/api/books/Revelation")
        assert response.status_code == 200
        data = response.json()
        assert data["name"] == "Revelation"

    def test_longest_chapter(self, client):
        """Test longest chapter (Psalms 119)"""
        response = client.get("/api/books/Psalms/chapters/119")
        assert response.status_code == 200
        data = response.json()
        assert data["total_verses"] == 176


class TestCrossReferencesEdgeCases:
    """Tests for cross-references edge cases"""

    def test_verse_with_no_cross_references(self, client):
        """Test verse that might have no cross-references"""
        response = client.get("/api/cross-references/III John/1/1")
        assert response.status_code == 200
        data = response.json()
        assert "cross_references" in data
        # Might be empty list

    def test_verse_with_many_cross_references(self, client):
        """Test verse with many cross-references"""
        response = client.get("/api/cross-references/John/3/16")
        assert response.status_code == 200
        data = response.json()
        assert "cross_references" in data


class TestInterlinearEdgeCases:
    """Tests for interlinear data edge cases"""

    def test_old_testament_interlinear(self, client):
        """Test interlinear for Old Testament (Hebrew)"""
        response = client.get("/api/interlinear/Genesis/1/1")
        assert response.status_code == 200
        data = response.json()
        assert "interlinear_available" in data

    def test_new_testament_interlinear(self, client):
        """Test interlinear for New Testament (Greek)"""
        response = client.get("/api/interlinear/John/1/1")
        assert response.status_code == 200
        data = response.json()
        assert "interlinear_available" in data


class TestTopicsEdgeCases:
    """Tests for topics edge cases"""

    def test_nonexistent_topic(self, client):
        """Test non-existent topic"""
        response = client.get("/api/topics/notarealtopic123456")
        assert response.status_code == 404

    def test_topic_case_sensitivity(self, client):
        """Test topic name case sensitivity"""
        response1 = client.get("/api/topics/faith")
        response2 = client.get("/api/topics/Faith")
        response3 = client.get("/api/topics/FAITH")

        # At least one should work
        assert any(r.status_code == 200 for r in [response1, response2, response3])


class TestReadingPlansEdgeCases:
    """Tests for reading plans edge cases"""

    def test_nonexistent_reading_plan(self, client):
        """Test non-existent reading plan"""
        response = client.get("/api/reading-plans/not-a-real-plan")
        assert response.status_code == 404

    def test_all_reading_plans_structure(self, client):
        """Test structure of all reading plans"""
        response = client.get("/api/reading-plans")
        assert response.status_code == 200
        data = response.json()

        assert "plans" in data
        for plan in data["plans"]:
            assert "id" in plan
            assert "name" in plan
            assert "description" in plan
            assert "days" in plan


class TestAPIPerformance:
    """Tests for API performance and large data handling"""

    def test_entire_bible_response_size(self, client):
        """Test that entire Bible endpoint returns valid data"""
        response = client.get("/api/bible")
        assert response.status_code == 200
        data = response.json()

        # Verify structure
        assert "total_books" in data
        assert "total_verses" in data
        assert "books" in data

        # Verify counts
        assert data["total_books"] == 66
        assert data["total_verses"] > 31000  # KJV has 31,102 verses

    def test_long_book_response(self, client):
        """Test response for longest books"""
        long_books = ["Psalms", "Genesis", "Isaiah", "Jeremiah"]

        for book in long_books:
            response = client.get(f"/api/books/{book}/text")
            assert response.status_code == 200
            data = response.json()
            assert data["total_verses"] > 100


class TestContentValidation:
    """Tests for content validation"""

    def test_john_3_16_content(self, client):
        """Test that John 3:16 has correct content"""
        response = client.get("/api/verse/John/3/16")
        assert response.status_code == 200
        data = response.json()

        text = data["text"].lower()
        assert "god" in text
        assert "loved" in text
        assert "world" in text
        assert "son" in text

    def test_genesis_1_1_content(self, client):
        """Test that Genesis 1:1 has correct content"""
        response = client.get("/api/verse/Genesis/1/1")
        assert response.status_code == 200
        data = response.json()

        text = data["text"].lower()
        assert "beginning" in text
        assert "god" in text
        assert "created" in text
        assert "heaven" in text
        assert "earth" in text

    def test_psalms_23_1_content(self, client):
        """Test that Psalms 23:1 has correct content"""
        response = client.get("/api/verse/Psalms/23/1")
        assert response.status_code == 200
        data = response.json()

        text = data["text"].lower()
        assert "lord" in text
        assert "shepherd" in text


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