"""
Bible data and utilities for the Bible MCP server.

This module contains comprehensive data about Bible structure
including books, chapters, and verses, as well as utility functions
for random verse selection and reference validation.
"""
import random
from typing import Dict, List, Optional, Tuple, Union, Any

# Constants for testament types
OLD_TESTAMENT = "OT"
NEW_TESTAMENT = "NT"

# Single chapter books (with verse counts)
SINGLE_CHAPTER_BOOKS = {
    "OBAD": 21,   # Obadiah - 21 verses
    "PHLM": 25,   # Philemon - 25 verses
    "2JN": 13,    # 2 John - 13 verses
    "3JN": 14,    # 3 John - 14 verses
    "JUD": 25     # Jude - 25 verses
}

# Bible books data with metadata
# Format: {
#     "book_id": {
#         "name": "Full Book Name",
#         "testament": "OT" or "NT",
#         "chapters": number of chapters,
#         "verses": [verses per chapter] or fixed verse count for single-chapter books
#     }
# }
BIBLE_DATA = {
    # Old Testament
    "GEN": {
        "name": "Genesis",
        "testament": OLD_TESTAMENT,
        "chapters": 50,
        "verses": [31, 25, 24, 26, 32, 22, 24, 22, 29, 32, 32, 20, 18, 24, 21, 16, 27, 33, 38, 18, 34, 24, 20, 67, 34, 35, 46, 22, 35, 43, 55, 32, 20, 31, 29, 43, 36, 30, 23, 23, 57, 38, 34, 34, 28, 34, 31, 22, 33, 26]
    },
    "EXO": {
        "name": "Exodus",
        "testament": OLD_TESTAMENT,
        "chapters": 40,
        "verses": [22, 25, 22, 31, 23, 30, 25, 32, 35, 29, 10, 51, 22, 31, 27, 36, 16, 27, 25, 26, 36, 31, 33, 18, 40, 37, 21, 43, 46, 38, 18, 35, 23, 35, 35, 38, 29, 31, 43, 38]
    },
    "LEV": {
        "name": "Leviticus",
        "testament": OLD_TESTAMENT,
        "chapters": 27,
        "verses": [17, 16, 17, 35, 19, 30, 38, 36, 24, 20, 47, 8, 59, 57, 33, 34, 16, 30, 37, 27, 24, 33, 44, 23, 55, 46, 34]
    },
    "NUM": {
        "name": "Numbers",
        "testament": OLD_TESTAMENT,
        "chapters": 36,
        "verses": [54, 34, 51, 49, 31, 27, 89, 26, 23, 36, 35, 16, 33, 45, 41, 50, 13, 32, 22, 29, 35, 41, 30, 25, 18, 65, 23, 31, 40, 16, 54, 42, 56, 29, 34, 13]
    },
    "DEU": {
        "name": "Deuteronomy",
        "testament": OLD_TESTAMENT,
        "chapters": 34,
        "verses": [46, 37, 29, 49, 33, 25, 26, 20, 29, 22, 32, 32, 18, 29, 23, 22, 20, 22, 21, 20, 23, 30, 25, 22, 19, 19, 26, 68, 29, 20, 30, 52, 29, 12]
    },
    "JOS": {
        "name": "Joshua",
        "testament": OLD_TESTAMENT,
        "chapters": 24,
        "verses": [18, 24, 17, 24, 15, 27, 26, 35, 27, 43, 23, 24, 33, 15, 63, 10, 18, 28, 51, 9, 45, 34, 16, 33]
    },
    "JDG": {
        "name": "Judges",
        "testament": OLD_TESTAMENT,
        "chapters": 21,
        "verses": [36, 23, 31, 24, 31, 40, 25, 35, 57, 18, 40, 15, 25, 20, 20, 31, 13, 31, 30, 48, 25]
    },
    "RUT": {
        "name": "Ruth",
        "testament": OLD_TESTAMENT,
        "chapters": 4,
        "verses": [22, 23, 18, 22]
    },
    "1SA": {
        "name": "1 Samuel",
        "testament": OLD_TESTAMENT,
        "chapters": 31,
        "verses": [28, 36, 21, 22, 12, 21, 17, 22, 27, 27, 15, 25, 23, 52, 35, 23, 58, 30, 24, 42, 15, 23, 29, 22, 44, 25, 12, 25, 11, 31, 13]
    },
    "2SA": {
        "name": "2 Samuel",
        "testament": OLD_TESTAMENT,
        "chapters": 24,
        "verses": [27, 32, 39, 12, 25, 23, 29, 18, 13, 19, 27, 31, 39, 33, 37, 23, 29, 33, 43, 26, 22, 51, 39, 25]
    },
    "1KI": {
        "name": "1 Kings",
        "testament": OLD_TESTAMENT,
        "chapters": 22,
        "verses": [53, 46, 28, 34, 18, 38, 51, 66, 28, 29, 43, 33, 34, 31, 34, 34, 24, 46, 21, 43, 29, 53]
    },
    "2KI": {
        "name": "2 Kings",
        "testament": OLD_TESTAMENT,
        "chapters": 25,
        "verses": [18, 25, 27, 44, 27, 33, 20, 29, 37, 36, 21, 21, 25, 29, 38, 20, 41, 37, 37, 21, 26, 20, 37, 20, 30]
    },
    "1CH": {
        "name": "1 Chronicles",
        "testament": OLD_TESTAMENT,
        "chapters": 29,
        "verses": [54, 55, 24, 43, 26, 81, 40, 40, 44, 14, 47, 40, 14, 17, 29, 43, 27, 17, 19, 8, 30, 19, 32, 31, 31, 32, 34, 21, 30]
    },
    "2CH": {
        "name": "2 Chronicles",
        "testament": OLD_TESTAMENT,
        "chapters": 36,
        "verses": [17, 18, 17, 22, 14, 42, 22, 18, 31, 19, 23, 16, 22, 15, 19, 14, 19, 34, 11, 37, 20, 12, 21, 27, 28, 23, 9, 27, 36, 27, 21, 33, 25, 33, 27, 23]
    },
    "EZR": {
        "name": "Ezra",
        "testament": OLD_TESTAMENT,
        "chapters": 10,
        "verses": [11, 70, 13, 24, 17, 22, 28, 36, 15, 44]
    },
    "NEH": {
        "name": "Nehemiah",
        "testament": OLD_TESTAMENT,
        "chapters": 13,
        "verses": [11, 20, 32, 23, 19, 19, 73, 18, 38, 39, 36, 47, 31]
    },
    "EST": {
        "name": "Esther",
        "testament": OLD_TESTAMENT,
        "chapters": 10,
        "verses": [22, 23, 15, 17, 14, 14, 10, 17, 32, 3]
    },
    "JOB": {
        "name": "Job",
        "testament": OLD_TESTAMENT,
        "chapters": 42,
        "verses": [22, 13, 26, 21, 27, 30, 21, 22, 35, 22, 20, 25, 28, 22, 35, 22, 16, 21, 29, 29, 34, 30, 17, 25, 6, 14, 23, 28, 25, 31, 40, 22, 33, 37, 16, 33, 24, 41, 30, 24, 34, 17]
    },
    "PSA": {
        "name": "Psalms",
        "testament": OLD_TESTAMENT,
        "chapters": 150,
        "verses": [6, 12, 8, 8, 12, 10, 17, 9, 20, 18, 7, 8, 6, 7, 5, 11, 15, 50, 14, 9, 13, 31, 6, 10, 22, 12, 14, 9, 11, 12, 24, 11, 22, 22, 28, 12, 40, 22, 13, 17, 13, 11, 5, 26, 17, 11, 9, 14, 20, 23, 19, 9, 6, 7, 23, 13, 11, 11, 17, 12, 8, 12, 11, 10, 13, 20, 7, 35, 36, 5, 24, 20, 28, 23, 10, 12, 20, 72, 13, 19, 16, 8, 18, 12, 13, 17, 7, 18, 52, 17, 16, 15, 5, 23, 11, 13, 12, 9, 9, 5, 8, 28, 22, 35, 45, 48, 43, 13, 31, 7, 10, 10, 9, 8, 18, 19, 2, 29, 176, 7, 8, 9, 4, 8, 5, 6, 5, 6, 8, 8, 3, 18, 3, 3, 21, 26, 9, 8, 24, 13, 10, 7, 12, 15, 21, 10, 20, 14, 9, 6]
    },
    "PRO": {
        "name": "Proverbs",
        "testament": OLD_TESTAMENT,
        "chapters": 31,
        "verses": [33, 22, 35, 27, 23, 35, 27, 36, 18, 32, 31, 28, 25, 35, 33, 33, 28, 24, 29, 30, 31, 29, 35, 34, 28, 28, 27, 28, 27, 33, 31]
    },
    "ECC": {
        "name": "Ecclesiastes",
        "testament": OLD_TESTAMENT,
        "chapters": 12,
        "verses": [18, 26, 22, 16, 20, 12, 29, 17, 18, 20, 10, 14]
    },
    "SNG": {
        "name": "Song of Solomon",
        "testament": OLD_TESTAMENT,
        "chapters": 8,
        "verses": [17, 17, 11, 16, 16, 13, 13, 14]
    },
    "ISA": {
        "name": "Isaiah",
        "testament": OLD_TESTAMENT,
        "chapters": 66,
        "verses": [31, 22, 26, 6, 30, 13, 25, 22, 21, 34, 16, 6, 22, 32, 9, 14, 14, 7, 25, 6, 17, 25, 18, 23, 12, 21, 13, 29, 24, 33, 9, 20, 24, 17, 10, 22, 38, 22, 8, 31, 29, 25, 28, 28, 25, 13, 15, 22, 26, 11, 23, 15, 12, 17, 13, 12, 21, 14, 21, 22, 11, 12, 19, 12, 25, 24]
    },
    "JER": {
        "name": "Jeremiah",
        "testament": OLD_TESTAMENT,
        "chapters": 52,
        "verses": [19, 37, 25, 31, 31, 30, 34, 22, 26, 25, 23, 17, 27, 22, 21, 21, 27, 23, 15, 18, 14, 30, 40, 10, 38, 24, 22, 17, 32, 24, 40, 44, 26, 22, 19, 32, 21, 28, 18, 16, 18, 22, 13, 30, 5, 28, 7, 47, 39, 46, 64, 34]
    },
    "LAM": {
        "name": "Lamentations",
        "testament": OLD_TESTAMENT,
        "chapters": 5,
        "verses": [22, 22, 66, 22, 22]
    },
    "EZK": {
        "name": "Ezekiel",
        "testament": OLD_TESTAMENT,
        "chapters": 48,
        "verses": [28, 10, 27, 17, 17, 14, 27, 18, 11, 22, 25, 28, 23, 23, 8, 63, 24, 32, 14, 49, 32, 31, 49, 27, 17, 21, 36, 26, 21, 26, 18, 32, 33, 31, 15, 38, 28, 23, 29, 49, 26, 20, 27, 31, 25, 24, 23, 35]
    },
    "DAN": {
        "name": "Daniel",
        "testament": OLD_TESTAMENT,
        "chapters": 12,
        "verses": [21, 49, 30, 37, 31, 28, 28, 27, 27, 21, 45, 13]
    },
    "HOS": {
        "name": "Hosea",
        "testament": OLD_TESTAMENT,
        "chapters": 14,
        "verses": [11, 23, 5, 19, 15, 11, 16, 14, 17, 15, 12, 14, 16, 9]
    },
    "JOL": {
        "name": "Joel",
        "testament": OLD_TESTAMENT,
        "chapters": 3,
        "verses": [20, 32, 21]
    },
    "AMO": {
        "name": "Amos",
        "testament": OLD_TESTAMENT,
        "chapters": 9,
        "verses": [15, 16, 15, 13, 27, 14, 17, 14, 15]
    },
    "OBAD": {
        "name": "Obadiah",
        "testament": OLD_TESTAMENT,
        "chapters": 1,
        "verses": 21
    },
    "JON": {
        "name": "Jonah",
        "testament": OLD_TESTAMENT,
        "chapters": 4,
        "verses": [17, 10, 10, 11]
    },
    "MIC": {
        "name": "Micah",
        "testament": OLD_TESTAMENT,
        "chapters": 7,
        "verses": [16, 13, 12, 13, 15, 16, 20]
    },
    "NAM": {
        "name": "Nahum",
        "testament": OLD_TESTAMENT,
        "chapters": 3,
        "verses": [15, 13, 19]
    },
    "HAB": {
        "name": "Habakkuk",
        "testament": OLD_TESTAMENT,
        "chapters": 3,
        "verses": [17, 20, 19]
    },
    "ZEP": {
        "name": "Zephaniah",
        "testament": OLD_TESTAMENT,
        "chapters": 3,
        "verses": [18, 15, 20]
    },
    "HAG": {
        "name": "Haggai",
        "testament": OLD_TESTAMENT,
        "chapters": 2,
        "verses": [15, 23]
    },
    "ZEC": {
        "name": "Zechariah",
        "testament": OLD_TESTAMENT,
        "chapters": 14,
        "verses": [21, 13, 10, 14, 11, 15, 14, 23, 17, 12, 17, 14, 9, 21]
    },
    "MAL": {
        "name": "Malachi",
        "testament": OLD_TESTAMENT,
        "chapters": 4,
        "verses": [14, 17, 18, 6]
    },
    
    # New Testament
    "MAT": {
        "name": "Matthew",
        "testament": NEW_TESTAMENT,
        "chapters": 28,
        "verses": [25, 23, 17, 25, 48, 34, 29, 34, 38, 42, 30, 50, 58, 36, 39, 28, 27, 35, 30, 34, 46, 46, 39, 51, 46, 75, 66, 20]
    },
    "MRK": {
        "name": "Mark",
        "testament": NEW_TESTAMENT,
        "chapters": 16,
        "verses": [45, 28, 35, 41, 43, 56, 37, 38, 50, 52, 33, 44, 37, 72, 47, 20]
    },
    "LUK": {
        "name": "Luke",
        "testament": NEW_TESTAMENT,
        "chapters": 24,
        "verses": [80, 52, 38, 44, 39, 49, 50, 56, 62, 42, 54, 59, 35, 35, 32, 31, 37, 43, 48, 47, 38, 71, 56, 53]
    },
    "JHN": {
        "name": "John",
        "testament": NEW_TESTAMENT,
        "chapters": 21,
        "verses": [51, 25, 36, 54, 47, 71, 53, 59, 41, 42, 57, 50, 38, 31, 27, 33, 26, 40, 42, 31, 25]
    },
    "ACT": {
        "name": "Acts",
        "testament": NEW_TESTAMENT,
        "chapters": 28,
        "verses": [26, 47, 26, 37, 42, 15, 60, 40, 43, 48, 30, 25, 52, 28, 41, 40, 34, 28, 41, 38, 40, 30, 35, 27, 27, 32, 44, 31]
    },
    "ROM": {
        "name": "Romans",
        "testament": NEW_TESTAMENT,
        "chapters": 16,
        "verses": [32, 29, 31, 25, 21, 23, 25, 39, 33, 21, 36, 21, 14, 23, 33, 27]
    },
    "1CO": {
        "name": "1 Corinthians",
        "testament": NEW_TESTAMENT,
        "chapters": 16,
        "verses": [31, 16, 23, 21, 13, 20, 40, 13, 27, 33, 34, 31, 13, 40, 58, 24]
    },
    "2CO": {
        "name": "2 Corinthians",
        "testament": NEW_TESTAMENT,
        "chapters": 13,
        "verses": [24, 17, 18, 18, 21, 18, 16, 24, 15, 18, 33, 21, 14]
    },
    "GAL": {
        "name": "Galatians",
        "testament": NEW_TESTAMENT,
        "chapters": 6,
        "verses": [24, 21, 29, 31, 26, 18]
    },
    "EPH": {
        "name": "Ephesians",
        "testament": NEW_TESTAMENT,
        "chapters": 6,
        "verses": [23, 22, 21, 32, 33, 24]
    },
    "PHP": {
        "name": "Philippians",
        "testament": NEW_TESTAMENT,
        "chapters": 4,
        "verses": [30, 30, 21, 23]
    },
    "COL": {
        "name": "Colossians",
        "testament": NEW_TESTAMENT,
        "chapters": 4,
        "verses": [29, 23, 25, 18]
    },
    "1TH": {
        "name": "1 Thessalonians",
        "testament": NEW_TESTAMENT,
        "chapters": 5,
        "verses": [10, 20, 13, 18, 28]
    },
    "2TH": {
        "name": "2 Thessalonians",
        "testament": NEW_TESTAMENT,
        "chapters": 3,
        "verses": [12, 17, 18]
    },
    "1TI": {
        "name": "1 Timothy",
        "testament": NEW_TESTAMENT,
        "chapters": 6,
        "verses": [20, 15, 16, 16, 25, 21]
    },
    "2TI": {
        "name": "2 Timothy",
        "testament": NEW_TESTAMENT,
        "chapters": 4,
        "verses": [18, 26, 17, 22]
    },
    "TIT": {
        "name": "Titus",
        "testament": NEW_TESTAMENT,
        "chapters": 3,
        "verses": [16, 15, 15]
    },
    "PHLM": {
        "name": "Philemon",
        "testament": NEW_TESTAMENT,
        "chapters": 1,
        "verses": 25
    },
    "HEB": {
        "name": "Hebrews",
        "testament": NEW_TESTAMENT,
        "chapters": 13,
        "verses": [14, 18, 19, 16, 14, 20, 28, 13, 28, 39, 40, 29, 25]
    },
    "JAS": {
        "name": "James",
        "testament": NEW_TESTAMENT,
        "chapters": 5,
        "verses": [27, 26, 18, 17, 20]
    },
    "1PE": {
        "name": "1 Peter",
        "testament": NEW_TESTAMENT,
        "chapters": 5,
        "verses": [25, 25, 22, 19, 14]
    },
    "2PE": {
        "name": "2 Peter",
        "testament": NEW_TESTAMENT,
        "chapters": 3,
        "verses": [21, 22, 18]
    },
    "1JN": {
        "name": "1 John",
        "testament": NEW_TESTAMENT,
        "chapters": 5,
        "verses": [10, 29, 24, 21, 21]
    },
    "2JN": {
        "name": "2 John",
        "testament": NEW_TESTAMENT,
        "chapters": 1,
        "verses": 13
    },
    "3JN": {
        "name": "3 John",
        "testament": NEW_TESTAMENT,
        "chapters": 1,
        "verses": 14
    },
    "JUD": {
        "name": "Jude",
        "testament": NEW_TESTAMENT,
        "chapters": 1,
        "verses": 25
    },
    "REV": {
        "name": "Revelation",
        "testament": NEW_TESTAMENT,
        "chapters": 22,
        "verses": [20, 29, 22, 11, 14, 17, 17, 13, 21, 11, 19, 17, 18, 20, 8, 21, 18, 24, 21, 15, 27, 21]
    }
}


