use des::Des;
use des::cipher::block_padding::Pkcs7;
use des::cipher::{BlockDecryptMut, BlockEncryptMut, KeyInit};

use crate::Error;

pub(crate) fn des_ecb_base64_encrypt<T, E>(key: T, plaintext: E) -> Result<String, Error>
where
    T: AsRef<[u8]>,
    E: AsRef<[u8]>,
{
    let ciphertext =
        Des::new(key.as_ref().into()).encrypt_padded_vec_mut::<Pkcs7>(plaintext.as_ref());
    Ok(base64_simd::STANDARD.encode_to_string(ciphertext))
}

pub(crate) fn des_ecb_base64_decrypt<T, E>(key: T, ciphertext: E) -> Result<String, Error>
where
    T: AsRef<[u8]>,
    E: AsRef<[u8]>,
{
    let ciphertext = base64_simd::STANDARD.decode_to_vec(ciphertext)?;
    let plaintext = Des::new(key.as_ref().into()).decrypt_padded_vec_mut::<Pkcs7>(&ciphertext)?;
    Ok(simdutf8::basic::from_utf8(&plaintext)?.to_string())
}

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

    #[test]
    fn des() -> Result<(), Error> {
        let key = "abcdefgh";
        let data = "Hello World";

        let encrypted = des_ecb_base64_encrypt(key, data)?;
        let decrypted = des_ecb_base64_decrypt(key, encrypted)?;

        assert_eq!(decrypted, data);

        Ok(())
    }
}
