// Licensed under the Apache-2.0 license

use core::fmt::Debug;
use zerocopy::{FromBytes, IntoBytes};

/// Marker trait for all cipher modes.
pub trait CipherMode: core::fmt::Debug + Clone + Copy {}

/// Marker trait for block cipher modes (e.g., CBC, CTR).
pub trait BlockCipherMode: CipherMode {}

/// Marker trait for AEAD modes (e.g., GCM, CCM).
pub trait AeadCipherMode: CipherMode {}

/// Marker trait for stream cipher modes (e.g., ChaCha20).
pub trait StreamCipherMode: CipherMode {}

/// Common error kinds for symmetric cipher operations.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[non_exhaustive]
pub enum ErrorKind {
    /// Failed to initialize the cipher context.
    InitializationError,

    /// General hardware failure during cipher operation.
    HardwareFailure,

    /// Insufficient permissions to access hardware or perform the operation.
    PermissionDenied,

    /// The cipher context is in an invalid or uninitialized state.
    InvalidState,

    /// The input data is invalid (e.g., wrong length or format).
    InvalidInput,

    /// The specified algorithm or mode is not supported.
    UnsupportedAlgorithm,

    /// Key or IV is invalid or missing.
    KeyError,
}

/// Trait for converting implementation-specific errors into a generic [`ErrorKind`].
pub trait Error: Debug {
    /// Returns a generic error kind corresponding to the specific error.
    fn kind(&self) -> ErrorKind;
}

/// Trait for associating a type with an error type.
pub trait ErrorType {
    /// The associated error type.
    type Error: Error;
}

/// Trait for symmetric cipher algorithms.
///
/// This trait defines the core types and constraints for symmetric cipher implementations.
/// All types must support zero-copy serialization via the `zerocopy` crate traits,
/// enabling efficient operation with both software and hardware implementations.
///
/// # Zero-Copy Requirements
///
/// The `FromBytes` and `IntoBytes` trait bounds ensure that:
/// - Types can be safely constructed from byte arrays without validation
/// - Types can be converted to byte arrays for hardware or network transmission
/// - No unnecessary copying occurs during cryptographic operations
/// - Memory layout is well-defined and predictable
///
/// # Security Considerations
///
/// - Key types should implement `Zeroize` for secure memory cleanup
/// - Plaintext and ciphertext types should be handled securely in memory
/// - Consider using `secrecy` crate for sensitive data protection
///
/// # Example Implementation
///
/// ```ignore
/// impl SymmetricCipher for MyAesCipher {
///     type Key = [u8; 32];           // AES-256 key
///     type Nonce = [u8; 16];         // 128-bit nonce/IV
///     type PlainText = [u8; 64];     // Fixed-size plaintext buffer
///     type CipherText = [u8; 80];    // Fixed-size ciphertext buffer (with padding)
///     type Error = CryptoError;
/// }
/// ```
pub trait SymmetricCipher: ErrorType {
    /// The cryptographic key type.
    ///
    /// This type represents the secret key material used for encryption and decryption.
    /// The key can be provided through various mechanisms including software keys,
    /// key vault references, or hardware-managed keys.
    ///
    /// # Security Requirements
    ///
    /// - Should implement `Zeroize` for secure memory cleanup when stored in software
    /// - May reference keys stored in secure hardware or key vaults
    /// - Size should match the algorithm's key requirements (e.g., 32 bytes for AES-256)
    /// - Consider using masked key shares for side-channel protection in hardware
    ///
    /// # Key Sources
    ///
    /// - **Software Keys**: `[u8; 32]` for AES-256, `[u8; 16]` for AES-128
    /// - **Key Vault References**: `KeyVaultHandle`, `KeyId`, or similar abstract types
    /// - **Hardware Keys**: Sideloaded keys from key managers or crypto coprocessors
    /// - **Masked Keys**: Split key shares for side-channel attack resistance
    ///
    /// # Common Types
    ///
    /// - `[u8; 32]` for AES-256, ChaCha20 (software keys)
    /// - `[u8; 16]` for AES-128 (software keys)
    /// - `KeyVaultId` for key vault managed keys
    /// - `HardwareKeyHandle` for hardware-managed keys
    /// - Custom types for hardware-specific key formats or masked implementations
    type Key;