def get_random_book(testament: Optional[str] = None) -> str:
    """
    Get a random book ID from the Bible.
    
    Args:
        testament: Optional filter for "OT" (Old Testament) or "NT" (New Testament)
        
    Returns:
        A random book ID (e.g., "JHN", "GEN")
        
    Raises:
        ValueError: If an invalid testament is specified
    """
    # Validate testament parameter if provided
    if testament and testament not in (OLD_TESTAMENT, NEW_TESTAMENT):
        raise ValueError(f"Invalid testament: {testament}. Must be 'OT', 'NT', or None.")
    
    # Filter books by testament if requested
    if testament:
        books = [book_id for book_id, data in BIBLE_DATA.items() 
                if data["testament"] == testament]
    else:
        books = list(BIBLE_DATA.keys())
    
    # Safety check in case filtering resulted in empty list
    if not books:
        raise ValueError(f"No books found for testament: {testament}")
    
    # Return a random book ID
    return random.choice(books)


def get_random_chapter(book_id: str) -> int:
    """
    Get a random chapter number for the given book.
    
    Args:
        book_id: Book ID (e.g., "JHN", "GEN")
        
    Returns:
        A random chapter number
    """
    if book_id not in BIBLE_DATA:
        raise ValueError(f"Unknown book ID: {book_id}")
    
    # Get the number of chapters in the book
    num_chapters = BIBLE_DATA[book_id]["chapters"]
    
    # Return a random chapter number (1-based)
    return random.randint(1, num_chapters)


