use crate::crypto::EncryptionPubKey;
use crate::error::Result;
use hkdf::Hkdf;
use sha2::Sha256;

/// Derives a deterministic 32-byte Ed25519 seed and 32-byte X25519 seed from a seed string.
/// Uses HKDF-SHA256 with a fixed salt for proper key derivation.
///
/// WARNING: This is for offline development/testing only. Production deployments must
/// resolve identity from the Hippius chain's AccountProfile pallet.
pub fn derive_keys(seed: &str) -> ([u8; 32], [u8; 32]) {
    let hk = Hkdf::<Sha256>::new(Some(b"hermes-identity-v1"), seed.as_bytes());

    let mut node_id_bytes = [0u8; 32];
    hk.expand(b"hermes-node-id-key", &mut node_id_bytes)
        .expect("32 bytes is a valid HKDF-SHA256 output length");

    let mut encrypt_bytes = [0u8; 32];
    hk.expand(b"hermes-encrypt-key", &mut encrypt_bytes)
        .expect("32 bytes is a valid HKDF-SHA256 output length");

    (node_id_bytes, encrypt_bytes)
}

/// A mapped profile for an external Hippius node.
#[derive(Clone, Debug)]
pub struct AccountProfile {
    pub node_id: Vec<u8>,
    pub encryption_key: EncryptionPubKey,
}

/// Resolves an SS58 address into an AccountProfile.
///
/// TODO: Query the Hippius chain's AccountProfile pallet via subxt once the chain is live
/// and SCALE decoding for the pallet's storage is implemented. Currently uses deterministic
/// key derivation from the SS58 string for offline development.
pub async fn resolve_profile(_rpc_url: &str, ss58: &str) -> Result<AccountProfile> {
    let (node_sec, enc_sec) = derive_keys(ss58);

    let node_pub = iroh::SecretKey::from_bytes(&node_sec)
        .public()
        .as_bytes()
        .to_vec();

    let static_sec = x25519_dalek::StaticSecret::from(enc_sec);
    let enc_pub = x25519_dalek::PublicKey::from(&static_sec).to_bytes();

    Ok(AccountProfile {
        node_id: node_pub,
        encryption_key: EncryptionPubKey(enc_pub.to_vec()),
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_derive_keys_deterministic() {
        let (node1, enc1) = derive_keys("test-wallet");
        let (node2, enc2) = derive_keys("test-wallet");
        assert_eq!(node1, node2);
        assert_eq!(enc1, enc2);
    }

    #[test]
    fn test_derive_keys_different_seeds_differ() {
        let (node1, enc1) = derive_keys("wallet-a");
        let (node2, enc2) = derive_keys("wallet-b");
        assert_ne!(node1, node2);
        assert_ne!(enc1, enc2);
    }

    #[test]
    fn test_derive_keys_node_and_encrypt_differ() {
        let (node, enc) = derive_keys("same-seed");
        assert_ne!(node, enc);
    }
}