    /// The nonce or initialization vector type.
    ///
    /// This type represents the nonce (number used once) or initialization vector
    /// for the cipher operation. It must be unique for each encryption with the same key.
    ///
    /// # Security Requirements
    ///
    /// - Must never be reused with the same key (critical for CTR mode and stream ciphers)
    /// - Should be generated using cryptographically secure random number generation
    /// - Size must match the algorithm's requirements
    ///
    /// # Common Types
    ///
    /// - `[u8; 16]` for AES-CTR, AES-CBC
    /// - `[u8; 12]` for ChaCha20, AES-GCM
    /// - `[u8; 8]` for some legacy ciphers
    type Nonce: FromBytes + IntoBytes;

    /// The plaintext data type.
    ///
    /// This type represents the unencrypted data input to the cipher.
    /// It must support zero-copy operations for efficient processing.
    ///
    /// # Performance Considerations
    ///
    /// - Should minimize copying and allocation
    /// - Consider using slices or references where possible
    /// - Support both fixed-size and variable-length data
    ///
    /// # Common Types
    ///
    /// - `&[u8]` for read-only operations
    /// - `[u8; N]` for fixed-size owned data
    /// - Custom container types for variable-length data
    type PlainText: FromBytes + IntoBytes;

    /// The ciphertext data type.
    ///
    /// This type represents the encrypted data output from the cipher.
    /// It must support zero-copy operations for efficient processing.
    ///
    /// # Size Considerations
    ///
    /// - For stream ciphers: same size as plaintext
    /// - For block ciphers with padding: may be larger than plaintext
    /// - For AEAD modes: includes authentication tag
    ///
    /// # Common Types
    ///
    /// - `[u8; N]` for fixed-size encrypted blocks
    /// - Custom container types for variable-length encrypted data
    /// - Types that include metadata or authentication tags
    type CipherText: FromBytes + IntoBytes;
}

/// Trait for initializing a cipher with a specific mode.
pub trait CipherInit<M: CipherMode>: SymmetricCipher {
    /// The operational context for performing encryption/decryption.
    type CipherContext<'a>: CipherOp<M>
    where
        Self: 'a;

    /// Initializes the cipher with the given parameters.
    ///
    /// # Parameters
    ///
    /// - `key`: A reference to the key used for the cipher.
    /// - `nonce`: A reference to the nonce or IV used for the cipher.
    /// - `mode`: The cipher mode to use.
    ///
    /// # Returns
    ///
    /// A result containing the operational context or an error.
    fn init<'a>(
        &'a mut self,
        key: &Self::Key,
        nonce: &Self::Nonce,
        mode: M,
    ) -> Result<Self::CipherContext<'a>, Self::Error>;
}

/// Trait for basic encryption/decryption operations.
pub trait CipherOp<M: CipherMode>: SymmetricCipher + ErrorType {
    /// Encrypts the given plaintext.
    ///
    /// # Parameters
    ///
    /// - `plaintext`: The data to encrypt.
    ///
    /// # Returns
    ///
    /// A result containing the ciphertext or an error.
    fn encrypt(&mut self, plaintext: Self::PlainText) -> Result<Self::CipherText, Self::Error>;

    /// Decrypts the given ciphertext.
    ///
    /// # Parameters
    ///
    /// - `ciphertext`: The data to decrypt.
    ///
    /// # Returns
    ///
    /// A result containing the plaintext or an error.
    fn decrypt(&mut self, ciphertext: Self::CipherText) -> Result<Self::PlainText, Self::Error>;
}

