use crate::*;
use once_cell::sync::Lazy;
use regex::Regex;
use std::collections::HashMap;

pub static TRIGGER_MAP: Lazy<HashMap<&'static str, &'static Regex>> = Lazy::new(|| {
    let mut m = HashMap::new();

    // Old Testament
    for r in GENESIS.all_refs().into_iter() {
        m.insert(r, &*GENESIS_REGEX);
    }
    for r in EXODUS.all_refs().into_iter() {
        m.insert(r, &*EXODUS_REGEX);
    }
    for r in LEVITICUS.all_refs().into_iter() {
        m.insert(r, &*LEVITICUS_REGEX);
    }
    for r in NUMBERS.all_refs().into_iter() {
        m.insert(r, &*NUMBERS_REGEX);
    }
    for r in DEUTERONOMY.all_refs().into_iter() {
        m.insert(r, &*DEUTERONOMY_REGEX);
    }
    for r in JOSHUA.all_refs().into_iter() {
        m.insert(r, &*JOSHUA_REGEX);
    }
    for r in JUDGES.all_refs().into_iter() {
        m.insert(r, &*JUDGES_REGEX);
    }
    for r in RUTH.all_refs().into_iter() {
        m.insert(r, &*RUTH_REGEX);
    }
    for r in FIRST_SAMUEL.all_refs().into_iter() {
        m.insert(r, &*FIRST_SAMUEL_REGEX);
    }
    for r in SECOND_SAMUEL.all_refs().into_iter() {
        m.insert(r, &*SECOND_SAMUEL_REGEX);
    }
    for r in FIRST_KINGS.all_refs().into_iter() {
        m.insert(r, &*FIRST_KINGS_REGEX);
    }
    for r in SECOND_KINGS.all_refs().into_iter() {
        m.insert(r, &*SECOND_KINGS_REGEX);
    }
    for r in FIRST_CHRONICLES.all_refs().into_iter() {
        m.insert(r, &*FIRST_CHRONICLES_REGEX);
    }
    for r in SECOND_CHRONICLES.all_refs().into_iter() {
        m.insert(r, &*SECOND_CHRONICLES_REGEX);
    }
    for r in EZRA.all_refs().into_iter() {
        m.insert(r, &*EZRA_REGEX);
    }
    for r in NEHEMIAH.all_refs().into_iter() {
        m.insert(r, &*NEHEMIAH_REGEX);
    }
    for r in ESTHER.all_refs().into_iter() {
        m.insert(r, &*ESTHER_REGEX);
    }
    for r in JOB.all_refs().into_iter() {
        m.insert(r, &*JOB_REGEX);
    }
    for r in PSALMS.all_refs().into_iter() {
        m.insert(r, &*PSALMS_REGEX);
    }
    for r in PROVERBS.all_refs().into_iter() {
        m.insert(r, &*PROVERBS_REGEX);
    }
    for r in ECCLESIASTES.all_refs().into_iter() {
        m.insert(r, &*ECCLESIASTES_REGEX);
    }
    for r in SONG_OF_SONGS.all_refs().into_iter() {
        m.insert(r, &*SONG_OF_SONGS_REGEX);
    }
    for r in ISAIAH.all_refs().into_iter() {
        m.insert(r, &*ISAIAH_REGEX);
    }
    for r in JEREMIAH.all_refs().into_iter() {
        m.insert(r, &*JEREMIAH_REGEX);
    }
    for r in LAMENTATIONS.all_refs().into_iter() {
        m.insert(r, &*LAMENTATIONS_REGEX);
    }
    for r in EZEKIEL.all_refs().into_iter() {
        m.insert(r, &*EZEKIEL_REGEX);
    }
    for r in DANIEL.all_refs().into_iter() {
        m.insert(r, &*DANIEL_REGEX);
    }
    for r in HOSEA.all_refs().into_iter() {
        m.insert(r, &*HOSEA_REGEX);
    }
    for r in JOEL.all_refs().into_iter() {
        m.insert(r, &*JOEL_REGEX);
    }
    for r in AMOS.all_refs().into_iter() {
        m.insert(r, &*AMOS_REGEX);
    }
    for r in OBADIAH.all_refs().into_iter() {
        m.insert(r, &*OBADIAH_REGEX);
    }
    for r in JONAH.all_refs().into_iter() {
        m.insert(r, &*JONAH_REGEX);
    }
    for r in MICAH.all_refs().into_iter() {
        m.insert(r, &*MICAH_REGEX);
    }
    for r in NAHUM.all_refs().into_iter() {
        m.insert(r, &*NAHUM_REGEX);
    }
    for r in HABAKKUK.all_refs().into_iter() {
        m.insert(r, &*HABAKKUK_REGEX);
    }
    for r in ZEPHANIAH.all_refs().into_iter() {
        m.insert(r, &*ZEPHANIAH_REGEX);
    }
    for r in HAGGAI.all_refs().into_iter() {
        m.insert(r, &*HAGGAI_REGEX);
    }
    for r in ZECHARIAH.all_refs().into_iter() {
        m.insert(r, &*ZECHARIAH_REGEX);
    }
    for r in MALACHI.all_refs().into_iter() {
        m.insert(r, &*MALACHI_REGEX);
    }

    // New Testament
    for r in MATTHEW.all_refs().into_iter() {
        m.insert(r, &*MATTHEW_REGEX);
    }
    for r in MARK.all_refs().into_iter() {
        m.insert(r, &*MARK_REGEX);
    }
    for r in LUKE.all_refs().into_iter() {
        m.insert(r, &*LUKE_REGEX);
    }
    for r in JOHN.all_refs().into_iter() {
        m.insert(r, &*JOHN_REGEX);
    }
    for r in ACTS.all_refs().into_iter() {
        m.insert(r, &*ACTS_REGEX);
    }
    for r in ROMANS.all_refs().into_iter() {
        m.insert(r, &*ROMANS_REGEX);
    }
    for r in FIRST_CORINTHIANS.all_refs().into_iter() {
        m.insert(r, &*FIRST_CORINTHIANS_REGEX);
    }
    for r in SECOND_CORINTHIANS.all_refs().into_iter() {
        m.insert(r, &*SECOND_CORINTHIANS_REGEX);
    }
    for r in GALATIANS.all_refs().into_iter() {
        m.insert(r, &*GALATIANS_REGEX);
    }
    for r in EPHESIANS.all_refs().into_iter() {
        m.insert(r, &*EPHESIANS_REGEX);
    }
    for r in PHILIPPIANS.all_refs().into_iter() {
        m.insert(r, &*PHILIPPIANS_REGEX);
    }
    for r in COLOSSIANS.all_refs().into_iter() {
        m.insert(r, &*COLOSSIANS_REGEX);
    }
    for r in FIRST_THESSALONIANS.all_refs().into_iter() {
        m.insert(r, &*FIRST_THESSALONIANS_REGEX);
    }
    for r in SECOND_THESSALONIANS.all_refs().into_iter() {
        m.insert(r, &*SECOND_THESSALONIANS_REGEX);
    }
    for r in FIRST_TIMOTHY.all_refs().into_iter() {
        m.insert(r, &*FIRST_TIMOTHY_REGEX);
    }
    for r in SECOND_TIMOTHY.all_refs().into_iter() {
        m.insert(r, &*SECOND_TIMOTHY_REGEX);
    }
    for r in TITUS.all_refs().into_iter() {
        m.insert(r, &*TITUS_REGEX);
    }
    for r in PHILEMON.all_refs().into_iter() {
        m.insert(r, &*PHILEMON_REGEX);
    }
    for r in HEBREWS.all_refs().into_iter() {
        m.insert(r, &*HEBREWS_REGEX);
    }
    for r in JAMES.all_refs().into_iter() {
        m.insert(r, &*JAMES_REGEX);
    }
    for r in FIRST_PETER.all_refs().into_iter() {
        m.insert(r, &*FIRST_PETER_REGEX);
    }
    for r in SECOND_PETER.all_refs().into_iter() {
        m.insert(r, &*SECOND_PETER_REGEX);
    }
    for r in FIRST_JOHN.all_refs().into_iter() {
        m.insert(r, &*FIRST_JOHN_REGEX);
    }
    for r in SECOND_JOHN.all_refs().into_iter() {
        m.insert(r, &*SECOND_JOHN_REGEX);
    }
    for r in THIRD_JOHN.all_refs().into_iter() {
        m.insert(r, &*THIRD_JOHN_REGEX);
    }
    for r in JUDE.all_refs().into_iter() {
        m.insert(r, &*JUDE_REGEX);
    }
    for r in REVELATION.all_refs().into_iter() {
        m.insert(r, &*REVELATION_REGEX);
    }

    m
});