def get_random_verse(book_id: str, chapter: int) -> int:
    """
    Get a random verse number for the given book and chapter.
    
    Args:
        book_id: Book ID (e.g., "JHN", "GEN")
        chapter: Chapter number
        
    Returns:
        A random verse number
    """
    if book_id not in BIBLE_DATA:
        raise ValueError(f"Unknown book ID: {book_id}")
    
    book_data = BIBLE_DATA[book_id]
    
    # Handle single-chapter books
    if book_data["chapters"] == 1:
        num_verses = book_data["verses"]
        return random.randint(1, num_verses)
    
    # For multi-chapter books, get the verse count for the specified chapter
    if chapter < 1 or chapter > book_data["chapters"]:
        raise ValueError(f"Chapter {chapter} does not exist in {book_id}")
    
    # Get verse count for the chapter (1-based indexing)
    num_verses = book_data["verses"][chapter - 1]
    
    # Return a random verse number (1-based)
    return random.randint(1, num_verses)


def get_random_reference(testament: Optional[str] = None) -> str:
    """
    Generate a random Bible reference.
    
    Args:
        testament: Optional filter for "OT" (Old Testament) or "NT" (New Testament)
        
    Returns:
        A random reference string (e.g., "John 3:16")
    """
    # Get a random book
    book_id = get_random_book(testament)
    book_data = BIBLE_DATA[book_id]
    book_name = book_data["name"]
    
    # Get a random chapter
    chapter = get_random_chapter(book_id)
    
    # Get a random verse
    verse = get_random_verse(book_id, chapter)
    
    # Format the reference (using the book name, not ID)
    return f"{book_name} {chapter}:{verse}"


