#![cfg(feature = "v4_local")]
use std::marker::PhantomData;
use std::ops::Deref;
use blake2::digest::consts::U56;
use blake2::{Blake2bMac, digest::Update};
use blake2::digest::FixedOutput;
use digest::KeyInit;
use chacha20::{XNonce, Key};
use crate::core::common::EncryptionKey;
use crate::core::{Local, PasetoError, PasetoSymmetricKey, V4};

impl EncryptionKey<V4, Local> {
    pub(crate) fn try_from(message: &crate::core::Key<53>, key: &PasetoSymmetricKey<V4, Local>) -> Result<Self, PasetoError> {
        let mut context = Blake2bMac::<U56>::new_from_slice(key.as_ref())?;
        context.update(message.as_ref());
        let binding = context.finalize_fixed();
        let context = binding.to_vec();

        // Use safe slicing with bounds checking
        let key_bytes = context.get(..32).ok_or(PasetoError::IncorrectSize)?.to_vec();
        let nonce = context.get(32..56).ok_or(PasetoError::IncorrectSize)?.to_vec();

        Ok(Self {
            key: key_bytes,
            nonce,
            version: PhantomData,
            purpose: PhantomData,
        })
    }
    pub(crate) fn counter_nonce(&self) -> &XNonce {
        XNonce::from_slice(&self.nonce)
    }
}

impl AsRef<Key> for EncryptionKey<V4, Local> {
    fn as_ref(&self) -> &Key {
        Key::from_slice(&self.key)
    }
}

impl Deref for EncryptionKey<V4, Local> {
    type Target = [u8];

    fn deref(&self) -> &Self::Target {
        Key::from_slice(&self.key)
    }
}