//! Micro-benchmark test for zero-length interval parsing performance.
//!
//! Verifies that bedtools-compatible mode has negligible (<1%) overhead
//! compared to strict mode during parsing.

use grit_genomics::bed::FastBedParser;
use grit_genomics::config;
use serial_test::serial;
use std::time::Instant;

/// Reset config to default state
fn reset_config() {
    config::set_bedtools_compatible(false);
}

/// Generate test BED lines for benchmarking.
/// Mix of regular intervals and zero-length intervals.
fn generate_test_lines(count: usize) -> Vec<Vec<u8>> {
    let mut lines = Vec::with_capacity(count);
    for i in 0..count {
        let start = (i * 100) as u64;
        // Every 10th interval is zero-length
        let end = if i % 10 == 0 { start } else { start + 100 };
        lines.push(format!("chr1\t{}\t{}\tname{}\t100\t+", start, end, i).into_bytes());
    }
    lines
}

/// Benchmark parsing in a specific mode, return nanoseconds per parse.
fn benchmark_parsing(lines: &[Vec<u8>], bedtools_compatible: bool) -> f64 {
    config::set_bedtools_compatible(bedtools_compatible);
    let parser = FastBedParser::new();

    // Warm up
    for line in lines.iter().take(100) {
        let _ = parser.parse_interval(line);
    }

    // Benchmark
    let iterations = 10;
    let mut total_ns = 0u128;

    for _ in 0..iterations {
        let start = Instant::now();
        for line in lines {
            let _ = parser.parse_interval(line);
        }
        total_ns += start.elapsed().as_nanos();
    }

    let total_parses = (lines.len() * iterations) as f64;
    total_ns as f64 / total_parses
}

#[test]
#[serial]
fn test_parsing_performance_overhead() {
    reset_config();

    let lines = generate_test_lines(10_000);

    // Benchmark strict mode (default)
    let strict_ns = benchmark_parsing(&lines, false);

    // Benchmark compatible mode
    let compatible_ns = benchmark_parsing(&lines, true);

    // Calculate overhead percentage
    let overhead_percent = ((compatible_ns - strict_ns) / strict_ns) * 100.0;

    println!("\n=== Zero-Length Interval Parsing Benchmark ===");
    println!("Strict mode:     {:.2} ns/parse", strict_ns);
    println!("Compatible mode: {:.2} ns/parse", compatible_ns);
    println!("Overhead:        {:.2}%", overhead_percent);
    println!("================================================\n");

    // Allow up to 5% overhead to account for measurement noise
    // The actual overhead should be <1% in practice
    assert!(
        overhead_percent < 5.0,
        "Performance overhead ({:.2}%) exceeds acceptable threshold (5%)",
        overhead_percent
    );

    reset_config();
}

#[test]
#[serial]
fn test_normalize_end_is_inlined() {
    reset_config();

    // This test verifies the atomic load doesn't cause measurable overhead
    // by parsing many intervals and checking total time is reasonable.
    let lines = generate_test_lines(100_000);
    let parser = FastBedParser::new();

    let start = Instant::now();
    let mut count = 0;
    for line in &lines {
        if parser.parse_interval(line).is_some() {
            count += 1;
        }
    }
    let elapsed = start.elapsed();

    // Should parse 100k lines in under 100ms on any reasonable hardware
    assert_eq!(count, 100_000);
    assert!(
        elapsed.as_millis() < 500,
        "Parsing 100k lines took {}ms, expected <500ms",
        elapsed.as_millis()
    );

    reset_config();
}
