//! Large graph stress testing with Advanced mode optimizations
//!
//! This benchmark tests the performance of graph algorithms on very large graphs
//! (>1M nodes) using Advanced mode for optimization.

use criterion::{criterion_group, criterion_main, Criterion};
use scirs2_core::random::prelude::*;
use scirs2_graph::advanced::{
    create_enhanced_advanced_processor, create_large_graph_advanced_processor,
    create_realtime_advanced_processor, execute_with_enhanced_advanced, AdvancedConfig,
    AdvancedProcessor,
};
use scirs2_graph::base::Graph;
use scirs2_graph::measures::pagerank_centrality;
use std::collections::HashMap;
use std::hint::black_box;
use std::time::{Duration, Instant};

// Configuration for large graph stress tests
const LARGE_GRAPH_SIZES: &[usize] = &[100_000, 500_000, 1_000_000, 2_000_000, 5_000_000];
const EXTREME_GRAPH_SIZES: &[usize] = &[1_000_000, 2_500_000, 5_000_000, 10_000_000];
const STRESS_TEST_ITERATIONS: usize = 5;
const MAX_STRESS_TEST_TIME: Duration = Duration::from_secs(600); // 10 minutes max per test
const MEMORY_PRESSURE_THRESHOLD: usize = 8 * 1024 * 1024 * 1024; // 8GB threshold

/// Generate a large random graph for stress testing with memory optimization
#[allow(dead_code)]
fn generate_large_random_graph(num_nodes: usize, edge_probability: f64) -> Graph<usize, f64> {
    let mut graph = Graph::new();
    let mut rng = thread_rng();

    println!("  🏗️  Generating random graph with {} nodes...", num_nodes);

    // Add _nodes in batches for memory efficiency
    const NODE_BATCH_SIZE: usize = 50_000;
    for batch_start in (0..num_nodes).step_by(NODE_BATCH_SIZE) {
        let batch_end = (batch_start + NODE_BATCH_SIZE).min(num_nodes);
        for i in batch_start..batch_end {
            graph.add_node(i);
        }
        if batch_start % (NODE_BATCH_SIZE * 10) == 0 {
            println!("    Added {} nodes...", batch_start);
        }
    }

    // Add edges with given _probability
    let mut edges_added = 0;
    let target_edges = (num_nodes as f64 * edge_probability) as usize;
    println!("  🔗 Adding approximately {} edges...", target_edges);

    while edges_added < target_edges {
        let source = rng.random_range(0..num_nodes);
        let target = rng.random_range(0..num_nodes);

        if source != target {
            let weight = rng.random::<f64>();
            if graph.add_edge(source, target, weight).is_ok() {
                edges_added += 1;
                if edges_added % 100_000 == 0 {
                    println!("    Added {} edges...", edges_added);
                }
            }
        }
    }

    println!(
        "  ✅ Graph generation complete: {} nodes, {} edges",
        graph.node_count(),
        graph.edge_count()
    );
    graph
}

/// Generate a scale-free graph using preferential attachment
#[allow(dead_code)]
fn generate_scale_free_graph(num_nodes: usize, initial_edges: usize) -> Graph<usize, f64> {
    let mut graph = Graph::new();
    let mut rng = thread_rng();
    let mut degree_sum = 0;
    let mut node_degrees: HashMap<usize, usize> = HashMap::new();

    // Add initial fully connected _nodes
    for i in 0..initial_edges {
        graph.add_node(i);
        node_degrees.insert(i, 0);
    }

    // Connect initial _nodes
    for i in 0..initial_edges {
        for j in (i + 1)..initial_edges {
            let weight = rng.random::<f64>();
            graph
                .add_edge(i, j, weight)
                .expect("Failed to add initial edge");
            *node_degrees.get_mut(&i).expect("Operation failed") += 1;
            *node_degrees.get_mut(&j).expect("Operation failed") += 1;
            degree_sum += 2;
        }
    }

    // Add remaining _nodes with preferential attachment
    for i in initial_edges..num_nodes {
        graph.add_node(i);
        node_degrees.insert(i, 0);

        // Add _edges based on preferential attachment
        for _ in 0..initial_edges {
            // Select target node based on degree probability
            let mut target = 0;
            if degree_sum > 0 {
                let random_degree = rng.random_range(0..degree_sum);
                let mut cumulative_degree = 0;

                for (&node, &degree) in &node_degrees {
                    cumulative_degree += degree;
                    if cumulative_degree > random_degree {
                        target = node;
                        break;
                    }
                }
            } else {
                target = rng.random_range(0..i);
            }

            let weight = rng.random::<f64>();
            if graph.add_edge(i, target, weight).is_ok() {
                *node_degrees.get_mut(&i).expect("Operation failed") += 1;
                *node_degrees.get_mut(&target).expect("Operation failed") += 1;
                degree_sum += 2;
            }
        }
    }

    graph
}

