use aes_gcm::aead::Aead;
use aes_gcm::{Aes256Gcm, KeyInit, Nonce};
use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
use rand::RngCore;

const CIPHER_VERSION: u8 = 0x01;

/// AES-256-GCM 加密。输出格式: Base64(0x01 || nonce[12] || ciphertext + tag)
pub fn encrypt(key: &[u8; 32], plaintext: &str) -> Result<String, String> {
    let cipher = Aes256Gcm::new_from_slice(key).map_err(|e| e.to_string())?;
    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| e.to_string())?;
    let mut combined = vec![CIPHER_VERSION];
    combined.extend_from_slice(&nonce_bytes);
    combined.extend_from_slice(&ciphertext);
    Ok(BASE64.encode(&combined))
}

/// AES-256-GCM 解密。支持 v1 格式: Base64(0x01 || nonce[12] || ciphertext + tag)
/// 兼容旧格式: Base64(nonce[12] || ciphertext + tag)
pub fn decrypt(key: &[u8; 32], encoded: &str) -> Result<String, String> {
    let bytes = BASE64.decode(encoded).map_err(|e| e.to_string())?;
    if bytes.len() < 13 {
        return Err("ciphertext too short".into());
    }

    let (nonce_bytes, ciphertext) = if bytes[0] == CIPHER_VERSION {
        // v1: version(1) + nonce(12) + ciphertext
        if bytes.len() < 14 {
            return Err("v1 ciphertext too short".into());
        }
        (&bytes[1..13], &bytes[13..])
    } else {
        // 旧格式: nonce(12) + ciphertext（向后兼容）
        (&bytes[0..12], &bytes[12..])
    };

    let cipher = Aes256Gcm::new_from_slice(key).map_err(|e| e.to_string())?;
    let nonce = Nonce::from_slice(nonce_bytes);
    let plaintext = cipher
        .decrypt(nonce, ciphertext)
        .map_err(|e| e.to_string())?;
    String::from_utf8(plaintext).map_err(|e| e.to_string())
}