/// Optional trait for cipher contexts that support resetting to their initial state.
pub trait ResettableCipherOp: ErrorType {
    /// Resets the cipher context.
    ///
    /// # Returns
    ///
    /// A result indicating success or failure.
    fn reset(&mut self) -> Result<(), Self::Error>;
}

/// Optional trait for cipher contexts that support rekeying.
pub trait CipherRekey<K>: ErrorType {
    /// Rekeys the cipher context with a new key.
    ///
    /// # Parameters
    ///
    /// - `new_key`: A reference to the new key.
    ///
    /// # Returns
    ///
    /// A result indicating success or failure.
    fn rekey(&mut self, new_key: &K) -> Result<(), Self::Error>;
}

/// Error type for block-aligned container operations.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BlockAlignedError {
    /// The container has reached its maximum capacity.
    CapacityExceeded,
    /// The input data is too large for the container.
    DataTooLarge,
}

impl core::fmt::Display for BlockAlignedError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Self::CapacityExceeded => write!(f, "block container has reached maximum capacity"),
            Self::DataTooLarge => write!(f, "input data exceeds container capacity"),
        }
    }
}

/// Block-aligned data container that guarantees correct block sizing at compile time.
///
/// This type wrapper ensures that data is always properly aligned to block boundaries,
/// preventing runtime errors from incorrectly sized cipher inputs. It uses fixed-size
/// arrays suitable for embedded systems without heap allocation.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BlockAligned<const BLOCK_SIZE: usize, const MAX_BLOCKS: usize> {
    blocks: [[u8; BLOCK_SIZE]; MAX_BLOCKS],
    block_count: usize,
}

impl<const BLOCK_SIZE: usize, const MAX_BLOCKS: usize> Default
    for BlockAligned<BLOCK_SIZE, MAX_BLOCKS>
{
    fn default() -> Self {
        Self::new()
    }
}

impl<const BLOCK_SIZE: usize, const MAX_BLOCKS: usize> BlockAligned<BLOCK_SIZE, MAX_BLOCKS> {
    /// Create a new empty block-aligned container
    pub const fn new() -> Self {
        Self {
            blocks: [[0u8; BLOCK_SIZE]; MAX_BLOCKS],
            block_count: 0,
        }
    }

    /// Create block-aligned data from a byte slice, padding if necessary.
    ///
    /// # Parameters
    /// - `data`: Input data that will be padded to block boundaries
    /// - `padding_byte`: Byte value to use for padding (typically 0)
    ///
    /// # Returns
    /// - `Ok(BlockAligned)`: Successfully created block-aligned data
    /// - `Err(BlockAlignedError)`: Input data exceeds maximum capacity
    ///
    /// # Errors
    /// Returns an error if the input data would require more than `MAX_BLOCKS` blocks.
    pub fn from_slice_padded(data: &[u8], padding_byte: u8) -> Result<Self, BlockAlignedError> {
        let required_blocks = data.len().div_ceil(BLOCK_SIZE);

        if required_blocks > MAX_BLOCKS {
            return Err(BlockAlignedError::DataTooLarge);
        }

        let mut result = Self::new();
        result.block_count = required_blocks;

        // Fill complete blocks
        for (i, chunk) in data.chunks(BLOCK_SIZE).enumerate() {
            let block = result
                .blocks
                .get_mut(i)
                .ok_or(BlockAlignedError::DataTooLarge)?;
            block.fill(padding_byte);
            let slice = block
                .get_mut(..chunk.len())
                .ok_or(BlockAlignedError::DataTooLarge)?;
            slice.copy_from_slice(chunk);
        }

        Ok(result)
    }

    /// Add a complete block to the container.
    ///
    /// # Parameters
    /// - `block`: Block data to add
    ///
    /// # Returns
    /// - `Ok(())`: Block successfully added
    /// - `Err(BlockAlignedError)`: Container is at maximum capacity
    pub fn push_block(&mut self, block: [u8; BLOCK_SIZE]) -> Result<(), BlockAlignedError> {
        if self.block_count >= MAX_BLOCKS {
            return Err(BlockAlignedError::CapacityExceeded);
        }

        let block_slot = self
            .blocks
            .get_mut(self.block_count)
            .ok_or(BlockAlignedError::CapacityExceeded)?;
        *block_slot = block;
        self.block_count = self.block_count.saturating_add(1);
        Ok(())
    }