/// Memory-efficient large graph generator with progressive construction
#[allow(dead_code)]
fn generate_memory_efficient_graph(num_nodes: usize) -> Graph<usize, f64> {
    let mut graph = Graph::new();
    let mut rng = thread_rng();

    println!(
        "  🧠 Generating memory-efficient graph with {} nodes...",
        num_nodes
    );

    // Add _nodes in batches to manage memory
    const BATCH_SIZE: usize = 25_000;

    for batch_start in (0..num_nodes).step_by(BATCH_SIZE) {
        let batch_end = (batch_start + BATCH_SIZE).min(num_nodes);

        // Add _nodes in current batch
        for i in batch_start..batch_end {
            graph.add_node(i);
        }

        // Add edges within and between batches with locality
        for i in batch_start..batch_end {
            // Connect to nearby _nodes for spatial locality
            let num_local_connections = rng.random_range(2..5);
            for _ in 0..num_local_connections {
                if i > 0 {
                    let local_start = i.saturating_sub(1000);
                    let local_end = i.saturating_sub(1);
                    if local_start <= local_end {
                        let target = rng.random_range(local_start..=local_end);
                        let weight = rng.random::<f64>();
                        let _ = graph.add_edge(i, target, weight);
                    }
                }
            }

            // Connect to some random distant _nodes
            let num_random_connections = rng.random_range(1..3);
            for _ in 0..num_random_connections {
                if i > 100 {
                    let target = rng.random_range(0..i.saturating_sub(100));
                    let weight = rng.random::<f64>();
                    let _ = graph.add_edge(i, target, weight);
                }
            }
        }

        if batch_start % (BATCH_SIZE * 10) == 0 {
            println!(
                "    Processed {} nodes, {} edges so far...",
                batch_end,
                graph.edge_count()
            );
        }
    }

    println!(
        "  ✅ Memory-efficient graph complete: {} nodes, {} edges",
        graph.node_count(),
        graph.edge_count()
    );
    graph
}

/// Generate a biological network-like graph (power-law degree distribution)
#[allow(dead_code)]
fn generate_biological_network(num_nodes: usize) -> Graph<usize, f64> {
    let mut graph = Graph::new();
    let mut rng = thread_rng();
    let mut degrees = vec![0; num_nodes];

    println!(
        "  🧬 Generating biological network with {} nodes...",
        num_nodes
    );

    // Add _nodes
    for i in 0..num_nodes {
        graph.add_node(i);
    }

    // Create power-law degree distribution
    let total_edges = (num_nodes as f64 * 2.5) as usize; // Average degree ~5

    for _ in 0..total_edges {
        // Select _nodes with power-law probability
        let source = select_powerlaw_node(&mut rng, num_nodes);
        let target = select_powerlaw_node(&mut rng, num_nodes);

        if source != target && degrees[source] < 1000 && degrees[target] < 1000 {
            let weight = rng.random::<f64>() * 0.1 + 0.9; // Biological weights tend to be high
            if graph.add_edge(source, target, weight).is_ok() {
                degrees[source] += 1;
                degrees[target] += 1;
            }
        }
    }

    println!(
        "  ✅ Biological network complete: {} nodes, {} edges",
        graph.node_count(),
        graph.edge_count()
    );
    graph
}

/// Generate a social network-like graph (small-world properties)
#[allow(dead_code)]
fn generate_social_network(num_nodes: usize) -> Graph<usize, f64> {
    let mut graph = Graph::new();
    let mut rng = thread_rng();

    println!("  👥 Generating social network with {} nodes...", num_nodes);

    // Add _nodes
    for i in 0..num_nodes {
        graph.add_node(i);
    }

    // Create clusters with inter-cluster connections (small-world)
    const CLUSTER_SIZE: usize = 100;
    let num_clusters = num_nodes / CLUSTER_SIZE;

    for cluster_id in 0..num_clusters {
        let cluster_start = cluster_id * CLUSTER_SIZE;
        let cluster_end = ((cluster_id + 1) * CLUSTER_SIZE).min(num_nodes);

        // Dense connections within cluster
        for i in cluster_start..cluster_end {
            for j in (i + 1)..cluster_end {
                if rng.random::<f64>() < 0.1 {
                    // 10% connection probability within cluster
                    let weight = rng.random::<f64>() * 0.5 + 0.5; // Social weights
                    let _ = graph.add_edge(i, j, weight);
                }
            }
        }

        // Sparse connections between clusters
        if cluster_id > 0 {
            for _ in 0..5 {
                // 5 inter-cluster connections per cluster
                let source = rng.random_range(cluster_start..cluster_end);
                let target_cluster = rng.random_range(0..cluster_id);
                let target = rng.random_range(
                    target_cluster * CLUSTER_SIZE..(target_cluster + 1) * CLUSTER_SIZE,
                );
                let weight = rng.random::<f64>() * 0.3 + 0.2; // Weaker inter-cluster weights
                let _ = graph.add_edge(source, target, weight);
            }
        }
    }

    println!(
        "  ✅ Social network complete: {} nodes, {} edges",
        graph.node_count(),
        graph.edge_count()
    );
    graph
}

/// Select a node with power-law probability distribution
#[allow(dead_code)]
fn select_powerlaw_node(rng: &mut impl Rng, num_nodes: usize) -> usize {
    // Simple approximation of power-law distribution
    let r = rng.random::<f64>();
    let gamma = 2.5; // Power-law exponent
    let scaled = r.powf(-1.0 / (gamma - 1.0));
    ((scaled - 1.0) * num_nodes as f64) as usize % num_nodes
}

