//! Criterion workload for the biobank-shape bernoulli marginal-slope
//! FLEX joint-Newton/Hv path. Multi-minute fit — run explicitly with:
//!
//! ```text
//! cargo bench --bench margslope_flex_biobank_hv
//! ```

#[path = "../../tests/test_support/margslope_flex_equivalence.rs"]
mod margslope_flex_equivalence;

use criterion::{Criterion, criterion_group, criterion_main};
use margslope_flex_equivalence::{
    DEFAULT_REPRO_N, build_biobank_shape_problem, cycle_capped_options, fit_problem,
};
use std::hint::black_box;
use std::time::Duration;

const BENCH_INNER_CYCLES: usize = 1;
#[cfg(target_os = "linux")]
const BENCH_MULTI_RHS_PROBE: usize = 4;
#[cfg(target_os = "linux")]
const BIOBANK_HVP_PRIMARY_R: usize = 20;
#[cfg(target_os = "linux")]
const BIOBANK_HVP_P_TOTAL: usize = 44;

fn bench_margslope_flex_biobank_cycle0(c: &mut Criterion) {
    gam::init_parallelism();
    let n = DEFAULT_REPRO_N;
    let inner_cycles = BENCH_INNER_CYCLES;
    #[cfg(target_os = "linux")]
    {
        let scratch = gam::gpu::bms_flex_row::bms_flex_row_hvp_multi_scratch_bytes_for_shape(
            n,
            BIOBANK_HVP_P_TOTAL,
            BENCH_MULTI_RHS_PROBE,
        )
        .expect("biobank-shape multi-RHS HVP scratch budget");
        let per_rhs_full_row_cache =
            (n * BIOBANK_HVP_PRIMARY_R * BIOBANK_HVP_PRIMARY_R * std::mem::size_of::<f64>()) as u64
                * BENCH_MULTI_RHS_PROBE as u64;
        eprintln!(
            "[MS-FLEX-BIOBANK-BENCH-HVP-MULTI-RHS] n={} p={} r={} rhs={} scratch_mib={:.3} full_row_cache_per_rhs_mib={:.3}",
            n,
            BIOBANK_HVP_P_TOTAL,
            BIOBANK_HVP_PRIMARY_R,
            BENCH_MULTI_RHS_PROBE,
            scratch as f64 / (1024.0 * 1024.0),
            per_rhs_full_row_cache as f64 / (1024.0 * 1024.0),
        );
    }
    let mut group = c.benchmark_group("margslope_flex_biobank_hv_pattern");
    group.sample_size(10);
    group.measurement_time(Duration::from_secs(30));
    group.bench_function(format!("n{n}_inner{inner_cycles}"), |b| {
        b.iter(|| {
            let problem = build_biobank_shape_problem(black_box(n));
            let (fit, timing) = fit_problem(problem, cycle_capped_options(inner_cycles))
                .expect("criterion biobank-shape margslope fit");
            eprintln!(
                "[MS-FLEX-BIOBANK-BENCH-ITER] n={} inner_max_cycles={} elapsed_s={:.3} outer_iters={} inner_cycles={} converged={} beta_len={}",
                n,
                inner_cycles,
                timing.elapsed.as_secs_f64(),
                timing.outer_iterations,
                timing.inner_cycles,
                timing.outer_converged,
                fit.fit.beta.len()
            );
            black_box(fit.fit.beta.len())
        });
    });
    group.finish();
}

criterion_group!(benches, bench_margslope_flex_biobank_cycle0);
criterion_main!(benches);