fn append_regex(base: &str) -> Regex {
    let regex_str = format!(
        r"{}(?P<book>{base}){}{}",
        BEGINNING_PATTERN, CHAP_VERSE_PATTERN, ENDING_PATTERN
    );
    Regex::new(regex_str.as_str()).unwrap()
}

fn append_relaxed_regex(base: &str) -> Regex {
    let regex_str = format!(
        r"{}(?P<book>{base}){}",
        RELAXED_BEGINNING_PATTERN, RELAXED_CHAP_VERSE_PATTERN
    );
    Regex::new(regex_str.as_str()).unwrap()
}

const BEGINNING_PATTERN: &str = r"(?xi)\b";
const CHAP_VERSE_PATTERN: &str = r"(\s+(?P<chapter>\d{1,3})((:|\s)(?P<verse>\d{1,3})(\s*(?:--|[\-–—])\s*(?P<end_verse>\d{1,3}))?)?)?";
const ENDING_PATTERN: &str = r"\b";

// Relaxed patterns allow optional space between book and chapter
// Note: We can't use look-around in Rust regex, so boundary checking is done in code
const RELAXED_BEGINNING_PATTERN: &str = r"(?xi)";
const RELAXED_CHAP_VERSE_PATTERN: &str = r"(\s*(?P<chapter>\d{1,3})([:.\s](?P<verse>\d{1,3})(\s*(?:--|[\-–—])\s*(?P<end_verse>\d{1,3}))?)?)?";
// Boundary validation is handled in contains_possible_references_with_options