    /// Get the blocks as a slice containing only the valid blocks.
    pub fn blocks(&self) -> &[[u8; BLOCK_SIZE]] {
        &self.blocks[..self.block_count]
    }

    /// Get the total number of bytes in valid blocks.
    pub const fn len(&self) -> usize {
        self.block_count.saturating_mul(BLOCK_SIZE)
    }

    /// Check if the container is empty.
    pub const fn is_empty(&self) -> bool {
        self.block_count == 0
    }

    /// Get the number of blocks currently stored.
    pub const fn block_count(&self) -> usize {
        self.block_count
    }

    /// Get the maximum number of blocks this container can hold.
    pub const fn capacity(&self) -> usize {
        MAX_BLOCKS
    }

    /// Get a specific block by index.
    pub fn get_block(&self, index: usize) -> Option<&[u8; BLOCK_SIZE]> {
        if index < self.block_count {
            self.blocks.get(index)
        } else {
            None
        }
    }

    /// Iterate over all valid blocks.
    pub fn iter_blocks(&self) -> impl Iterator<Item = &[u8; BLOCK_SIZE]> {
        self.blocks[..self.block_count].iter()
    }
}

/// Trait for secure cipher operations and cleanup.
///
/// This trait provides security-focused operations that are orthogonal to basic
/// cipher functionality. It enables secure state management, cleanup, and
/// zeroization without requiring full cipher operation capabilities.
///
/// # Security Operations
///
/// - Secure state clearing and zeroization
/// - Emergency cleanup procedures
/// - Security policy enforcement
/// - Sensitive data lifecycle management
///
/// # Independence from CipherOp
///
/// This trait is deliberately independent of `CipherOp` to allow:
/// - Security managers that don't perform encryption/decryption
/// - Key stores and vaults with secure cleanup
/// - Flexible composition with other cipher traits
pub trait SecureCipherOp: ErrorType {
    /// Securely clear internal state and zeroize sensitive data.
    ///
    /// This method performs a secure cleanup of all internal state, including:
    /// - Zeroization of key material in memory
    /// - Clearing of intermediate computation values
    /// - Resetting hardware registers (for hardware implementations)
    /// - Invalidating cached data or contexts
    ///
    /// # Security Guarantees
    ///
    /// - All sensitive data must be cryptographically erased
    /// - Memory containing keys or intermediate values must be zeroized
    /// - Hardware registers must be cleared if applicable
    /// - The operation should be resistant to compiler optimizations
    ///
    /// # Returns
    ///
    /// A result indicating whether the secure cleanup was successful.
    ///
    /// # Errors
    ///
    /// - `HardwareFailure`: Hardware cleanup operations failed
    /// - `PermissionDenied`: Insufficient privileges for secure operations
    /// - `InvalidState`: Cipher is in a state that prevents secure cleanup
    ///
    /// # Example
    ///
    /// ```ignore
    /// let mut cipher = SecureAesCipher::new();
    /// // ... perform cipher operations ...
    /// cipher.clear_state()?; // Secure cleanup before dropping
    /// ```
    fn clear_state(&mut self) -> Result<(), Self::Error>;
}

