use biblicist::{
    ParseOptions, Text, parse_reference, parse_reference_with_offsets, parse_reference_with_options,
};
use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main};

// ==================== INPUTS ====================

const SHORT_REFERENCE: &str = "John 3:16";
const SHORT_REFERENCE_ABBREV: &str = "Jn 3:16";
const VERSE_RANGE: &str = "Romans 8:28-39";
const NUMBERED_BOOK: &str = "2 Timothy 2:15";
const FULL_CHAPTER: &str = "Genesis 1";
const BOOK_ONLY: &str = "Revelation";

const MIXED_TEXT_SHORT: &str =
    "In the beginning (Gen 1:1), the Word existed (Jhn 1:1). Guard this truth (2 Tim 2:15).";

const MIXED_TEXT_LONG: &str = r#"
    The Bible begins with Genesis 1:1 saying "In the beginning God created the heavens and the earth."
    Exodus 20:3 gives us the first commandment. Leviticus 19:18 teaches us to love our neighbor.
    Numbers 6:24 contains the priestly blessing. Deuteronomy 6:4 is the Shema.
    Joshua 1:9 encourages us to be strong and courageous. Judges 6:12 calls Gideon a mighty warrior.
    Ruth 1:16 shows loyalty. 1 Samuel 3:10 records Samuel's response to God.
    2 Samuel 7:12 contains the Davidic covenant. 1 Kings 3:9 shows Solomon's wisdom.
    2 Kings 2:11 describes Elijah's ascension. 1 Chronicles 16:34 praises God's goodness.
    2 Chronicles 7:14 calls for repentance. Ezra 7:10 describes Ezra's devotion.
    Nehemiah 8:10 reminds us that joy is our strength. Esther 4:14 speaks of purpose.
    Job 1:21 shows acceptance of God's will. Psalms 23:1 declares the Lord as shepherd.
    Proverbs 3:5 calls us to trust in the Lord. Ecclesiastes 3:1 speaks of seasons.
    Song of Songs 2:4 describes God's love. Isaiah 53:5 prophesies the Messiah's suffering.
    Jeremiah 29:11 gives hope for the future. Lamentations 3:22 speaks of God's mercies.
    Ezekiel 37:1 describes the valley of dry bones. Daniel 3:17 shows faith in trial.
    Hosea 6:6 teaches about mercy over sacrifice. Joel 2:28 prophesies the Spirit's outpouring.
    Amos 5:24 calls for justice. Obadiah 1:4 warns the proud. Jonah 2:9 declares salvation.
    Micah 6:8 defines what God requires. Nahum 1:7 declares God's goodness.
    Habakkuk 2:4 says the righteous live by faith. Zephaniah 3:17 describes God's joy.
    Haggai 2:9 promises glory. Zechariah 9:9 prophesies the coming king.
    Malachi 3:10 challenges us to tithe. Matthew 5:3 begins the Beatitudes.
    Mark 1:1 introduces the Gospel. Luke 2:10 announces good news of great joy.
    John 3:16 is the most famous verse. Acts 2:38 calls for repentance and baptism.
    Romans 8:28 assures us all things work for good. 1 Corinthians 13:4 defines love.
    2 Corinthians 5:17 speaks of new creation. Galatians 5:22 lists the fruit of the Spirit.
    Ephesians 2:8 explains salvation by grace. Philippians 4:13 declares strength in Christ.
    Colossians 3:23 teaches us to work heartily. 1 Thessalonians 5:16 calls us to rejoice.
    2 Thessalonians 3:3 assures God's faithfulness. 1 Timothy 6:12 urges fighting the good fight.
    2 Timothy 2:15 calls for rightly handling the word. Titus 3:5 speaks of salvation.
    Philemon 1:6 speaks of sharing faith. Hebrews 11:1 defines faith.
    James 1:2 teaches about trials. 1 Peter 5:7 tells us to cast our cares.
    2 Peter 1:3 speaks of divine power. 1 John 4:8 declares God is love.
    2 John 1:6 defines walking in love. 3 John 1:4 expresses joy in truth.
    Jude 1:3 urges contending for the faith. Revelation 21:4 promises no more tears.
"#;

// Search bar style inputs (optimistic use cases)
const SEARCH_COMPACT: &str = "jn3:16";
const SEARCH_TYPO: &str = "Genisis 1:1";
const SEARCH_BARE_REF: &str = "3:16";
const SEARCH_MIXED: &str = "good shepherd jn10:11";

// ==================== BENCHMARKS ====================