/// Get a relaxed regex for a book (allows no space between book and chapter)
pub fn get_relaxed_regex(book: &crate::book::Book) -> Option<&'static Regex> {
    RELAXED_TRIGGER_MAP.get(book.title).copied()
}

pub static RELAXED_TRIGGER_MAP: Lazy<HashMap<&'static str, &'static Regex>> = Lazy::new(|| {
    let mut m = HashMap::new();

    // Old Testament
    m.insert("Genesis", &*GENESIS_RELAXED_REGEX);
    m.insert("Exodus", &*EXODUS_RELAXED_REGEX);
    m.insert("Leviticus", &*LEVITICUS_RELAXED_REGEX);
    m.insert("Numbers", &*NUMBERS_RELAXED_REGEX);
    m.insert("Deuteronomy", &*DEUTERONOMY_RELAXED_REGEX);
    m.insert("Joshua", &*JOSHUA_RELAXED_REGEX);
    m.insert("Judges", &*JUDGES_RELAXED_REGEX);
    m.insert("Ruth", &*RUTH_RELAXED_REGEX);
    m.insert("1 Samuel", &*FIRST_SAMUEL_RELAXED_REGEX);
    m.insert("2 Samuel", &*SECOND_SAMUEL_RELAXED_REGEX);
    m.insert("1 Kings", &*FIRST_KINGS_RELAXED_REGEX);
    m.insert("2 Kings", &*SECOND_KINGS_RELAXED_REGEX);
    m.insert("1 Chronicles", &*FIRST_CHRONICLES_RELAXED_REGEX);
    m.insert("2 Chronicles", &*SECOND_CHRONICLES_RELAXED_REGEX);
    m.insert("Ezra", &*EZRA_RELAXED_REGEX);
    m.insert("Nehemiah", &*NEHEMIAH_RELAXED_REGEX);
    m.insert("Esther", &*ESTHER_RELAXED_REGEX);
    m.insert("Job", &*JOB_RELAXED_REGEX);
    m.insert("Psalms", &*PSALMS_RELAXED_REGEX);
    m.insert("Proverbs", &*PROVERBS_RELAXED_REGEX);
    m.insert("Ecclesiastes", &*ECCLESIASTES_RELAXED_REGEX);
    m.insert("Song of Songs", &*SONG_OF_SONGS_RELAXED_REGEX);
    m.insert("Isaiah", &*ISAIAH_RELAXED_REGEX);
    m.insert("Jeremiah", &*JEREMIAH_RELAXED_REGEX);
    m.insert("Lamentations", &*LAMENTATIONS_RELAXED_REGEX);
    m.insert("Ezekiel", &*EZEKIEL_RELAXED_REGEX);
    m.insert("Daniel", &*DANIEL_RELAXED_REGEX);
    m.insert("Hosea", &*HOSEA_RELAXED_REGEX);
    m.insert("Joel", &*JOEL_RELAXED_REGEX);
    m.insert("Amos", &*AMOS_RELAXED_REGEX);
    m.insert("Obadiah", &*OBADIAH_RELAXED_REGEX);
    m.insert("Jonah", &*JONAH_RELAXED_REGEX);
    m.insert("Micah", &*MICAH_RELAXED_REGEX);
    m.insert("Nahum", &*NAHUM_RELAXED_REGEX);
    m.insert("Habakkuk", &*HABAKKUK_RELAXED_REGEX);
    m.insert("Zephaniah", &*ZEPHANIAH_RELAXED_REGEX);
    m.insert("Haggai", &*HAGGAI_RELAXED_REGEX);
    m.insert("Zechariah", &*ZECHARIAH_RELAXED_REGEX);
    m.insert("Malachi", &*MALACHI_RELAXED_REGEX);

    // New Testament
    m.insert("Matthew", &*MATTHEW_RELAXED_REGEX);
    m.insert("Mark", &*MARK_RELAXED_REGEX);
    m.insert("Luke", &*LUKE_RELAXED_REGEX);
    m.insert("John", &*JOHN_RELAXED_REGEX);
    m.insert("Acts", &*ACTS_RELAXED_REGEX);
    m.insert("Romans", &*ROMANS_RELAXED_REGEX);
    m.insert("1 Corinthians", &*FIRST_CORINTHIANS_RELAXED_REGEX);
    m.insert("2 Corinthians", &*SECOND_CORINTHIANS_RELAXED_REGEX);
    m.insert("Galatians", &*GALATIANS_RELAXED_REGEX);
    m.insert("Ephesians", &*EPHESIANS_RELAXED_REGEX);
    m.insert("Philippians", &*PHILIPPIANS_RELAXED_REGEX);
    m.insert("Colossians", &*COLOSSIANS_RELAXED_REGEX);
    m.insert("1 Thessalonians", &*FIRST_THESSALONIANS_RELAXED_REGEX);
    m.insert("2 Thessalonians", &*SECOND_THESSALONIANS_RELAXED_REGEX);
    m.insert("1 Timothy", &*FIRST_TIMOTHY_RELAXED_REGEX);
    m.insert("2 Timothy", &*SECOND_TIMOTHY_RELAXED_REGEX);
    m.insert("Titus", &*TITUS_RELAXED_REGEX);
    m.insert("Philemon", &*PHILEMON_RELAXED_REGEX);
    m.insert("Hebrews", &*HEBREWS_RELAXED_REGEX);
    m.insert("James", &*JAMES_RELAXED_REGEX);
    m.insert("1 Peter", &*FIRST_PETER_RELAXED_REGEX);
    m.insert("2 Peter", &*SECOND_PETER_RELAXED_REGEX);
    m.insert("1 John", &*FIRST_JOHN_RELAXED_REGEX);
    m.insert("2 John", &*SECOND_JOHN_RELAXED_REGEX);
    m.insert("3 John", &*THIRD_JOHN_RELAXED_REGEX);
    m.insert("Jude", &*JUDE_RELAXED_REGEX);
    m.insert("Revelation", &*REVELATION_RELAXED_REGEX);

    m
});

