//! Attachment encrypt/decrypt + content-addressed AID + cap enforcement.

use relicario_core::{
    AttachmentId, RelicarioError,
    crypto::KdfParams,
    decrypt_attachment, derive_master_key, encrypt_attachment,
};
use zeroize::Zeroizing;

fn fast_params() -> KdfParams { KdfParams { argon2_m: 256, argon2_t: 1, argon2_p: 1 } }

fn make_key() -> Zeroizing<[u8; 32]> {
    derive_master_key(b"x", &[0u8; 32], &[0u8; 32], &fast_params()).unwrap()
}

#[test]
fn attachment_round_trip_5kb() {
    let plaintext: Vec<u8> = (0..5000u32).map(|i| (i & 0xff) as u8).collect();
    let key = make_key();
    let enc = encrypt_attachment(&plaintext, &key, 10 * 1024 * 1024).unwrap();
    assert_eq!(enc.id, AttachmentId::from_plaintext(&plaintext));

    let dec = decrypt_attachment(&enc.bytes, &key).unwrap();
    assert_eq!(&*dec, &plaintext);
}

#[test]
fn identical_plaintexts_yield_identical_aids() {
    let plaintext = b"hello world";
    let key = make_key();
    let a = encrypt_attachment(plaintext, &key, 1024).unwrap();
    let b = encrypt_attachment(plaintext, &key, 1024).unwrap();
    assert_eq!(a.id, b.id);
    // (Bytes will differ because nonce is random per-encryption — that's expected.)
}

#[test]
fn cap_enforcement_at_exact_max() {
    let plaintext = vec![0u8; 1024];
    let key = make_key();
    // Exactly at max — should pass
    let _ = encrypt_attachment(&plaintext, &key, 1024).unwrap();
    // One byte over — should fail
    let err = encrypt_attachment(&plaintext, &key, 1023);
    match err {
        Err(RelicarioError::AttachmentTooLarge { size, max }) => {
            assert_eq!(size, 1024);
            assert_eq!(max, 1023);
        }
        other => panic!("expected AttachmentTooLarge, got {other:?}"),
    }
}
