#![allow(clippy::unwrap_used)]
//! Benchmark: Identity keypair operations, sealed sender, and message padding.
//!
//! Covers:
//! - [`IdentityKeypair`] generation, signing, and signature verification
//! - Sealed sender `seal` / `unseal` (Ed25519 sign + verify overhead)
//! - Message padding `pad` / `unpad` at various payload sizes

use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};

use quicproquo_core::{compute_safety_number, IdentityKeypair, padding};

// ── Identity keypair benchmarks ──────────────────────────────────────────────

fn bench_identity_keygen(c: &mut Criterion) {
    c.bench_function("identity_keygen", |b| {
        b.iter(|| black_box(IdentityKeypair::generate()));
    });
}

fn bench_identity_sign(c: &mut Criterion) {
    let identity = IdentityKeypair::generate();
    let payload = b"benchmark signing payload -- 32+ bytes of realistic data here";

    c.bench_function("identity_sign", |b| {
        b.iter(|| black_box(identity.sign_raw(black_box(payload))));
    });
}

fn bench_identity_verify(c: &mut Criterion) {
    let identity = IdentityKeypair::generate();
    let payload = b"benchmark signing payload -- 32+ bytes of realistic data here";
    let sig = identity.sign_raw(payload);
    let pk = identity.public_key_bytes();

    c.bench_function("identity_verify", |b| {
        b.iter(|| {
            IdentityKeypair::verify_raw(
                black_box(&pk),
                black_box(payload),
                black_box(&sig),
            )
            .unwrap();
        });
    });
}

// ── Sealed sender benchmarks ─────────────────────────────────────────────────

fn bench_sealed_sender(c: &mut Criterion) {
    use quicproquo_core::sealed_sender::{seal, unseal};

    let sizes: &[(&str, usize)] = &[
        ("32B", 32),
        ("256B", 256),
        ("1KB", 1024),
        ("4KB", 4096),
    ];

    let identity = IdentityKeypair::generate();

    let mut group = c.benchmark_group("sealed_sender_seal");
    for (label, size) in sizes {
        let payload = vec![0xABu8; *size];
        group.bench_with_input(
            BenchmarkId::from_parameter(label),
            &payload,
            |b, payload| {
                b.iter(|| black_box(seal(black_box(&identity), black_box(payload))));
            },
        );
    }
    group.finish();

    let mut group = c.benchmark_group("sealed_sender_unseal");
    for (label, size) in sizes {
        let payload = vec![0xABu8; *size];
        let sealed = seal(&identity, &payload);
        group.bench_with_input(
            BenchmarkId::from_parameter(label),
            &sealed,
            |b, sealed| {
                b.iter(|| black_box(unseal(black_box(sealed)).unwrap()));
            },
        );
    }
    group.finish();
}

// ── Message padding benchmarks ────────────────────────────────────────────────

fn bench_padding(c: &mut Criterion) {
    // Representative sizes: one per bucket + oversized
    let sizes: &[(&str, usize)] = &[
        ("50B", 50),       // → 256 bucket
        ("512B", 512),     // → 1024 bucket
        ("2KB", 2048),     // → 4096 bucket
        ("8KB", 8192),     // → 16384 bucket
        ("20KB", 20480),   // → 32768 (oversized)
    ];

    let mut group = c.benchmark_group("padding_pad");
    for (label, size) in sizes {
        let payload = vec![0xABu8; *size];
        group.bench_with_input(
            BenchmarkId::from_parameter(label),
            &payload,
            |b, payload| {
                b.iter(|| black_box(padding::pad(black_box(payload))));
            },
        );
    }
    group.finish();

    let mut group = c.benchmark_group("padding_unpad");
    for (label, size) in sizes {
        let payload = vec![0xABu8; *size];
        let padded = padding::pad(&payload);
        group.bench_with_input(
            BenchmarkId::from_parameter(label),
            &padded,
            |b, padded| {
                b.iter(|| black_box(padding::unpad(black_box(padded)).unwrap()));
            },
        );
    }
    group.finish();
}

// ── Safety number benchmarks ─────────────────────────────────────────────────

fn bench_safety_number(c: &mut Criterion) {
    let key_a = [0x1au8; 32];
    let key_b = [0x2bu8; 32];

    c.bench_function("safety_number", |b| {
        b.iter(|| black_box(compute_safety_number(black_box(&key_a), black_box(&key_b))));
    });
}

criterion_group!(
    benches,
    bench_identity_keygen,
    bench_identity_sign,
    bench_identity_verify,
    bench_sealed_sender,
    bench_padding,
    bench_safety_number,
);
criterion_main!(benches);