/// Trait for querying cipher status and hardware state.
///
/// This trait provides status monitoring capabilities that are useful for
/// hardware implementations, performance optimization, and error detection.
/// It's independent of cipher operations to allow status monitoring without
/// requiring operation capabilities.
///
/// # Status Monitoring
///
/// - Hardware readiness and availability
/// - Output data availability
/// - Error and alert conditions
/// - Performance and state information
///
/// # Hardware Integration
///
/// - Allows polling-based operation models
/// - Supports interrupt-driven architectures
/// - Enables efficient resource utilization
/// - Provides visibility into hardware state
pub trait CipherStatus: ErrorType {
    /// Check if the cipher is ready to accept new input data.
    ///
    /// This method indicates whether the cipher implementation can accept
    /// new input for processing. For hardware implementations, this typically
    /// corresponds to input buffer availability.
    ///
    /// # Returns
    ///
    /// - `Ok(true)`: Cipher is ready for new input
    /// - `Ok(false)`: Cipher is busy and cannot accept input
    /// - `Err(_)`: Error occurred while checking status
    ///
    /// # Use Cases
    ///
    /// - Polling loops waiting for hardware readiness
    /// - Flow control in streaming operations
    /// - Performance optimization by avoiding blocking calls
    fn is_ready(&self) -> Result<bool, Self::Error>;

    /// Check if processed output data is available for reading.
    ///
    /// This method indicates whether the cipher has completed processing
    /// and has output data available. For hardware implementations, this
    /// typically corresponds to output buffer status.
    ///
    /// # Returns
    ///
    /// - `Ok(true)`: Output data is available
    /// - `Ok(false)`: No output data is currently available
    /// - `Err(_)`: Error occurred while checking status
    ///
    /// # Use Cases
    ///
    /// - Polling for completion of asynchronous operations
    /// - Avoiding blocking reads when no data is available
    /// - Implementing efficient producer-consumer patterns
    fn has_output(&self) -> Result<bool, Self::Error>;

    /// Check if the cipher is idle and available for new operations.
    ///
    /// This method indicates whether the cipher is in an idle state and
    /// can be used for new operations. This is useful for determining
    /// when to start new transactions or perform maintenance operations.
    ///
    /// # Returns
    ///
    /// - `Ok(true)`: Cipher is idle and available
    /// - `Ok(false)`: Cipher is busy with ongoing operations
    /// - `Err(_)`: Error occurred while checking status
    ///
    /// # Use Cases
    ///
    /// - Determining when to begin new cipher transactions
    /// - Resource management and scheduling
    /// - Power management decisions
    /// - Maintenance and diagnostic operations
    fn is_idle(&self) -> Result<bool, Self::Error>;
}

/// Trait for AEAD (Authenticated Encryption with Associated Data) operations.
///
/// This trait extends symmetric cipher operations to provide authenticated encryption,
/// which combines confidentiality (encryption) with authenticity and integrity
/// (authentication). AEAD modes like AES-GCM and ChaCha20-Poly1305 are the
/// recommended approach for modern cryptographic applications.
///
/// # AEAD Benefits
///
/// - **Confidentiality**: Data is encrypted and unreadable without the key
/// - **Authenticity**: Verifies the data came from the expected sender
/// - **Integrity**: Detects any tampering or corruption of the data
/// - **Associated Data**: Can authenticate additional data without encrypting it
///
/// # Security Guarantees
///
/// - Prevents chosen-ciphertext attacks
/// - Provides semantic security
/// - Detects message tampering
/// - Supports additional authenticated data (AAD) that remains in plaintext
///
/// # Common Algorithms
///
/// - **AES-GCM**: High performance, hardware acceleration available
/// - **ChaCha20-Poly1305**: Software-friendly, constant-time implementation
/// - **AES-CCM**: Suited for resource-constrained environments
///
/// # Example Usage
///
/// ```ignore
/// // Encrypt with associated data
/// let plaintext = b"secret message";
/// let aad = b"public header info";
/// let (ciphertext, tag) = cipher.encrypt_aead(plaintext, aad)?;
///
/// // Decrypt and verify
/// let decrypted = cipher.decrypt_aead(ciphertext, aad, tag)?;
/// ```
pub trait AeadCipherOp: SymmetricCipher + ErrorType {
    /// The associated data type for AEAD operations.
    ///
    /// Associated data (AAD) is additional information that is authenticated
    /// but not encrypted. It provides integrity protection for data that must
    /// remain in plaintext, such as packet headers or metadata.
    ///
    /// # Security Properties
    ///
    /// - **Authenticated but not encrypted**: AAD is included in authentication tag calculation
    /// - **Integrity protected**: Any modification to AAD will cause decryption to fail
    /// - **No confidentiality**: AAD remains visible in plaintext
    ///
    /// # Use Cases
    ///
    /// - Network packet headers that must be readable by intermediary devices
    /// - File metadata that must remain accessible
    /// - Protocol version information
    /// - Sequence numbers or timestamps
    ///
    /// # Common Types
    ///
    /// - `&[u8]` for read-only associated data
    /// - `[u8; N]` for fixed-size owned associated data
    /// - `()` or empty slice if no associated data is needed
    type AssociatedData: FromBytes + IntoBytes;