fn bench_parse_reference(c: &mut Criterion) {
    let mut group = c.benchmark_group("parse_reference");

    for (name, input) in [
        ("short", SHORT_REFERENCE),
        ("short_abbrev", SHORT_REFERENCE_ABBREV),
        ("verse_range", VERSE_RANGE),
        ("numbered_book", NUMBERED_BOOK),
        ("full_chapter", FULL_CHAPTER),
        ("book_only", BOOK_ONLY),
    ] {
        group.bench_with_input(BenchmarkId::new("strict", name), input, |b, i| {
            b.iter(|| parse_reference(black_box(i)))
        });
    }

    group.finish();
}

fn bench_parse_reference_mixed_text(c: &mut Criterion) {
    let mut group = c.benchmark_group("parse_reference/mixed_text");

    group.bench_function("short", |b| {
        b.iter(|| parse_reference(black_box(MIXED_TEXT_SHORT)))
    });

    group.bench_function("long_66_books", |b| {
        b.iter(|| parse_reference(black_box(MIXED_TEXT_LONG)))
    });

    let large_text = MIXED_TEXT_LONG.repeat(100);
    group.bench_function("large_66books_x100", |b| {
        b.iter(|| parse_reference(black_box(&large_text)))
    });

    group.finish();
}

fn bench_parse_reference_with_offsets(c: &mut Criterion) {
    let mut group = c.benchmark_group("parse_reference_with_offsets");

    group.bench_function("short", |b| {
        b.iter(|| parse_reference_with_offsets(black_box(SHORT_REFERENCE)))
    });

    group.bench_function("mixed_text_long", |b| {
        b.iter(|| parse_reference_with_offsets(black_box(MIXED_TEXT_LONG)))
    });

    group.finish();
}

fn bench_text_parse(c: &mut Criterion) {
    let mut group = c.benchmark_group("Text::parse");

    group.bench_function("short", |b| {
        b.iter(|| Text::parse(black_box(SHORT_REFERENCE)))
    });

    group.bench_function("mixed_text_long", |b| {
        b.iter(|| Text::parse(black_box(MIXED_TEXT_LONG)))
    });

    group.finish();
}

fn bench_optimistic_parsing(c: &mut Criterion) {
    let mut group = c.benchmark_group("parse_reference/optimistic");

    let opts_relaxed = ParseOptions::new().relaxed_boundaries(true);
    let opts_fuzzy = ParseOptions::new().fuzzy_matching(true);
    let opts_bare = ParseOptions::new().bare_references(true);
    let opts_full = ParseOptions::optimistic();

    group.bench_function("relaxed_compact_ref", |b| {
        b.iter(|| parse_reference_with_options(black_box(SEARCH_COMPACT), &opts_relaxed))
    });

    group.bench_function("fuzzy_typo", |b| {
        b.iter(|| parse_reference_with_options(black_box(SEARCH_TYPO), &opts_fuzzy))
    });

    group.bench_function("bare_ref", |b| {
        b.iter(|| parse_reference_with_options(black_box(SEARCH_BARE_REF), &opts_bare))
    });

    group.bench_function("full_optimistic_compact", |b| {
        b.iter(|| parse_reference_with_options(black_box(SEARCH_COMPACT), &opts_full))
    });

    group.bench_function("full_optimistic_typo", |b| {
        b.iter(|| parse_reference_with_options(black_box(SEARCH_TYPO), &opts_full))
    });

    group.bench_function("full_optimistic_mixed", |b| {
        b.iter(|| parse_reference_with_options(black_box(SEARCH_MIXED), &opts_full))
    });

    group.bench_function("full_optimistic_mixed_text_long", |b| {
        b.iter(|| parse_reference_with_options(black_box(MIXED_TEXT_LONG), &opts_full))
    });

    group.finish();
}

fn bench_optimistic_vs_strict(c: &mut Criterion) {
    let mut group = c.benchmark_group("optimistic_vs_strict");

    let opts_optimistic = ParseOptions::optimistic();

    group.bench_with_input(
        BenchmarkId::new("strict", "long_text"),
        MIXED_TEXT_LONG,
        |b, i| b.iter(|| parse_reference(black_box(i))),
    );

    group.bench_with_input(
        BenchmarkId::new("optimistic", "long_text"),
        MIXED_TEXT_LONG,
        |b, i| b.iter(|| parse_reference_with_options(black_box(i), &opts_optimistic)),
    );

    group.finish();
}

criterion_group!(
    benches,
    bench_parse_reference,
    bench_parse_reference_mixed_text,
    bench_parse_reference_with_offsets,
    bench_text_parse,
    bench_optimistic_parsing,
    bench_optimistic_vs_strict,
);
criterion_main!(benches);