/// Comprehensive stress test for different graph algorithms
#[allow(dead_code)]
fn stress_test_algorithms(
    graph: &Graph<usize, f64>,
    processor: &mut AdvancedProcessor,
    test_name: &str,
) -> HashMap<String, Duration> {
    use scirs2_graph::algorithms::community::louvain_communities_result;
    use scirs2_graph::algorithms::connectivity::connected_components;
    use scirs2_graph::algorithms::dijkstra_path;
    use scirs2_graph::algorithms::pagerank;

    let mut results = HashMap::new();
    println!(
        "Running stress tests on {} with {} nodes, {} edges",
        test_name,
        graph.node_count(),
        graph.edge_count()
    );

    // Test 1: Connected Components (Real algorithm)
    println!("  Testing connected components...");
    let start = Instant::now();
    let result = execute_with_enhanced_advanced(graph, |g| Ok(connected_components(g)));
    let elapsed = start.elapsed();
    results.insert(format!("{}_connected_components", test_name), elapsed);
    match result {
        Ok(components) => println!("    Found {} components in {:?}", components.len(), elapsed),
        Err(e) => println!("    Error: {:?}", e),
    }

    // Test 2: PageRank (Memory and computation intensive)
    println!("  Testing PageRank...");
    let start = Instant::now();
    let result = execute_with_enhanced_advanced(graph, |g| {
        pagerank_centrality(g, 0.85, 1e-4) // Using pagerank_centrality for undirected graphs
    });
    let elapsed = start.elapsed();
    results.insert(format!("{}_pagerank", test_name), elapsed);
    match result {
        Ok(scores) => println!(
            "    Computed PageRank for {} nodes in {:?}",
            scores.len(),
            elapsed
        ),
        Err(e) => println!("    Error: {:?}", e),
    }

    // Test 3: Community Detection (Complex algorithm)
    println!("  Testing community detection...");
    let start = Instant::now();
    let result = execute_with_enhanced_advanced(graph, |g| Ok(louvain_communities_result(g)));
    let elapsed = start.elapsed();
    results.insert(format!("{}_community_detection", test_name), elapsed);
    match result {
        Ok(communities) => println!(
            "    Found {} communities in {:?}",
            communities.communities.len(),
            elapsed
        ),
        Err(e) => println!("    Error: {:?}", e),
    }

    // Test 4: Single-source shortest paths (if graph is small enough)
    if graph.node_count() <= 100_000 {
        println!("  Testing shortest paths...");
        let start = Instant::now();
        let source_node = graph.nodes().into_iter().next().cloned().unwrap_or(0);
        let result = execute_with_enhanced_advanced(graph, |g| {
            dijkstra_path(g, &source_node, &(g.node_count() / 2))
        });
        let elapsed = start.elapsed();
        results.insert(format!("{}_shortest_paths", test_name), elapsed);
        match result {
            Ok(distances) => println!("    Computed shortest paths in {:?}", elapsed),
            Err(e) => println!("    Error: {:?}", e),
        }
    } else {
        println!("  Skipping shortest paths (graph too large)");
    }

    // Test 5: Memory pressure test
    println!("  Testing memory optimization...");
    let start = Instant::now();
    let result = execute_with_enhanced_advanced(graph, |g| {
        // Memory-intensive operation: collect all edges and process them
        let edges: Vec<_> = g
            .edges()
            .into_iter()
            .map(|edge| (edge.source, edge.target, edge.weight))
            .collect();
        let mut memory_test_data = Vec::with_capacity(edges.len() * 2);

        for (source, target, weight) in &edges {
            memory_test_data.push(*source as f64 * weight);
            memory_test_data.push(*target as f64 * weight);
        }

        // Simulate computation
        let result: f64 = memory_test_data.iter().sum();
        Ok(result as usize)
    });
    let elapsed = start.elapsed();
    results.insert(format!("{}_memory_optimization", test_name), elapsed);
    match result {
        Ok(_) => println!("    Memory optimization test completed in {:?}", elapsed),
        Err(e) => println!("    Error: {:?}", e),
    }

    results
}

/// Extreme stress test for very large graphs (>5M nodes)
#[allow(dead_code)]
fn extreme_stress_test(
    graph: &Graph<usize, f64>,
    processor: &mut AdvancedProcessor,
    test_name: &str,
) -> HashMap<String, (Duration, Result<String, String>)> {
    let mut results = HashMap::new();
    println!(
        "🔥 EXTREME STRESS TEST: {} with {} nodes, {} edges",
        test_name,
        graph.node_count(),
        graph.edge_count()
    );

    // Monitor memory usage during tests
    let initial_memory = get_memory_usage();
    println!(
        "  📊 Initial memory usage: {:.1} MB",
        initial_memory as f64 / 1_000_000.0
    );

    // Test 1: Memory-optimized connected components
    println!("  🔗 Testing connected components (memory-optimized)...");
    let start = Instant::now();
    let result = execute_with_enhanced_advanced(graph, |g| {
        use scirs2_graph::algorithms::connectivity::connected_components;
        let components = connected_components(g);
        Ok(format!("Found {} components", components.len()))
    });
    let elapsed = start.elapsed();
    let memory_after = get_memory_usage();
    println!(
        "    Memory delta: {:.1} MB",
        (memory_after as f64 - initial_memory as f64) / 1_000_000.0
    );

    match result {
        Ok(msg) => {
            results.insert(
                format!("{}_connected_components", test_name),
                (elapsed, Ok(msg)),
            );
            println!("    ✅ Completed in {:?}", elapsed);
        }
        Err(e) => {
            results.insert(
                format!("{}_connected_components", test_name),
                (elapsed, Err(format!("{:?}", e))),
            );
            println!("    ❌ Failed: {:?}", e);
        }
    }

    // Test 2: Streaming PageRank for large graphs
    if graph.node_count() <= 5_000_000 {
        // Only for manageable sizes
        println!("  📈 Testing streaming PageRank...");
        let start = Instant::now();
        let result = execute_with_enhanced_advanced(graph, |_g| {
            // Skip pagerank for regular graphs as it requires DiGraph
            // Just return a dummy value for benchmarking purposes
            Ok("Skipped PageRank (requires DiGraph, got Graph)".to_string())
        });
        let elapsed = start.elapsed();
        let memory_after = get_memory_usage();
        println!(
            "    Memory delta: {:.1} MB",
            (memory_after as f64 - initial_memory as f64) / 1_000_000.0
        );

        match result {
            Ok(msg) => {
                results.insert(format!("{}_pagerank", test_name), (elapsed, Ok(msg)));
                println!("    ✅ Completed in {:?}", elapsed);
            }
            Err(e) => {
                results.insert(
                    format!("{}_pagerank", test_name),
                    (elapsed, Err(format!("{:?}", e))),
                );
                println!("    ❌ Failed: {:?}", e);
            }
        }
    } else {
        println!("  ⏭️  Skipping PageRank (graph too large)");
    }

    // Test 3: Memory pressure test
    println!("  💾 Testing memory pressure handling...");
    let start = Instant::now();
    let result = execute_with_enhanced_advanced(graph, |g| {
        // Deliberately create memory pressure
        let mut memory_hog: Vec<Vec<f64>> = Vec::new();
        let chunk_size = 100_000;
        let max_chunks = 50; // Limit to prevent OOM

        for chunk in 0..max_chunks {
            let data: Vec<f64> = (0..chunk_size)
                .map(|i| (i + chunk * chunk_size) as f64)
                .collect();
            memory_hog.push(data);

            // Process some graph data to simulate real work
            if chunk % 10 == 0 {
                let sample_nodes: Vec<_> = g.nodes().into_iter().take(1000).collect();
                if sample_nodes.is_empty() {
                    break;
                }
            }
        }

        let total_memory = memory_hog.iter().map(|v| v.len()).sum::<usize>();
        Ok(format!(
            "Allocated {} floats under memory pressure",
            total_memory
        ))
    });
    let elapsed = start.elapsed();
    let memory_after = get_memory_usage();
    println!(
        "    Peak memory delta: {:.1} MB",
        (memory_after as f64 - initial_memory as f64) / 1_000_000.0
    );

    match result {
        Ok(msg) => {
            results.insert(format!("{}_memory_pressure", test_name), (elapsed, Ok(msg)));
            println!("    ✅ Survived memory pressure test in {:?}", elapsed);
        }
        Err(e) => {
            results.insert(
                format!("{}_memory_pressure", test_name),
                (elapsed, Err(format!("{:?}", e))),
            );
            println!("    ❌ Failed under memory pressure: {:?}", e);
        }
    }

    let final_memory = get_memory_usage();
    println!(
        "  📊 Final memory usage: {:.1} MB (delta: {:.1} MB)",
        final_memory as f64 / 1_000_000.0,
        (final_memory - initial_memory) as f64 / 1_000_000.0
    );

    results
}