// ==================== OLD TESTAMENT ====================

static GENESIS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("gen(?:esis)?"));

static EXODUS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("ex(?:od(?:us)?)?"));

static LEVITICUS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("lev(?:iticus)?"));

static NUMBERS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("num(?:bers)?"));

static DEUTERONOMY_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("de?ut(?:eronomy)?"));

static JOSHUA_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("josh(?:ua)?"));

static JUDGES_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("judg(?:es)?"));

static RUTH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("ruth"));

static FIRST_SAMUEL_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(1(st)?|first|I)\s*sam(?:uel)?"));

static SECOND_SAMUEL_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(2(nd)?|second|II)\s*sam(?:uel)?"));

static FIRST_KINGS_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(1(st)?|first|I)\s*k(?:in)?gs?"));

static SECOND_KINGS_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(2(nd)?|second|II)\s*k(?:in)?gs?"));

static FIRST_CHRONICLES_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(1(st)?|first|I)\s*chr(?:on(?:icles)?)?"));

static SECOND_CHRONICLES_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(2(nd)?|second|II)\s*chr(?:on(?:icles)?)?"));

static EZRA_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("ezra?"));

static NEHEMIAH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("neh(?:emiah)?"));

static ESTHER_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("esth(?:er)?"));

static JOB_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("job"));

static PSALMS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("ps(?:a)?(?:lms?)?"));

static PROVERBS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("pro(?:v(?:erbs)?)?"));