    /// The authentication tag type for AEAD operations.
    ///
    /// The authentication tag is a cryptographic checksum that provides
    /// integrity and authenticity verification for both the ciphertext
    /// and associated data.
    ///
    /// # Security Properties
    ///
    /// - **Unforgeable**: Cannot be created without the secret key
    /// - **Tamper-evident**: Any modification to protected data changes the tag
    /// - **Algorithm-specific size**: Fixed size determined by the AEAD mode
    ///
    /// # Tag Sizes
    ///
    /// - **AES-GCM**: 16 bytes (128 bits) recommended, can be truncated
    /// - **ChaCha20-Poly1305**: 16 bytes (128 bits) fixed
    /// - **AES-CCM**: Variable (4, 6, 8, 10, 12, 14, or 16 bytes)
    ///
    /// # Security Warning
    ///
    /// Tags must be compared in constant time to prevent timing attacks.
    /// Use cryptographic comparison functions, not standard equality operators.
    ///
    /// # Common Types
    ///
    /// - `[u8; 16]` for most AEAD modes
    /// - `[u8; N]` for variable-length tags
    /// - Custom types that include metadata
    type Tag: FromBytes + IntoBytes;

    /// Encrypts the given plaintext with associated data.
    ///
    /// # Parameters
    ///
    /// - `plaintext`: The data to encrypt.
    /// - `associated_data`: The associated data to authenticate.
    ///
    /// # Returns
    ///
    /// A result containing the ciphertext and authentication tag or an error.
    fn encrypt_aead(
        &mut self,
        plaintext: Self::PlainText,
        associated_data: Self::AssociatedData,
    ) -> Result<(Self::CipherText, Self::Tag), Self::Error>;

    /// Decrypts the given ciphertext with associated data and authentication tag.
    ///
    /// # Parameters
    ///
    /// - `ciphertext`: The data to decrypt.
    /// - `associated_data`: The associated data to authenticate.
    /// - `tag`: The authentication tag.
    ///
    /// # Returns
    ///
    /// A result containing the plaintext or an error.
    fn decrypt_aead(
        &mut self,
        ciphertext: Self::CipherText,
        associated_data: Self::AssociatedData,
        tag: Self::Tag,
    ) -> Result<Self::PlainText, Self::Error>;
}

#[cfg(test)]
#[allow(clippy::unwrap_used)] // Allow unwrap in tests for cleaner test code
mod tests {
    use super::*;

    #[test]
    fn test_block_aligned_creation() {
        let container = BlockAligned::<16, 4>::new();
        assert_eq!(container.block_count(), 0);
        assert_eq!(container.capacity(), 4);
        assert_eq!(container.len(), 0);
        assert!(container.is_empty());
    }

    #[test]
    fn test_block_aligned_default() {
        let container: BlockAligned<16, 4> = Default::default();
        assert_eq!(container.block_count(), 0);
        assert_eq!(container.capacity(), 4);
        assert!(container.is_empty());
    }

    #[test]
    fn test_push_block_success() {
        let mut container = BlockAligned::<16, 4>::new();

        let block1 = [0x42u8; 16];
        let result = container.push_block(block1);
        assert!(result.is_ok());
        assert_eq!(container.block_count(), 1);
        assert_eq!(container.len(), 16);
        assert!(!container.is_empty());

        let block2 = [0x33u8; 16];
        let result = container.push_block(block2);
        assert!(result.is_ok());
        assert_eq!(container.block_count(), 2);
        assert_eq!(container.len(), 32);
    }