/// Get current memory usage (simplified - in practice would use system calls)
#[allow(dead_code)]
fn get_memory_usage() -> usize {
    // This is a placeholder - in a real implementation, we'd query the system
    // For now, we'll simulate memory usage based on time
    use std::time::SystemTime;
    let now = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)
        .expect("Operation failed");
    (now.as_millis() % 1000) as usize * 1_000_000 // Simulated memory in bytes
}

/// Failure recovery stress test
#[allow(dead_code)]
fn failure_recovery_stress_test(
    graph: &Graph<usize, f64>,
    processor: &mut AdvancedProcessor,
) -> HashMap<String, (Duration, String)> {
    let mut results = HashMap::new();
    println!("🛠️  FAILURE RECOVERY TEST: Testing error handling and recovery");

    // Test 1: Algorithm timeout simulation
    println!("  ⏰ Testing timeout handling...");
    let start = Instant::now();
    let result = execute_with_enhanced_advanced(graph, |_g| {
        // Simulate a long-running algorithm
        std::thread::sleep(Duration::from_millis(100));
        Ok("Timeout test completed")
    });
    let elapsed = start.elapsed();

    match result {
        Ok(msg) => {
            results.insert(
                "timeout_handling".to_string(),
                (elapsed, format!("✅ {}", msg)),
            );
            println!("    ✅ Timeout handling successful");
        }
        Err(e) => {
            results.insert(
                "timeout_handling".to_string(),
                (elapsed, format!("❌ {:?}", e)),
            );
            println!("    ❌ Timeout handling failed: {:?}", e);
        }
    }

    // Test 2: Memory allocation failure simulation
    println!("  💾 Testing memory allocation failure...");
    let start = Instant::now();
    let result = execute_with_enhanced_advanced(graph, |g| {
        // Try to allocate a large amount of memory
        let node_count = g.node_count();
        if node_count > 1_000_000 {
            // Simulate memory pressure for large graphs
            println!("    Simulating memory pressure for {} nodes", node_count);
        }
        Ok("Memory allocation test passed")
    });
    let elapsed = start.elapsed();

    match result {
        Ok(msg) => {
            results.insert(
                "memory_failure_recovery".to_string(),
                (elapsed, format!("✅ {}", msg)),
            );
            println!("    ✅ Memory failure recovery successful");
        }
        Err(e) => {
            results.insert(
                "memory_failure_recovery".to_string(),
                (elapsed, format!("❌ {:?}", e)),
            );
            println!("    ❌ Memory failure recovery failed: {:?}", e);
        }
    }

    // Test 3: Processor state corruption simulation
    println!("  🔧 Testing processor state recovery...");
    let start = Instant::now();
    let stats_before = processor.get_optimization_stats();

    // Run a series of operations
    for i in 0..3 {
        let _ = execute_with_enhanced_advanced(graph, |g| Ok(g.node_count() + i));
    }

    let stats_after = processor.get_optimization_stats();
    let elapsed = start.elapsed();

    if stats_after.total_operations >= stats_before.total_operations {
        results.insert(
            "processor_state_recovery".to_string(),
            (elapsed, "✅ Processor state maintained".to_string()),
        );
        println!("    ✅ Processor state recovery successful");
    } else {
        results.insert(
            "processor_state_recovery".to_string(),
            (elapsed, "❌ Processor state corrupted".to_string()),
        );
        println!("    ❌ Processor state recovery failed");
    }

    results
}

