#![allow(
    clippy::assertions_on_constants,
    clippy::assertions_on_result_states,
    clippy::clone_on_copy,
    clippy::decimal_literal_representation,
    clippy::doc_markdown,
    clippy::empty_line_after_doc_comments,
    clippy::field_reassign_with_default,
    clippy::get_unwrap,
    clippy::identity_op,
    clippy::inconsistent_digit_grouping,
    clippy::indexing_slicing,
    clippy::integer_division,
    clippy::len_zero,
    clippy::let_underscore_must_use,
    clippy::manual_div_ceil,
    clippy::manual_let_else,
    clippy::manual_range_contains,
    clippy::modulo_arithmetic,
    clippy::needless_range_loop,
    clippy::non_ascii_literal,
    clippy::redundant_clone,
    clippy::shadow_reuse,
    clippy::shadow_same,
    clippy::shadow_unrelated,
    clippy::single_match_else,
    clippy::str_to_string,
    clippy::string_slice,
    clippy::tests_outside_test_module,
    clippy::too_many_lines,
    clippy::unnecessary_wraps,
    clippy::unseparated_literal_suffix,
    clippy::use_debug,
    clippy::useless_vec,
    clippy::wildcard_enum_match_arm,
    clippy::else_if_without_else,
    clippy::expect_used,
    clippy::missing_const_for_fn,
    clippy::similar_names,
    clippy::type_complexity,
    clippy::collapsible_else_if,
    clippy::doc_lazy_continuation,
    clippy::items_after_test_module,
    clippy::map_clone,
    clippy::multiple_unsafe_ops_per_block,
    clippy::unwrap_or_default,
    clippy::assign_op_pattern,
    clippy::needless_borrow,
    clippy::println_empty_string,
    clippy::unnecessary_cast,
    clippy::used_underscore_binding,
    clippy::create_dir,
    clippy::implicit_saturating_sub,
    clippy::exit,
    clippy::expect_fun_call,
    clippy::too_many_arguments,
    clippy::unnecessary_map_or,
    clippy::unwrap_used,
    dead_code,
    unused_imports,
    unused_variables,
    clippy::cloned_ref_to_slice_refs,
    clippy::neg_multiply,
    clippy::while_let_loop,
    clippy::bool_assert_comparison,
    clippy::excessive_precision,
    clippy::trivially_copy_pass_by_ref,
    clippy::op_ref,
    clippy::redundant_closure,
    clippy::unnecessary_lazy_evaluations,
    clippy::if_then_some_else_none,
    clippy::unnecessary_to_owned,
    clippy::single_component_path_imports,
)]
//! Performance Benchmark for Feature Extraction (Production)
//!
//! Benchmarks the production feature extraction pipeline to validate
//! performance targets are met.
//!
//! ## Usage
//!
//! ```bash
//! cargo bench --bench bench_feature_extraction
//! ```

use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use ml::features::config::FeatureConfig;

/// Generate synthetic close prices for benchmarking
fn generate_prices(count: usize) -> Vec<f64> {
    let mut prices = Vec::with_capacity(count);
    let mut price = 4500.0;

    for i in 0..count {
        let trend = (i as f64 / 100.0).sin() * 5.0;
        let random_walk = ((i * 7919) % 100) as f64 / 50.0 - 1.0;
        price += trend + random_walk * 2.0;
        prices.push(price);
    }

    prices
}

/// Synthetic feature extraction for benchmarking throughput
fn extract_features_bench(idx: usize, feature_count: usize) -> Vec<f64> {
    let mut features = Vec::with_capacity(feature_count);

    for i in 0..feature_count {
        let base_value = ((i + idx) as f64 * 0.01).sin();
        let noise = ((i * idx) % 100) as f64 / 100.0 - 0.5;
        features.push(base_value + noise * 0.1);
    }

    features
}

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

    group.bench_function("baseline_46_features", |b| {
        b.iter(|| black_box(extract_features_bench(black_box(0), 46)));
    });

    group.bench_function("production_54_features", |b| {
        b.iter(|| black_box(extract_features_bench(black_box(0), 54)));
    });

    group.finish();
}

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

    for batch_size in [100, 500, 1000, 2000].iter() {
        let prices = generate_prices(*batch_size);

        group.throughput(Throughput::Elements(*batch_size as u64));
        group.bench_with_input(
            BenchmarkId::new("baseline_46", batch_size),
            &prices,
            |b, prices| {
                b.iter(|| {
                    let all: Vec<_> = prices
                        .iter()
                        .enumerate()
                        .map(|(idx, _)| extract_features_bench(idx, 46))
                        .collect();
                    black_box(all);
                });
            },
        );

        group.throughput(Throughput::Elements(*batch_size as u64));
        group.bench_with_input(
            BenchmarkId::new("production_54", batch_size),
            &prices,
            |b, prices| {
                b.iter(|| {
                    let all: Vec<_> = prices
                        .iter()
                        .enumerate()
                        .map(|(idx, _)| extract_features_bench(idx, 54))
                        .collect();
                    black_box(all);
                });
            },
        );
    }

    group.finish();
}

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

    group.bench_function("config_creation", |b| {
        b.iter(|| black_box(FeatureConfig::default()));
    });

    group.bench_function("feature_count", |b| {
        let config = FeatureConfig::default();
        b.iter(|| black_box(config.feature_count()));
    });

    group.bench_function("feature_indices", |b| {
        let config = FeatureConfig::default();
        b.iter(|| black_box(config.feature_indices()));
    });

    group.finish();
}

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

    group.bench_function("vec_alloc_54", |b| {
        b.iter(|| black_box(Vec::<f64>::with_capacity(54)));
    });

    group.bench_function("batch_1000_alloc_54", |b| {
        b.iter(|| {
            let all: Vec<_> = (0..1000).map(|_| Vec::<f64>::with_capacity(54)).collect();
            black_box(all);
        });
    });

    group.finish();
}

criterion_group!(
    benches,
    bench_single_bar_extraction,
    bench_batch_extraction,
    bench_config_overhead,
    bench_memory_allocation,
);

criterion_main!(benches);