    #[test]
    fn test_push_block_capacity_exceeded() {
        let mut container = BlockAligned::<16, 2>::new();

        // Fill to capacity
        container.push_block([0x01u8; 16]).unwrap();
        container.push_block([0x02u8; 16]).unwrap();
        assert_eq!(container.block_count(), 2);

        // Try to exceed capacity
        let result = container.push_block([0x03u8; 16]);
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), BlockAlignedError::CapacityExceeded);
        assert_eq!(container.block_count(), 2); // Should remain unchanged
    }

    #[test]
    fn test_get_block() {
        let mut container = BlockAligned::<16, 4>::new();

        let block1 = [0x42u8; 16];
        let block2 = [0x33u8; 16];
        container.push_block(block1).unwrap();
        container.push_block(block2).unwrap();

        // Test valid indices
        assert_eq!(container.get_block(0), Some(&block1));
        assert_eq!(container.get_block(1), Some(&block2));

        // Test invalid indices
        assert_eq!(container.get_block(2), None);
        assert_eq!(container.get_block(100), None);
    }

    #[test]
    fn test_blocks_slice() {
        let mut container = BlockAligned::<16, 4>::new();

        let block1 = [0x42u8; 16];
        let block2 = [0x33u8; 16];
        container.push_block(block1).unwrap();
        container.push_block(block2).unwrap();

        let blocks = container.blocks();
        assert_eq!(blocks.len(), 2);
        assert_eq!(blocks.first().unwrap(), &block1);
        assert_eq!(blocks.get(1).unwrap(), &block2);
    }

    #[test]
    fn test_iter_blocks() {
        let mut container = BlockAligned::<16, 4>::new();

        let block1 = [0x42u8; 16];
        let block2 = [0x33u8; 16];
        let block3 = [0x11u8; 16];

        container.push_block(block1).unwrap();
        container.push_block(block2).unwrap();
        container.push_block(block3).unwrap();

        // Test iterator manually
        let mut iter = container.iter_blocks();
        assert_eq!(iter.next(), Some(&block1));
        assert_eq!(iter.next(), Some(&block2));
        assert_eq!(iter.next(), Some(&block3));
        assert_eq!(iter.next(), None);

        // Test that iterator only includes valid blocks
        let empty_container = BlockAligned::<16, 4>::new();
        let mut empty_iter = empty_container.iter_blocks();
        assert_eq!(empty_iter.next(), None);
    }

    #[test]
    fn test_from_slice_padded_exact_fit() {
        // Test data that exactly fits one block
        let data = [0x42u8; 16];
        let container = BlockAligned::<16, 4>::from_slice_padded(&data, 0x00).unwrap();

        assert_eq!(container.block_count(), 1);
        assert_eq!(container.get_block(0), Some(&data));
    }

    #[test]
    fn test_from_slice_padded_partial_block() {
        // Test data that requires padding
        let data = b"Hello, World!"; // 13 bytes
        let container = BlockAligned::<16, 4>::from_slice_padded(data, 0x00).unwrap();

        assert_eq!(container.block_count(), 1);

        let block = container.get_block(0).unwrap();
        // First 13 bytes should match input
        assert_eq!(&block[..13], data);
        // Last 3 bytes should be padding
        assert_eq!(&block[13..], &[0x00; 3]);
    }

    #[test]
    fn test_from_slice_padded_multiple_blocks() {
        // Test data that spans multiple blocks
        let data = [0x42u8; 33]; // 33 bytes = 3 blocks (16 + 16 + 1)
        let container = BlockAligned::<16, 4>::from_slice_padded(&data, 0xFF).unwrap();

        assert_eq!(container.block_count(), 3);

        // First two blocks should be all 0x42
        assert_eq!(container.get_block(0), Some(&[0x42u8; 16]));
        assert_eq!(container.get_block(1), Some(&[0x42u8; 16]));

        // Third block should have one byte of data and 15 bytes of padding
        let third_block = container.get_block(2).unwrap();
        assert_eq!(third_block.first().unwrap(), &0x42);
        assert_eq!(&third_block[1..], &[0xFF; 15]);
    }

    #[test]
    fn test_from_slice_padded_empty_data() {
        let data = &[];
        let container = BlockAligned::<16, 4>::from_slice_padded(data, 0x00).unwrap();

        assert_eq!(container.block_count(), 0);
        assert!(container.is_empty());
    }

    #[test]
    fn test_from_slice_padded_data_too_large() {
        // Test data that exceeds capacity
        let data = [0x42u8; 100]; // 100 bytes = 7 blocks (16*6 + 4), but capacity is only 4
        let result = BlockAligned::<16, 4>::from_slice_padded(&data, 0x00);

        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), BlockAlignedError::DataTooLarge);
    }

    #[test]
    fn test_from_slice_padded_different_padding() {
        let data = b"test"; // 4 bytes
        let container = BlockAligned::<8, 2>::from_slice_padded(data, 0xAA).unwrap();

        assert_eq!(container.block_count(), 1);

        let block = container.get_block(0).unwrap();
        assert_eq!(&block[..4], data);
        assert_eq!(&block[4..], &[0xAA; 4]);
    }

    #[test]
    fn test_different_block_sizes() {
        // Test with 8-byte blocks
        let mut container8 = BlockAligned::<8, 4>::new();
        container8.push_block([0x11u8; 8]).unwrap();
        assert_eq!(container8.len(), 8);

        // Test with 32-byte blocks
        let mut container32 = BlockAligned::<32, 2>::new();
        container32.push_block([0x22u8; 32]).unwrap();
        assert_eq!(container32.len(), 32);

        // Test with 1-byte blocks
        let mut container1 = BlockAligned::<1, 16>::new();
        container1.push_block([0x33]).unwrap();
        assert_eq!(container1.len(), 1);
    }

    #[test]
    fn test_clone_and_equality() {
        let mut container1 = BlockAligned::<16, 4>::new();
        let block = [0x42u8; 16];
        container1.push_block(block).unwrap();

        let container2 = container1.clone();
        assert_eq!(container1, container2);
        assert_eq!(container1.block_count(), container2.block_count());
        assert_eq!(container1.get_block(0), container2.get_block(0));

        // Test inequality
        let mut container3 = BlockAligned::<16, 4>::new();
        container3.push_block([0x33u8; 16]).unwrap();
        assert_ne!(container1, container3);
    }

    #[test]
    fn test_edge_cases() {
        // Test with maximum capacity
        let mut container = BlockAligned::<1, 8>::new();
        for i in 0..8 {
            container.push_block([i as u8]).unwrap();
        }
        assert_eq!(container.block_count(), 8);
        assert_eq!(container.len(), 8);

        // Verify all blocks are correct
        for i in 0..8 {
            assert_eq!(container.get_block(i), Some(&[i as u8]));
        }
    }

    #[test]
    fn test_error_display() {
        let capacity_error = BlockAlignedError::CapacityExceeded;
        let data_error = BlockAlignedError::DataTooLarge;

        // Test that the errors are created correctly
        assert_eq!(capacity_error, BlockAlignedError::CapacityExceeded);
        assert_eq!(data_error, BlockAlignedError::DataTooLarge);

        // Test that they are not equal to each other
        assert_ne!(capacity_error, data_error);
    }

    #[test]
    fn test_debug_formatting() {
        let mut container = BlockAligned::<4, 2>::new();
        container.push_block([1, 2, 3, 4]).unwrap();

        // Test that the container was created successfully
        assert_eq!(container.block_count(), 1);
        assert_eq!(container.get_block(0), Some(&[1, 2, 3, 4]));
    }
}