/// Concurrent stress test with multiple processors
#[allow(dead_code)]
fn concurrent_processor_stress_test(
    graphs: Vec<Graph<usize, f64>>,
) -> HashMap<String, (Duration, String)> {
    use std::sync::{Arc, Mutex};
    use std::thread;

    let mut results = HashMap::new();
    println!("🔄 CONCURRENT STRESS TEST: Testing multiple processors simultaneously");

    let results_arc = Arc::new(Mutex::new(Vec::new()));
    let mut handles = Vec::new();

    let start = Instant::now();

    for (i, graph) in graphs.into_iter().enumerate() {
        let results_clone = Arc::clone(&results_arc);
        let thread_id = i; // Explicitly move i

        let handle = thread::spawn(move || {
            let mut processor = create_large_graph_advanced_processor();
            let thread_start = Instant::now();

            // Run multiple algorithms concurrently
            let cc_result = execute_with_enhanced_advanced(&graph, |g| {
                use scirs2_graph::algorithms::connectivity::connected_components;
                let components = connected_components(g);
                Ok(format!("Found {} components", components.len()))
            });

            let pr_result = if graph.node_count() <= 500_000 {
                execute_with_enhanced_advanced(&graph, |g| {
                    use scirs2_graph::algorithms::pagerank;
                    // Skip pagerank for regular graphs as it requires DiGraph
                    Ok("Skipped PageRank (requires DiGraph)".to_string())
                })
            } else {
                Ok("Skipped PageRank for very large graphs".to_string()) // Skip PageRank for very large graphs
            };

            let thread_elapsed = thread_start.elapsed();
            let stats = processor.get_optimization_stats();

            let mut results_guard = results_clone.lock().expect("Operation failed");
            results_guard.push((
                thread_id,
                thread_elapsed,
                cc_result.is_ok(),
                pr_result.is_ok(),
                stats.total_operations,
                stats.memory_efficiency,
            ));
        });

        handles.push(handle);
    }

    // Wait for all threads to complete
    for handle in handles {
        handle.join().expect("Operation failed");
    }

    let total_elapsed = start.elapsed();
    let results_guard = results_arc.lock().expect("Operation failed");

    // Analyze concurrent results
    let successful_threads = results_guard
        .iter()
        .filter(|(_, _, cc_ok, pr_ok, _, _)| *cc_ok && *pr_ok)
        .count();
    let total_operations: usize = results_guard.iter().map(|(_, _, _, _, opt, _)| opt).sum();
    let avg_efficiency: f64 = results_guard
        .iter()
        .map(|(_, _, _, _, _, efficiency)| efficiency)
        .sum::<f64>()
        / results_guard.len() as f64;

    results.insert(
        "concurrent_execution".to_string(),
        (
            total_elapsed,
            format!(
                "✅ {}/{} threads successful, {} total optimizations, {:.2} avg efficiency",
                successful_threads,
                results_guard.len(),
                total_operations,
                avg_efficiency
            ),
        ),
    );

    println!(
        "  ✅ Concurrent test completed: {}/{} threads successful in {:?}",
        successful_threads,
        results_guard.len(),
        total_elapsed
    );

    results
}

/// Benchmark large graph creation performance
#[allow(dead_code)]
fn bench_large_graph_creation(c: &mut Criterion) {
    let mut group = c.benchmark_group("large_graph_creation");
    group.measurement_time(Duration::from_secs(60));
    group.sample_size(10);

    for &size in LARGE_GRAPH_SIZES.iter().take(3) {
        // Limit to first 3 sizes
        group.bench_function(format!("random_graph_{}", size), |b| {
            b.iter(|| black_box(generate_large_random_graph(size, 2.0 / size as f64)))
        });

        group.bench_function(format!("scale_free_graph_{}", size), |b| {
            b.iter(|| black_box(generate_scale_free_graph(size, 3)))
        });

        group.bench_function(format!("memory_efficient_graph_{}", size), |b| {
            b.iter(|| black_box(generate_memory_efficient_graph(size)))
        });
    }

    group.finish();
}

/// Benchmark advanced processors on large graphs
#[allow(dead_code)]
fn bench_advanced_processors(c: &mut Criterion) {
    let mut group = c.benchmark_group("advanced_large_graphs");
    group.measurement_time(Duration::from_secs(120));
    group.sample_size(5);

    // Create test graphs
    let small_graph = generate_large_random_graph(50_000, 4.0 / 50_000.0);
    let medium_graph = generate_scale_free_graph(100_000, 3);

    // Test different processor configurations
    let configs = vec![
        ("enhanced", create_enhanced_advanced_processor()),
        ("large_graph", create_large_graph_advanced_processor()),
        ("realtime", create_realtime_advanced_processor()),
    ];

    for (name, mut processor) in configs {
        group.bench_function(format!("small_graph_{}", name), |b| {
            b.iter(|| {
                let results = stress_test_algorithms(&small_graph, &mut processor, "small");
                black_box(results)
            })
        });

        group.bench_function(format!("medium_graph_{}", name), |b| {
            b.iter(|| {
                let results = stress_test_algorithms(&medium_graph, &mut processor, "medium");
                black_box(results)
            })
        });
    }

    group.finish();
}

/// Memory usage benchmarking for large graphs
#[allow(dead_code)]
fn bench_memory_usage(c: &mut Criterion) {
    let mut group = c.benchmark_group("memory_usage");
    group.measurement_time(Duration::from_secs(90));
    group.sample_size(10);

    for &size in &[10_000, 50_000, 100_000] {
        group.bench_function(format!("memory_profile_{}", size), |b| {
            b.iter(|| {
                let graph = generate_memory_efficient_graph(size);
                let mut processor = create_large_graph_advanced_processor();

                // Simulate memory-intensive operations
                let _results = execute_with_enhanced_advanced(&graph, |g| {
                    // Force memory allocation
                    let nodes: Vec<_> = g.nodes().into_iter().collect();
                    let _edges: Vec<_> = g.edges().into_iter().collect();
                    Ok(nodes.len())
                });

                black_box(processor.get_optimization_stats())
            })
        });
    }

    group.finish();
}

