use std::sync::OnceLock;

use criterion::{Criterion, black_box, criterion_group, criterion_main};
use icons::leptos::parser::{SvgElement, parse_svg_elements};

// Simulate the old approach (parsing every time)
fn parse_every_time(svg_content: &str) -> Vec<SvgElement> {
    parse_svg_elements(svg_content)
}

// Simulate the new cached approach
static CACHE: OnceLock<Vec<SvgElement>> = OnceLock::new();
fn parse_with_cache(svg_content: &str) -> &Vec<SvgElement> {
    CACHE.get_or_init(|| parse_svg_elements(svg_content))
}

// Sample SVG content (similar to actual icons)
const SAMPLE_SVG: &str = r#"<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
<circle cx="12" cy="12" r="3"/>
<rect x="9" y="9" width="6" height="6"/>"#;

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

    // Benchmark parsing every time (old approach)
    group.bench_function("parse_every_render", |b| {
        b.iter(|| {
            let elements = parse_every_time(black_box(SAMPLE_SVG));
            black_box(elements)
        })
    });

    // Benchmark parsing + caching (simulates first call)
    group.bench_function("parse_and_cache", |b| {
        b.iter(|| {
            let cache = OnceLock::new();
            let elements = cache.get_or_init(|| parse_svg_elements(black_box(SAMPLE_SVG)));
            black_box(elements.len()) // Just benchmark access, not the reference
        })
    });

    // Benchmark cached approach - subsequent calls (cache hits)
    group.bench_function("parse_cached_subsequent_calls", |b| {
        // Prime the cache
        parse_with_cache(SAMPLE_SVG);

        b.iter(|| {
            let elements = parse_with_cache(black_box(SAMPLE_SVG));
            black_box(elements.len())
        })
    });

    group.finish();
}

fn benchmark_complex_svg(c: &mut Criterion) {
    // More complex SVG similar to real icons
    const COMPLEX_SVG: &str = r#"<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/>
<line x1="12" y1="22.08" x2="12" y2="12"/>
<circle cx="12" cy="8" r="2"/>
<path d="m8.5 14.5 2-2 4 4"/>
<rect x="4" y="4" width="16" height="16" rx="2"/>"#;

    static COMPLEX_CACHE: OnceLock<Vec<SvgElement>> = OnceLock::new();

    let mut group = c.benchmark_group("complex_icon_parsing");

    group.bench_function("complex_parse_every_render", |b| {
        b.iter(|| {
            let elements = parse_every_time(black_box(COMPLEX_SVG));
            black_box(elements)
        })
    });

    group.bench_function("complex_parse_cached", |b| {
        // Prime the cache
        COMPLEX_CACHE.get_or_init(|| parse_svg_elements(COMPLEX_SVG));

        b.iter(|| {
            let elements = COMPLEX_CACHE.get().unwrap();
            black_box(elements.len())
        })
    });

    group.finish();
}

criterion_group!(benches, benchmark_parsing_performance, benchmark_complex_svg);
criterion_main!(benches);
