//! Encrypted DID identity backup for onboarding.
//! Uses Argon2 for key derivation and ChaCha20-Poly1305 for encryption.

use anyhow::{Context, Result};
use argon2::Argon2;
use base64::{engine::general_purpose::STANDARD as BASE64, Engine};
use chacha20poly1305::aead::{Aead, KeyInit};
use rand::RngCore;
use std::path::Path;
use tokio::fs;

const BACKUP_VERSION: u32 = 1;
const SALT_LEN: usize = 16;
const NONCE_LEN: usize = 12;
const KEY_LEN: usize = 32;

/// Create an encrypted backup of the node identity key.
/// Returns JSON-serializable backup metadata + encrypted blob (base64).
pub async fn create_encrypted_backup(
    identity_dir: &Path,
    passphrase: &str,
    did: &str,
    pubkey_hex: &str,
) -> Result<serde_json::Value> {
    let key_path = identity_dir.join("node_key");
    let key_bytes = fs::read(&key_path)
        .await
        .context("Failed to read node key")?;
    if key_bytes.len() != 32 {
        anyhow::bail!("Invalid node key length");
    }

    let mut salt = [0u8; SALT_LEN];
    let mut nonce = [0u8; NONCE_LEN];
    rand::rngs::OsRng.fill_bytes(&mut salt);
    rand::rngs::OsRng.fill_bytes(&mut nonce);

    let argon2 = Argon2::default();
    let mut key = [0u8; KEY_LEN];
    argon2
        .hash_password_into(passphrase.as_bytes(), &salt, &mut key)
        .map_err(|e| anyhow::anyhow!("Argon2 key derivation failed: {}", e))?;

    let cipher = chacha20poly1305::ChaCha20Poly1305::new_from_slice(&key)
        .map_err(|e| anyhow::anyhow!("Cipher init: {}", e))?;
    let ciphertext = cipher
        .encrypt(
            chacha20poly1305::aead::generic_array::GenericArray::from_slice(&nonce),
            key_bytes.as_ref(),
        )
        .map_err(|e| anyhow::anyhow!("Encryption failed: {}", e))?;

    let mut blob = Vec::with_capacity(SALT_LEN + NONCE_LEN + ciphertext.len());
    blob.extend_from_slice(&salt);
    blob.extend_from_slice(&nonce);
    blob.extend_from_slice(&ciphertext);
    let blob_b64 = BASE64.encode(&blob);

    Ok(serde_json::json!({
        "version": BACKUP_VERSION,
        "did": did,
        "pubkey": pubkey_hex,
        "kid": format!("{}#key-1", did),
        "encrypted": true,
        "blob": blob_b64,
        "timestamp": chrono::Utc::now().to_rfc3339(),
    }))
}