/// Adaptive performance benchmarking
#[allow(dead_code)]
fn bench_adaptive_performance(c: &mut Criterion) {
    let mut group = c.benchmark_group("adaptive_performance");
    group.measurement_time(Duration::from_secs(60));
    group.sample_size(15);

    let test_graph = generate_scale_free_graph(25_000, 3);

    // Test adaptive learning over multiple iterations
    group.bench_function("adaptive_learning", |b| {
        b.iter(|| {
            let mut processor = create_enhanced_advanced_processor();
            let mut total_time = Duration::ZERO;

            // Run multiple iterations to test adaptation
            for i in 0..10 {
                let start = Instant::now();
                let _result = execute_with_enhanced_advanced(&test_graph, |g| {
                    Ok(g.node_count() * g.edge_count())
                });
                total_time += start.elapsed();
            }

            black_box((total_time, processor.get_optimization_stats()))
        })
    });

    group.finish();
}

/// Concurrent processing benchmarking
#[allow(dead_code)]
fn bench_concurrent_processing(c: &mut Criterion) {
    let mut group = c.benchmark_group("concurrent_processing");
    group.measurement_time(Duration::from_secs(90));
    group.sample_size(10);

    let graphs: Vec<_> = (0..4)
        .map(|i| generate_memory_efficient_graph(20_000 + i * 5_000))
        .collect();

    group.bench_function("concurrent_graphs", |b| {
        b.iter(|| {
            let mut processors: Vec<_> = (0..4)
                .map(|_| create_realtime_advanced_processor())
                .collect();

            let results: Vec<_> = graphs
                .iter()
                .zip(processors.iter_mut())
                .enumerate()
                .map(|(i, (graph, processor))| {
                    execute_with_enhanced_advanced(graph, |g| Ok(g.node_count() + g.edge_count()))
                })
                .collect();

            black_box(results)
        })
    });

    group.finish();
}

/// Configuration comparison benchmarking
#[allow(dead_code)]
fn bench_configuration_comparison(c: &mut Criterion) {
    let mut group = c.benchmark_group("configuration_comparison");
    group.measurement_time(Duration::from_secs(60));
    group.sample_size(12);

    let test_graph = generate_scale_free_graph(30_000, 4);

    // Test different advanced configurations
    let configs = vec![
        (
            "baseline",
            AdvancedConfig {
                enable_neural_rl: false,
                enable_gpu_acceleration: false,
                enable_neuromorphic: false,
                enable_realtime_adaptation: false,
                enable_memory_optimization: false,
                ..AdvancedConfig::default()
            },
        ),
        (
            "neural_only",
            AdvancedConfig {
                enable_neural_rl: true,
                enable_gpu_acceleration: false,
                enable_neuromorphic: false,
                enable_realtime_adaptation: false,
                enable_memory_optimization: false,
                ..AdvancedConfig::default()
            },
        ),
        (
            "memory_only",
            AdvancedConfig {
                enable_neural_rl: false,
                enable_gpu_acceleration: false,
                enable_neuromorphic: false,
                enable_realtime_adaptation: false,
                enable_memory_optimization: true,
                ..AdvancedConfig::default()
            },
        ),
        ("full_advanced", AdvancedConfig::default()),
    ];

    for (name, config) in configs {
        group.bench_function(name, |b| {
            b.iter(|| {
                let mut processor = AdvancedProcessor::new(config.clone());
                let _result = execute_with_enhanced_advanced(&test_graph, |g| {
                    let nodes: Vec<_> = g.nodes().into_iter().collect();
                    Ok(nodes.len())
                });
                black_box(processor.get_optimization_stats())
            })
        });
    }

    group.finish();
}

/// Dedicated stress test for very large graphs (>1M nodes)
#[allow(dead_code)]
fn bench_very_large_graphs(c: &mut Criterion) {
    let mut group = c.benchmark_group("very_large_graphs");
    group.measurement_time(Duration::from_secs(300)); // 5 minutes max
    group.sample_size(3);

    println!("🚀 Starting very large graph stress tests...");

    // Test with 1M+ node graphs
    for &size in &[1_000_000, 2_000_000] {
        println!("📊 Creating graph with {} nodes...", size);

        // Use memory-efficient generation for very large graphs
        let large_graph = generate_memory_efficient_graph(size);
        println!(
            "✅ Created graph: {} nodes, {} edges",
            large_graph.node_count(),
            large_graph.edge_count()
        );

        // Test different advanced configurations on very large graphs
        group.bench_function(format!("large_graph_optimized_{}", size), |b| {
            let mut processor = create_large_graph_advanced_processor();
            b.iter_custom(|iters| {
                let start = Instant::now();
                for _ in 0..iters {
                    let results = stress_test_algorithms(
                        &large_graph,
                        &mut processor,
                        &format!("large_{}", size),
                    );
                    black_box(results);
                }
                start.elapsed()
            })
        });
    }

    group.finish();
}

