// AES-256-GCM kryptering for API-nøkler
//
// Master key leses fra SYNOPS_MASTER_KEY env-variabel (32 bytes, hex-kodet).
// Hver kryptert verdi inneholder nonce (12 bytes) + ciphertext.

use aes_gcm::{
    aead::{Aead, KeyInit},
    Aes256Gcm, Nonce,
};
use rand::RngCore;

/// Hent master key fra env. Returnerer 32 bytes.
pub fn master_key() -> Result<[u8; 32], String> {
    let hex_key = std::env::var("SYNOPS_MASTER_KEY")
        .map_err(|_| "SYNOPS_MASTER_KEY er ikke satt".to_string())?;

    let bytes = hex::decode(hex_key.trim())
        .map_err(|e| format!("SYNOPS_MASTER_KEY er ikke gyldig hex: {e}"))?;

    if bytes.len() != 32 {
        return Err(format!(
            "SYNOPS_MASTER_KEY må være 32 bytes (64 hex-tegn), fikk {}",
            bytes.len()
        ));
    }

    let mut key = [0u8; 32];
    key.copy_from_slice(&bytes);
    Ok(key)
}

/// Krypter plaintext med AES-256-GCM. Returnerer nonce (12 bytes) || ciphertext.
pub fn encrypt(plaintext: &str, key: &[u8; 32]) -> Result<Vec<u8>, String> {
    let cipher = Aes256Gcm::new(key.into());

    let mut nonce_bytes = [0u8; 12];
    rand::thread_rng().fill_bytes(&mut nonce_bytes);
    let nonce = Nonce::from_slice(&nonce_bytes);

    let ciphertext = cipher
        .encrypt(nonce, plaintext.as_bytes())
        .map_err(|e| format!("Krypteringsfeil: {e}"))?;

    let mut result = Vec::with_capacity(12 + ciphertext.len());
    result.extend_from_slice(&nonce_bytes);
    result.extend_from_slice(&ciphertext);
    Ok(result)
}

/// Dekrypter data (nonce || ciphertext) med AES-256-GCM.
pub fn decrypt(data: &[u8], key: &[u8; 32]) -> Result<String, String> {
    if data.len() < 13 {
        return Err("Kryptert data er for kort".to_string());
    }

    let cipher = Aes256Gcm::new(key.into());
    let nonce = Nonce::from_slice(&data[..12]);
    let ciphertext = &data[12..];

    let plaintext = cipher
        .decrypt(nonce, ciphertext)
        .map_err(|e| format!("Dekrypteringsfeil: {e}"))?;

    String::from_utf8(plaintext).map_err(|e| format!("Ugyldig UTF-8: {e}"))
}

/// Lag key_hint: siste 4 tegn av nøkkelen.
pub fn key_hint(key: &str) -> String {
    if key.len() >= 4 {
        format!("...{}", &key[key.len() - 4..])
    } else {
        "****".to_string()
    }
}

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

    #[test]
    fn test_roundtrip() {
        let key = [0x42u8; 32];
        let plaintext = "sk-or-v1-test-key-12345";
        let encrypted = encrypt(plaintext, &key).unwrap();
        let decrypted = decrypt(&encrypted, &key).unwrap();
        assert_eq!(decrypted, plaintext);
    }

    #[test]
    fn test_key_hint() {
        assert_eq!(key_hint("sk-or-v1-abc123c08b"), "...c08b");
        assert_eq!(key_hint("ab"), "****");
    }
}
