//! Field history end-to-end: capture on update, prune by retention policy,
//! survive encrypt/decrypt round-trip.

use relicario_core::{
    Field, FieldValue, HistoryRetention, Item, ItemCore, Section,
    crypto::KdfParams,
    derive_master_key, decrypt_item, encrypt_item,
};
use relicario_core::item_types::LoginCore;
use zeroize::Zeroizing;

fn key() -> Zeroizing<[u8; 32]> {
    derive_master_key(b"x", &[0u8; 32], &[0u8; 32], &KdfParams { argon2_m: 256, argon2_t: 1, argon2_p: 1 }).unwrap()
}

#[test]
fn password_field_history_captured_on_update() {
    let mut item = Item::new("login".into(), ItemCore::Login(LoginCore::default()));
    let f = Field::new("password".into(), FieldValue::Password(Zeroizing::new("v0".into())));
    let fid = f.id.clone();
    item.sections.push(Section { name: None, fields: vec![f] });

    item.set_field_value(&fid, FieldValue::Password(Zeroizing::new("v1".into()))).unwrap();
    item.set_field_value(&fid, FieldValue::Password(Zeroizing::new("v2".into()))).unwrap();
    item.set_field_value(&fid, FieldValue::Password(Zeroizing::new("v3".into()))).unwrap();

    let hist = item.field_history.get(&fid).expect("history exists");
    assert_eq!(hist.len(), 3);
    assert_eq!(hist[0].value.as_str(), "v0");
    assert_eq!(hist[2].value.as_str(), "v2");
}

#[test]
fn prune_last_n_keeps_most_recent() {
    let mut item = Item::new("x".into(), ItemCore::Login(LoginCore::default()));
    let f = Field::new("p".into(), FieldValue::Password(Zeroizing::new("v0".into())));
    let fid = f.id.clone();
    item.sections.push(Section { name: None, fields: vec![f] });
    for i in 1..=10 {
        item.set_field_value(&fid, FieldValue::Password(Zeroizing::new(format!("v{i}")))).unwrap();
    }
    item.prune_history(&HistoryRetention::LastN(3), 0);
    let hist = &item.field_history[&fid];
    assert_eq!(hist.len(), 3);
    // Most recent 3: v7, v8, v9 (v10's predecessor v9 was the latest captured)
    assert!(hist.last().unwrap().value.as_str().starts_with('v'));
}

#[test]
fn history_survives_encrypt_decrypt() {
    let mut item = Item::new("x".into(), ItemCore::Login(LoginCore::default()));
    let f = Field::new("p".into(), FieldValue::Password(Zeroizing::new("v0".into())));
    let fid = f.id.clone();
    item.sections.push(Section { name: None, fields: vec![f] });
    item.set_field_value(&fid, FieldValue::Password(Zeroizing::new("v1".into()))).unwrap();

    let blob = encrypt_item(&item, &key()).unwrap();
    let decoded = decrypt_item(&blob, &key()).unwrap();

    let hist = decoded.field_history.get(&fid).expect("history survived");
    assert_eq!(hist.len(), 1);
    assert_eq!(hist[0].value.as_str(), "v0");
}
