// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0

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,

    /// The hardware accelerator is busy and cannot process the cipher operation.
    Busy,

    /// The operation did not complete within the expected time.
    Timeout,
}

/// 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.
    ///
    /// # Returns
    ///
    /// A result containing the operational context or an error.
    fn init<'a>(
        &'a mut self,
        key: &Self::Key,
        nonce: &Self::Nonce,
    ) -> 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: SymmetricCipher {
    /// 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: &Self::Key) -> 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 {
    /// 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);
}

/// 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
    ///
    /// 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: &[u8],
    ) -> 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: &[u8],
        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]));
    }
}