static ECCLESIASTES_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("ecc(?:l(?:es(?:iastes)?)?)?"));

static SONG_OF_SONGS_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(song(\s+of\s+(songs?|solomon))?|canticles?|sos|ss)"));

static ISAIAH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("isa(?:iah)?"));

static JEREMIAH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("jer(?:emiah)?"));

static LAMENTATIONS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("lam(?:entations)?"));

static EZEKIEL_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("ezek(?:iel)?"));

static DANIEL_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("dan(?:iel)?"));

static HOSEA_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("hos(?:ea)?"));

static JOEL_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("joel"));

static AMOS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("amos"));

static OBADIAH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("obad(?:iah)?"));

static JONAH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("jonah?"));

static MICAH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("mic(?:ah)?"));

static NAHUM_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("nah(?:um)?"));

static HABAKKUK_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("hab(?:akkuk)?"));

static ZEPHANIAH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("zeph(?:aniah)?"));

static HAGGAI_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("hag(?:gai)?"));

static ZECHARIAH_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("zech(?:ariah)?"));

static MALACHI_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("mal(?:achi)?"));

// ==================== NEW TESTAMENT ====================

static MATTHEW_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(the\s+gospel\s+of\s+)?matt(?:hew)?|mt"));

static MARK_REGEX: Lazy<Regex> = Lazy::new(|| append_regex(r"(the\s+gospel\s+of\s+)?m(?:ar)?k"));

static LUKE_REGEX: Lazy<Regex> = Lazy::new(|| append_regex(r"(the\s+gospel\s+of\s+)?lu?ke?"));

static JOHN_REGEX: Lazy<Regex> = Lazy::new(|| append_regex(r"(the\s+gospel\s+of\s+)?jo?h?n"));

static ACTS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex(r"acts?(\s+of\s+(the\s+)?apostles)?"));

static ROMANS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("rom(?:ans)?"));

static FIRST_CORINTHIANS_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(1(st)?|first|I)\s*cor(?:inthians)?"));

static SECOND_CORINTHIANS_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(2(nd)?|second|II)\s*cor(?:inthians)?"));

static GALATIANS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("gal(?:atians)?"));

static EPHESIANS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("eph(?:esians)?"));

static PHILIPPIANS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("phil(?:ippians)?"));

static COLOSSIANS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("col(?:ossians)?"));

static FIRST_THESSALONIANS_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(1(st)?|first|I)\s*thess(?:alonians)?"));

static SECOND_THESSALONIANS_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(2(nd)?|second|II)\s*thess(?:alonians)?"));

static FIRST_TIMOTHY_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(1(st)?|first|I)\s*tim(?:othy)?"));

static SECOND_TIMOTHY_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(2(nd)?|second|II)\s*tim(?:othy)?"));

static TITUS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("tit(?:us)?"));

static PHILEMON_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("philem(?:on)?|phlm"));

static HEBREWS_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("heb(?:rews)?"));

static JAMES_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("ja(?:me)?s"));

static FIRST_PETER_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(1(st)?|first|I)\s*pet(?:er)?"));

static SECOND_PETER_REGEX: Lazy<Regex> =
    Lazy::new(|| append_regex(r"(2(nd)?|second|II)\s*pet(?:er)?"));

static FIRST_JOHN_REGEX: Lazy<Regex> = Lazy::new(|| append_regex(r"(1(st)?|first|I)\s*jo?h?n"));

static SECOND_JOHN_REGEX: Lazy<Regex> = Lazy::new(|| append_regex(r"(2(nd)?|second|II)\s*jo?h?n"));

static THIRD_JOHN_REGEX: Lazy<Regex> = Lazy::new(|| append_regex(r"(3(rd)?|third|III)\s*jo?h?n"));

static JUDE_REGEX: Lazy<Regex> = Lazy::new(|| append_regex("jude?"));

static REVELATION_REGEX: Lazy<Regex> = Lazy::new(|| append_regex(r"rev(?:elation)?|apocalypse"));

// ==================== RELAXED REGEXES (for optimistic parsing) ====================