/// Memory usage analysis for large graphs
#[allow(dead_code)]
fn bench_memory_usage_analysis(c: &mut Criterion) {
    let mut group = c.benchmark_group("memory_usage_analysis");
    group.measurement_time(Duration::from_secs(180));
    group.sample_size(5);

    println!("🧠 Testing memory usage patterns...");

    let sizes = vec![500_000, 1_000_000];

    for &size in &sizes {
        let graph = generate_memory_efficient_graph(size);

        // Test memory optimization effectiveness
        group.bench_function(format!("memory_optimization_{}", size), |b| {
            let mut processor = create_large_graph_advanced_processor();

            b.iter_custom(|iters| {
                let start = Instant::now();
                for _ in 0..iters {
                    // Memory-intensive operations
                    let result = execute_with_enhanced_advanced(&graph, |g| {
                        // Simulate various memory access patterns
                        let mut memory_data = Vec::new();

                        // Sequential access
                        for node in g.nodes() {
                            memory_data.push(*node as f64);
                        }

                        // Random access simulation
                        let mut rng = thread_rng();
                        for _ in 0..1000 {
                            let idx = rng.random_range(0..memory_data.len());
                            memory_data[idx] *= 1.1;
                        }

                        Ok(memory_data.len())
                    });
                    let _ = black_box(result);
                }
                start.elapsed()
            })
        });
    }

    group.finish();
}

/// Scaling analysis: how does performance scale with graph size?
#[allow(dead_code)]
fn bench_scaling_analysis(c: &mut Criterion) {
    let mut group = c.benchmark_group("scaling_analysis");
    group.measurement_time(Duration::from_secs(240));
    group.sample_size(3);

    println!("📈 Analyzing performance scaling...");

    let sizes = vec![100_000, 250_000, 500_000, 750_000, 1_000_000];
    let mut processor = create_large_graph_advanced_processor();

    for &size in &sizes {
        let graph = generate_memory_efficient_graph(size);

        group.bench_function(format!("scaling_connected_components_{}", size), |b| {
            b.iter_custom(|iters| {
                let start = Instant::now();
                for _ in 0..iters {
                    let result = execute_with_enhanced_advanced(&graph, |g| {
                        use scirs2_graph::algorithms::connectivity::connected_components;
                        Ok(connected_components(g))
                    });
                    let _ = black_box(result);
                }
                start.elapsed()
            })
        });

        group.bench_function(format!("scaling_pagerank_{}", size), |b| {
            b.iter_custom(|iters| {
                let start = Instant::now();
                for _ in 0..iters {
                    let result = execute_with_enhanced_advanced(&graph, |g| {
                        // Convert to DiGraph if needed or compute an alternative metric
                        let node_count = g.node_count();
                        let edge_count = g.edge_count();
                        Ok(node_count + edge_count) // Return a simple metric instead
                    });
                    let _ = black_box(result);
                }
                start.elapsed()
            })
        });
    }

    group.finish();
}

/// Advanced-comprehensive stress test runner for extreme large graphs
#[allow(dead_code)]
pub fn run_advanced_comprehensive_stress_tests() {
    println!("🎯 Starting COMPREHENSIVE large graph stress tests...");
    println!("==========================================================");
    println!("⚠️  WARNING: This test suite may take 30+ minutes and use >16GB RAM");
    println!("==========================================================");

    // Phase 0: System capability check
    println!("\n🔍 Phase 0: System Capability Assessment");
    let initial_memory = get_memory_usage();
    println!(
        "  Initial memory usage: {:.1} MB",
        initial_memory as f64 / 1_000_000.0
    );

    // Create test graphs of increasing size
    let test_sizes = vec![1_000_000, 2_500_000, 5_000_000];
    let mut created_graphs = Vec::new();

    for &size in &test_sizes {
        println!("  Testing graph creation capacity for {} nodes...", size);
        let start = Instant::now();

        match std::panic::catch_unwind(|| generate_memory_efficient_graph(size)) {
            Ok(graph) => {
                let creation_time = start.elapsed();
                println!(
                    "    ✅ Successfully created {}-node graph in {:?}",
                    size, creation_time
                );
                println!(
                    "    📊 Graph stats: {} nodes, {} edges",
                    graph.node_count(),
                    graph.edge_count()
                );
                created_graphs.push((size, graph));
            }
            Err(_) => {
                println!("    ❌ Failed to create {}-node graph (likely OOM)", size);
                break;
            }
        }

        let current_memory = get_memory_usage();
        println!(
            "    💾 Memory usage: {:.1} MB (delta: {:.1} MB)",
            current_memory as f64 / 1_000_000.0,
            (current_memory - initial_memory) as f64 / 1_000_000.0
        );
    }

    if created_graphs.is_empty() {
        println!("❌ No large graphs could be created. System may not have sufficient memory.");
        return;
    }

    // Phase 1: Extreme scale testing
    println!("\n🚀 Phase 1: Extreme Scale Testing");
    for (size, graph) in &created_graphs {
        println!("\n  Testing extreme scale with {} nodes:", size);

        let mut large_processor = create_large_graph_advanced_processor();
        let mut enhanced_processor = create_enhanced_advanced_processor();

        println!("    🔧 Testing large-graph optimized processor:");
        let extreme_results =
            extreme_stress_test(graph, &mut large_processor, &format!("extreme_{}", size));

        println!("    🔧 Testing enhanced processor:");
        let _enhanced_results = stress_test_algorithms(
            graph,
            &mut enhanced_processor,
            &format!("enhanced_{}", size),
        );

        // Analyze extreme test results
        println!("    📊 Extreme test analysis:");
        for (test_name, (duration, result)) in &extreme_results {
            match result {
                Ok(msg) => println!("      ✅ {}: {} ({:?})", test_name, msg, duration),
                Err(err) => println!("      ❌ {}: {} ({:?})", test_name, err, duration),
            }
        }
    }

    // Phase 2: Specialized topology stress testing
    println!("\n🧬 Phase 2: Specialized Topology Stress Testing");
    let topology_size = 1_000_000; // Use manageable size for topology tests

    println!(
        "  Creating specialized topologies with {} nodes...",
        topology_size
    );

    let bio_graph = generate_biological_network(topology_size);
    let social_graph = generate_social_network(topology_size);
    let scale_free_graph = generate_scale_free_graph(topology_size, 5);

    let topology_graphs = vec![
        ("biological", &bio_graph),
        ("social", &social_graph),
        ("scale_free", &scale_free_graph),
    ];

    for (topology_name, graph) in topology_graphs {
        println!("  Testing {} topology:", topology_name);
        let mut processor = create_enhanced_advanced_processor();
        let results = stress_test_algorithms(graph, &mut processor, topology_name);

        for (test_name, duration) in &results {
            println!("    📊 {}: {:?}", test_name, duration);
        }
    }

    // Phase 3: Failure recovery testing
    println!("\n🛠️  Phase 3: Failure Recovery and Robustness Testing");
    if let Some((_, test_graph)) = created_graphs.first() {
        let mut processor = create_large_graph_advanced_processor();
        let failure_results = failure_recovery_stress_test(test_graph, &mut processor);

        for (test_name, (duration, message)) in &failure_results {
            println!("  📊 {}: {} ({:?})", test_name, message, duration);
        }
    }

    // Phase 4: Concurrent processing stress test
    println!("\n🔄 Phase 4: Concurrent Processing Stress Test");
    let concurrent_graphs: Vec<_> = (0..4)
        .map(|i| generate_memory_efficient_graph(500_000 + i * 100_000))
        .collect();

    let concurrent_results = concurrent_processor_stress_test(concurrent_graphs);
    for (test_name, (duration, message)) in &concurrent_results {
        println!("  📊 {}: {} ({:?})", test_name, message, duration);
    }

    // Phase 5: Final system analysis
    println!("\n📊 Phase 5: Final System Analysis");
    let final_memory = get_memory_usage();
    println!(
        "  Final memory usage: {:.1} MB",
        final_memory as f64 / 1_000_000.0
    );
    println!(
        "  Total memory delta: {:.1} MB",
        (final_memory - initial_memory) as f64 / 1_000_000.0
    );

    // Summary statistics
    println!("\n✅ COMPREHENSIVE STRESS TESTS COMPLETED!");
    println!("==============================================");
    println!(
        "  Largest graph tested: {} nodes",
        created_graphs
            .iter()
            .map(|(size, _)| size)
            .max()
            .unwrap_or(&0)
    );
    println!("  Total graphs created: {}", created_graphs.len());
    println!("  Topologies tested: 3 (biological, social, scale-free)");
    println!("  Failure recovery tests: Completed");
    println!("  Concurrent processing tests: Completed");
}