def is_valid_reference(book_id: str, chapter: int, verse: Optional[int] = None) -> bool:
    """
    Check if a Bible reference is valid.
    
    Args:
        book_id: Book ID (e.g., "JHN", "GEN")
        chapter: Chapter number
        verse: Optional verse number
        
    Returns:
        True if the reference is valid, False otherwise
    """
    # Check if book exists
    if book_id not in BIBLE_DATA:
        return False
    
    book_data = BIBLE_DATA[book_id]
    
    # Check if chapter exists
    if chapter < 1 or chapter > book_data["chapters"]:
        return False
    
    # If no verse specified, just validate the chapter
    if verse is None:
        return True
    
    # For single-chapter books
    if book_data["chapters"] == 1:
        num_verses = book_data["verses"]
        return 1 <= verse <= num_verses
    
    # For multi-chapter books, check the verse
    num_verses = book_data["verses"][chapter - 1]
    return 1 <= verse <= num_verses


def get_book_testament(book_id: str) -> str:
    """
    Get the testament (OT/NT) for a given book.
    
    Args:
        book_id: Book ID (e.g., "JHN", "GEN")
        
    Returns:
        "OT" or "NT"
    """
    if book_id not in BIBLE_DATA:
        raise ValueError(f"Unknown book ID: {book_id}")
    
    return BIBLE_DATA[book_id]["testament"]


