//! Benchmarks for Micropub property lookups
//!
//! This benchmark demonstrates the performance improvement from using
//! HashSet-based lookups (O(1)) vs Vec-based linear search (O(n)).

use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
use std::collections::HashSet;

// Old implementation - O(n) linear search
fn old_known_properties() -> Vec<String> {
    vec![
        "post-status".into(),
        "status".into(),
        "category".into(),
        "slug".into(),
        "channel".into(),
        "syndicate-to".into(),
        "destination".into(),
        "audience".into(),
        "visibility".into(),
    ]
}

fn old_is_known_property(property: &str) -> bool {
    let known = old_known_properties();
    known.contains(&property.to_string()) || known.contains(&format!("mp-{}", property))
}

// New implementation - O(1) hash lookup
fn new_known_properties() -> HashSet<&'static str> {
    let mut set = HashSet::new();
    set.insert("post-status");
    set.insert("status");
    set.insert("category");
    set.insert("slug");
    set.insert("channel");
    set.insert("syndicate-to");
    set.insert("destination");
    set.insert("audience");
    set.insert("visibility");
    set.insert("mp-post-status");
    set.insert("mp-status");
    set.insert("mp-category");
    set.insert("mp-slug");
    set.insert("mp-channel");
    set.insert("mp-syndicate-to");
    set.insert("mp-destination");
    set.insert("mp-audience");
    set.insert("mp-visibility");
    set
}

fn new_is_known_property(property: &str) -> bool {
    let known = new_known_properties();
    known.contains(property) || known.contains(format!("mp-{}", property).as_str())
}

fn benchmark_property_lookup(c: &mut Criterion) {
    let test_properties = vec![
        "post-status",    // Known property
        "category",       // Known property
        "unknown-prop",   // Unknown property
        "content",        // Unknown property
        "slug",           // Known property
        "custom-field",   // Unknown property
    ];

    let mut group = c.benchmark_group("property_lookup");
    
    for prop in &test_properties {
        group.bench_with_input(
            BenchmarkId::new("old_implementation", prop),
            prop,
            |b, &prop| {
                b.iter(|| old_is_known_property(black_box(prop)))
            },
        );

        group.bench_with_input(
            BenchmarkId::new("new_implementation", prop),
            prop,
            |b, &prop| {
                b.iter(|| new_is_known_property(black_box(prop)))
            },
        );
    }
    
    group.finish();
}

fn benchmark_bulk_filtering(c: &mut Criterion) {
    // Simulate filtering properties from a typical Micropub request
    let properties: Vec<(&str, i32)> = vec![
        ("content", 1),
        ("post-status", 2),
        ("name", 3),
        ("category", 4),
        ("photo", 5),
        ("slug", 6),
        ("published", 7),
        ("visibility", 8),
        ("custom-field", 9),
        ("syndicate-to", 10),
    ];

    c.bench_function("bulk_filter_old", |b| {
        b.iter(|| {
            properties
                .iter()
                .filter(|(key, _)| old_is_known_property(black_box(key)))
                .count()
        })
    });

    c.bench_function("bulk_filter_new", |b| {
        b.iter(|| {
            properties
                .iter()
                .filter(|(key, _)| new_is_known_property(black_box(key)))
                .count()
        })
    });
}

criterion_group!(benches, benchmark_property_lookup, benchmark_bulk_filtering);
criterion_main!(benches);