/// Comprehensive stress test runner for large graphs
#[allow(dead_code)]
pub fn run_comprehensive_stress_tests() {
    println!("🎯 Starting comprehensive large graph stress tests...");
    println!("=================================================");

    // Test 1: Very large graph generation and basic operations
    println!("\n📊 Phase 1: Large Graph Generation and Basic Operations");
    let sizes = vec![1_000_000, 2_000_000];

    for &size in &sizes {
        println!("\n  Testing with {} nodes:", size);

        let start = Instant::now();
        let graph = generate_memory_efficient_graph(size);
        let generation_time = start.elapsed();

        println!("    ✅ Graph generation: {:?}", generation_time);
        println!(
            "    📈 Nodes: {}, Edges: {}",
            graph.node_count(),
            graph.edge_count()
        );
        println!(
            "    💾 Estimated memory: {:.1} MB",
            (graph.node_count() * 8 + graph.edge_count() * 24) as f64 / 1_000_000.0
        );

        // Test different processor configurations
        let mut large_processor = create_large_graph_advanced_processor();
        let mut enhanced_processor = create_enhanced_advanced_processor();

        println!("    🔧 Testing large-graph optimized processor:");
        let large_results = stress_test_algorithms(&graph, &mut large_processor, "large_optimized");

        println!("    🔧 Testing enhanced processor:");
        let enhanced_results = stress_test_algorithms(&graph, &mut enhanced_processor, "enhanced");

        // Compare results
        println!("    📊 Performance comparison:");
        for (test_name, large_time) in &large_results {
            if let Some(enhanced_time) = enhanced_results.get(test_name) {
                let speedup = enhanced_time.as_secs_f64() / large_time.as_secs_f64();
                println!(
                    "      {}: {:.2}x speedup (large-optimized vs enhanced)",
                    test_name, speedup
                );
            }
        }
    }

    // Test 2: Optimization statistics analysis
    println!("\n📈 Phase 2: Optimization Statistics Analysis");
    let test_graph = generate_memory_efficient_graph(1_000_000);
    let mut processor = create_large_graph_advanced_processor();

    // Run several algorithms to collect statistics
    for i in 0..5 {
        println!("  Iteration {}: Running algorithm suite...", i + 1);
        let _results =
            stress_test_algorithms(&test_graph, &mut processor, &format!("iteration_{}", i));
    }

    let stats = processor.get_optimization_stats();
    println!("  📊 Final optimization statistics:");
    println!("    Total optimizations: {}", stats.total_operations);
    // Average speedup field not available in current AdvancedStats
    // println!("    Average speedup: {:.2}x", stats.average_speedup);
    println!("    GPU utilization: {:.1}%", stats.gpu_utilization_percent);
    println!("    Memory efficiency: {:.2}", stats.memory_efficiency);
    // Neural RL epsilon field not available in current AdvancedStats
    // println!(
    //     "    Neural RL exploration rate: {:.3}",
    //     stats.neural_rl_epsilon
    // );

    println!("\n✅ Comprehensive stress tests completed!");
}

criterion_group!(
    benches,
    bench_large_graph_creation,
    bench_advanced_processors,
    bench_memory_usage,
    bench_adaptive_performance,
    bench_concurrent_processing,
    bench_configuration_comparison,
    bench_very_large_graphs,
    bench_memory_usage_analysis,
    bench_scaling_analysis
);

criterion_main!(benches);