def parse_reference(reference: str) -> Tuple[str, int, Optional[int]]:
    """
    Parse a Bible reference string into its components.
    
    Args:
        reference: Reference string (e.g., "John 3:16", "Genesis 1")
        
    Returns:
        Tuple of (book_id, chapter, verse) where verse may be None
    """
    # This is a simplified parser - a full implementation would handle
    # more complex references like ranges and multiple verses
    
    # First, split by space to separate book name from chapter/verse
    parts = reference.strip().split(" ", 1)
    if len(parts) < 2:
        raise ValueError(f"Invalid reference format: {reference}")
    
    book_name, chapter_verse = parts
    
    # Find the book ID from the name
    book_id = None
    for bid, data in BIBLE_DATA.items():
        if data["name"].lower() == book_name.lower():
            book_id = bid
            break
    
    if not book_id:
        # If not found by name, maybe it's already an ID
        if book_name.upper() in BIBLE_DATA:
            book_id = book_name.upper()
        else:
            raise ValueError(f"Unknown book: {book_name}")
    
    # Parse chapter and verse
    if ":" in chapter_verse:
        # Has both chapter and verse
        chapter_str, verse_str = chapter_verse.split(":", 1)
        try:
            chapter = int(chapter_str)
            verse = int(verse_str)
        except ValueError:
            raise ValueError(f"Invalid chapter or verse number: {chapter_verse}")
    else:
        # Has only chapter
        try:
            chapter = int(chapter_verse)
            verse = None
        except ValueError:
            raise ValueError(f"Invalid chapter number: {chapter_verse}")
    
    # Validate the reference
    if not is_valid_reference(book_id, chapter, verse):
        raise ValueError(f"Reference does not exist: {reference}")
    
    return book_id, chapter, verse