// Old Testament - Relaxed
static GENESIS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("gen(?:esis)?"));
static EXODUS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("ex(?:od(?:us)?)?"));
static LEVITICUS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("lev(?:iticus)?"));
static NUMBERS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("num(?:bers)?"));
static DEUTERONOMY_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex("de?ut(?:eronomy)?"));
static JOSHUA_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("josh(?:ua)?"));
static JUDGES_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("judg(?:es)?"));
static RUTH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("ruth"));
static FIRST_SAMUEL_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(1(st)?|first|I)\s*sam(?:uel)?"));
static SECOND_SAMUEL_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(2(nd)?|second|II)\s*sam(?:uel)?"));
static FIRST_KINGS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(1(st)?|first|I)\s*k(?:in)?gs?"));
static SECOND_KINGS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(2(nd)?|second|II)\s*k(?:in)?gs?"));
static FIRST_CHRONICLES_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(1(st)?|first|I)\s*chr(?:on(?:icles)?)?"));
static SECOND_CHRONICLES_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(2(nd)?|second|II)\s*chr(?:on(?:icles)?)?"));
static EZRA_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("ezra?"));
static NEHEMIAH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("neh(?:emiah)?"));
static ESTHER_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("esth(?:er)?"));
static JOB_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("job"));
static PSALMS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("ps(?:a)?(?:lms?)?"));
static PROVERBS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex("pro(?:v(?:erbs)?)?"));
static ECCLESIASTES_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex("ecc(?:l(?:es(?:iastes)?)?)?"));
static SONG_OF_SONGS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(song(\s+of\s+(songs?|solomon))?|canticles?|sos|ss)"));
static ISAIAH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("isa(?:iah)?"));
static JEREMIAH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("jer(?:emiah)?"));
static LAMENTATIONS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex("lam(?:entations)?"));
static EZEKIEL_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("ezek(?:iel)?"));
static DANIEL_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("dan(?:iel)?"));
static HOSEA_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("hos(?:ea)?"));
static JOEL_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("joel"));
static AMOS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("amos"));
static OBADIAH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("obad(?:iah)?"));
static JONAH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("jonah?"));
static MICAH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("mic(?:ah)?"));
static NAHUM_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("nah(?:um)?"));
static HABAKKUK_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("hab(?:akkuk)?"));
static ZEPHANIAH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("zeph(?:aniah)?"));
static HAGGAI_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("hag(?:gai)?"));
static ZECHARIAH_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("zech(?:ariah)?"));
static MALACHI_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("mal(?:achi)?"));

// New Testament - Relaxed
static MATTHEW_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(the\s+gospel\s+of\s+)?matt(?:hew)?|mt"));
static MARK_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(the\s+gospel\s+of\s+)?m(?:ar)?k"));
static LUKE_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(the\s+gospel\s+of\s+)?lu?ke?"));
static JOHN_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(the\s+gospel\s+of\s+)?jo?h?n"));
static ACTS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"acts?(\s+of\s+(the\s+)?apostles)?"));
static ROMANS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("rom(?:ans)?"));
static FIRST_CORINTHIANS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(1(st)?|first|I)\s*cor(?:inthians)?"));
static SECOND_CORINTHIANS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(2(nd)?|second|II)\s*cor(?:inthians)?"));
static GALATIANS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("gal(?:atians)?"));
static EPHESIANS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("eph(?:esians)?"));
static PHILIPPIANS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex("phil(?:ippians)?"));
static COLOSSIANS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex("col(?:ossians)?"));
static FIRST_THESSALONIANS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(1(st)?|first|I)\s*thess(?:alonians)?"));
static SECOND_THESSALONIANS_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(2(nd)?|second|II)\s*thess(?:alonians)?"));
static FIRST_TIMOTHY_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(1(st)?|first|I)\s*tim(?:othy)?"));
static SECOND_TIMOTHY_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(2(nd)?|second|II)\s*tim(?:othy)?"));
static TITUS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("tit(?:us)?"));
static PHILEMON_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex("philem(?:on)?|phlm"));
static HEBREWS_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("heb(?:rews)?"));
static JAMES_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("ja(?:me)?s"));
static FIRST_PETER_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(1(st)?|first|I)\s*pet(?:er)?"));
static SECOND_PETER_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(2(nd)?|second|II)\s*pet(?:er)?"));
static FIRST_JOHN_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(1(st)?|first|I)\s*jo?h?n"));
static SECOND_JOHN_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(2(nd)?|second|II)\s*jo?h?n"));
static THIRD_JOHN_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"(3(rd)?|third|III)\s*jo?h?n"));
static JUDE_RELAXED_REGEX: Lazy<Regex> = Lazy::new(|| append_relaxed_regex("jude?"));
static REVELATION_RELAXED_REGEX: Lazy<Regex> =
    Lazy::new(|| append_relaxed_regex(r"rev(?:elation)?|apocalypse"));
