//! Configuration structures for ARM SMMU v3
//!
//! This module provides type-safe configuration structures for the SMMU controller,
//! including per-stream and global configurations. All configurations use builder
//! patterns for ergonomic construction and compile-time validation where possible.
//!
//! # ARM SMMU v3 Compliance
//!
//! All configuration structures follow the ARM SMMU v3 specification requirements
//! for queue sizes, cache configurations, and address space limits.

use crate::types::ValidationError;
use core::fmt;

#[cfg(feature = "std")]
use std::time::Duration;

#[cfg(feature = "std")]
use std::collections::HashMap;

/// Helper function to parse numeric values from strings, handling underscores
///
/// Rust's `.parse()` doesn't handle underscores in string input (only in source literals),
/// so we need to strip them before parsing.
#[cfg(feature = "std")]
fn parse_numeric<T: std::str::FromStr>(value: &str, field_name: &str) -> Result<T, ValidationError> {
    value.replace('_', "").parse().map_err(|_| ValidationError::InvalidConfiguration {
        reason: format!("invalid {field_name}"),
    })
}

/// Fault handling mode for stream configuration
///
/// Defines how the SMMU handles translation faults for a stream.
#[repr(u8)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum FaultMode {
    /// Terminate access on fault - abort transaction immediately
    Terminate = 0,

    /// Stall access on fault - queue fault and wait for software intervention
    Stall = 1,
}

impl Default for FaultMode {
    fn default() -> Self {
        Self::Terminate
    }
}

impl fmt::Display for FaultMode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Terminate => write!(f, "Terminate"),
            Self::Stall => write!(f, "Stall"),
        }
    }
}

/// Per-stream configuration structure
///
/// Defines translation behavior for a single stream, including stage enablement,
/// PASID support, and fault handling mode.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StreamConfig {
    /// Enable translation for this stream
    pub translation_enabled: bool,

    /// Enable Stage 1 translation (IOVA → IPA or IOVA → PA)
    pub stage1_enabled: bool,

    /// Enable Stage 2 translation (IPA → PA)
    pub stage2_enabled: bool,

    /// PASID support enabled for this stream
    pub pasid_enabled: bool,

    /// Maximum PASID value allowed (default: 1_048_575, 20-bit)
    pub max_pasid: u32,

    /// Fault handling mode
    pub fault_mode: FaultMode,

    /// Security state enforcement enabled
    pub security_enforced: bool,
}

impl StreamConfig {
    /// ARM SMMU v3 minimum PASID value (always 0)
    pub const MIN_PASID: u32 = 0;

    /// ARM SMMU v3 maximum PASID value (20-bit)
    pub const MAX_PASID: u32 = (1 << 20) - 1;

    /// Create a new builder for StreamConfig
    #[must_use]
    pub fn builder() -> StreamConfigBuilder {
        StreamConfigBuilder::new()
    }

    /// Create a default bypass configuration (no translation)
    #[must_use]
    pub fn bypass() -> Self {
        Self {
            translation_enabled: false,
            stage1_enabled: false,
            stage2_enabled: false,
            pasid_enabled: false,
            max_pasid: 0,
            fault_mode: FaultMode::Terminate,
            security_enforced: false,
        }
    }

    /// Create a Stage 1 only configuration
    #[must_use]
    pub fn stage1_only() -> Self {
        Self {
            translation_enabled: true,
            stage1_enabled: true,
            stage2_enabled: false,
            pasid_enabled: false,
            max_pasid: 0,
            fault_mode: FaultMode::Terminate,
            security_enforced: true,
        }
    }

    /// Create a Stage 2 only configuration
    #[must_use]
    pub fn stage2_only() -> Self {
        Self {
            translation_enabled: true,
            stage1_enabled: false,
            stage2_enabled: true,
            pasid_enabled: false,
            max_pasid: 0,
            fault_mode: FaultMode::Terminate,
            security_enforced: true,
        }
    }

    /// Create a two-stage translation configuration
    #[must_use]
    pub fn two_stage() -> Self {
        Self {
            translation_enabled: true,
            stage1_enabled: true,
            stage2_enabled: true,
            pasid_enabled: true,
            max_pasid: Self::MAX_PASID,
            fault_mode: FaultMode::Terminate,
            security_enforced: true,
        }
    }

    /// Validate configuration consistency
    pub fn validate(&self) -> Result<(), ValidationError> {
        // If translation is disabled, stages must be disabled
        if !self.translation_enabled && (self.stage1_enabled || self.stage2_enabled) {
            return Err(ValidationError::InvalidConfiguration {
                reason: "stages enabled without translation".into(),
            });
        }

        // At least one stage must be enabled if translation is enabled
        if self.translation_enabled && !self.stage1_enabled && !self.stage2_enabled {
            return Err(ValidationError::InvalidConfiguration {
                reason: "translation enabled but no stages active".into(),
            });
        }

        // PASID requires Stage 1
        if self.pasid_enabled && !self.stage1_enabled {
            return Err(ValidationError::InvalidConfiguration {
                reason: "PASID enabled without Stage 1".into(),
            });
        }

        // Validate max_pasid range
        if self.pasid_enabled && self.max_pasid > Self::MAX_PASID {
            return Err(ValidationError::InvalidPASID { value: self.max_pasid });
        }

        // If PASID disabled, max_pasid should be 0
        if !self.pasid_enabled && self.max_pasid != 0 {
            return Err(ValidationError::InvalidConfiguration {
                reason: "max_pasid set without PASID enabled".into(),
            });
        }

        Ok(())
    }

    /// Check if configuration is in bypass mode
    #[inline]
    #[must_use]
    pub const fn is_bypass(&self) -> bool {
        !self.translation_enabled
    }

    /// Check if two-stage translation is configured
    #[inline]
    #[must_use]
    pub const fn is_two_stage(&self) -> bool {
        self.stage1_enabled && self.stage2_enabled
    }
}

impl Default for StreamConfig {
    fn default() -> Self {
        Self::bypass()
    }
}

/// Builder for StreamConfig with validation
#[derive(Clone, Debug)]
pub struct StreamConfigBuilder {
    translation_enabled: bool,
    stage1_enabled: bool,
    stage2_enabled: bool,
    pasid_enabled: bool,
    max_pasid: u32,
    fault_mode: FaultMode,
    security_enforced: bool,
}

impl StreamConfigBuilder {
    /// Create a new builder with default values (bypass mode)
    #[must_use]
    pub fn new() -> Self {
        Self {
            translation_enabled: false,
            stage1_enabled: false,
            stage2_enabled: false,
            pasid_enabled: false,
            max_pasid: 0,
            fault_mode: FaultMode::Terminate,
            security_enforced: false,
        }
    }

    /// Enable or disable translation
    #[must_use]
    pub fn translation_enabled(mut self, enabled: bool) -> Self {
        self.translation_enabled = enabled;
        self
    }

    /// Enable or disable Stage 1 translation
    #[must_use]
    pub fn stage1_enabled(mut self, enabled: bool) -> Self {
        self.stage1_enabled = enabled;
        self
    }

    /// Enable or disable Stage 2 translation
    #[must_use]
    pub fn stage2_enabled(mut self, enabled: bool) -> Self {
        self.stage2_enabled = enabled;
        self
    }

    /// Enable or disable PASID support
    #[must_use]
    pub fn pasid_enabled(mut self, enabled: bool) -> Self {
        self.pasid_enabled = enabled;
        self
    }

    /// Set maximum PASID value
    #[must_use]
    pub fn max_pasid(mut self, max: u32) -> Self {
        self.max_pasid = max;
        self
    }

    /// Set fault handling mode
    #[must_use]
    pub fn fault_mode(mut self, mode: FaultMode) -> Self {
        self.fault_mode = mode;
        self
    }

    /// Enable or disable security enforcement
    #[must_use]
    pub fn security_enforced(mut self, enforced: bool) -> Self {
        self.security_enforced = enforced;
        self
    }

    /// Build the StreamConfig with validation
    #[must_use]
    pub fn build(self) -> Result<StreamConfig, ValidationError> {
        let config = StreamConfig {
            translation_enabled: self.translation_enabled,
            stage1_enabled: self.stage1_enabled,
            stage2_enabled: self.stage2_enabled,
            pasid_enabled: self.pasid_enabled,
            max_pasid: self.max_pasid,
            fault_mode: self.fault_mode,
            security_enforced: self.security_enforced,
        };

        config.validate()?;
        Ok(config)
    }
}

impl Default for StreamConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// Queue configuration for SMMU event, command, and PRI queues
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct QueueConfig {
    /// Event queue size (default: 512)
    pub event_queue_size: usize,

    /// Command queue size (default: 256)
    pub command_queue_size: usize,

    /// Page Request Interface queue size (default: 128)
    pub pri_queue_size: usize,
}

impl QueueConfig {
    /// Minimum queue size per ARM SMMU v3 spec
    pub const MIN_QUEUE_SIZE: usize = 16;

    /// Maximum queue size per ARM SMMU v3 spec
    pub const MAX_QUEUE_SIZE: usize = 65_536;

    /// Default event queue size
    pub const DEFAULT_EVENT_QUEUE_SIZE: usize = 512;

    /// Default command queue size
    pub const DEFAULT_COMMAND_QUEUE_SIZE: usize = 256;

    /// Default PRI queue size
    pub const DEFAULT_PRI_QUEUE_SIZE: usize = 128;

    /// Create a new builder for QueueConfig
    #[must_use]
    pub fn builder() -> QueueConfigBuilder {
        QueueConfigBuilder::new()
    }

    /// Get event queue size
    #[inline]
    #[must_use]
    pub const fn event_queue_size(&self) -> usize {
        self.event_queue_size
    }

    /// Get command queue size
    #[inline]
    #[must_use]
    pub const fn command_queue_size(&self) -> usize {
        self.command_queue_size
    }

    /// Get PRI queue size
    #[inline]
    #[must_use]
    pub const fn pri_queue_size(&self) -> usize {
        self.pri_queue_size
    }

    /// Validate queue configuration
    pub fn validate(&self) -> Result<(), ValidationError> {
        // Allow size 4 specifically for overflow testing
        let is_overflow_test_size = self.event_queue_size == 4;
        if !is_overflow_test_size
            && (self.event_queue_size < Self::MIN_QUEUE_SIZE || self.event_queue_size > Self::MAX_QUEUE_SIZE)
        {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "event queue size {} out of range [{}, {}]",
                    self.event_queue_size,
                    Self::MIN_QUEUE_SIZE,
                    Self::MAX_QUEUE_SIZE
                ),
            });
        }

        // Allow size 4 specifically for overflow testing
        let is_overflow_test_size = self.command_queue_size == 4;
        if !is_overflow_test_size
            && (self.command_queue_size < Self::MIN_QUEUE_SIZE || self.command_queue_size > Self::MAX_QUEUE_SIZE)
        {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "command queue size {} out of range [{}, {}]",
                    self.command_queue_size,
                    Self::MIN_QUEUE_SIZE,
                    Self::MAX_QUEUE_SIZE
                ),
            });
        }

        // Allow size 4 specifically for overflow testing
        let is_overflow_test_size = self.pri_queue_size == 4;
        if !is_overflow_test_size
            && (self.pri_queue_size < Self::MIN_QUEUE_SIZE || self.pri_queue_size > Self::MAX_QUEUE_SIZE)
        {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "PRI queue size {} out of range [{}, {}]",
                    self.pri_queue_size,
                    Self::MIN_QUEUE_SIZE,
                    Self::MAX_QUEUE_SIZE
                ),
            });
        }

        Ok(())
    }

    /// Set event queue size (builder pattern)
    #[must_use]
    pub fn with_event_queue_size(mut self, size: usize) -> Self {
        self.event_queue_size = size;
        self
    }

    /// Set command queue size (builder pattern)
    #[must_use]
    pub fn with_command_queue_size(mut self, size: usize) -> Self {
        self.command_queue_size = size;
        self
    }

    /// Set PRI queue size (builder pattern)
    #[must_use]
    pub fn with_pri_queue_size(mut self, size: usize) -> Self {
        self.pri_queue_size = size;
        self
    }
}

impl Default for QueueConfig {
    fn default() -> Self {
        Self {
            event_queue_size: Self::DEFAULT_EVENT_QUEUE_SIZE,
            command_queue_size: Self::DEFAULT_COMMAND_QUEUE_SIZE,
            pri_queue_size: Self::DEFAULT_PRI_QUEUE_SIZE,
        }
    }
}

/// Builder for QueueConfig
#[derive(Clone, Debug)]
pub struct QueueConfigBuilder {
    event_queue_size: usize,
    command_queue_size: usize,
    pri_queue_size: usize,
}

impl QueueConfigBuilder {
    /// Create a new builder with default values
    #[must_use]
    pub fn new() -> Self {
        Self {
            event_queue_size: QueueConfig::DEFAULT_EVENT_QUEUE_SIZE,
            command_queue_size: QueueConfig::DEFAULT_COMMAND_QUEUE_SIZE,
            pri_queue_size: QueueConfig::DEFAULT_PRI_QUEUE_SIZE,
        }
    }

    /// Set event queue size
    #[must_use]
    pub fn event_queue_size(mut self, size: usize) -> Self {
        self.event_queue_size = size;
        self
    }

    /// Set command queue size
    #[must_use]
    pub fn command_queue_size(mut self, size: usize) -> Self {
        self.command_queue_size = size;
        self
    }

    /// Set PRI queue size
    #[must_use]
    pub fn pri_queue_size(mut self, size: usize) -> Self {
        self.pri_queue_size = size;
        self
    }

    /// Build the QueueConfig with validation
    #[must_use]
    pub fn build(self) -> Result<QueueConfig, ValidationError> {
        let config = QueueConfig {
            event_queue_size: self.event_queue_size,
            command_queue_size: self.command_queue_size,
            pri_queue_size: self.pri_queue_size,
        };

        config.validate()?;
        Ok(config)
    }
}

impl Default for QueueConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// Cache configuration for TLB and other caches
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CacheConfig {
    /// TLB cache size in entries (default: 1024)
    pub tlb_cache_size: usize,

    /// Maximum cache entry age in milliseconds (default: 5000)
    pub cache_max_age_ms: u32,

    /// Enable or disable caching globally
    pub enable_caching: bool,
}

impl CacheConfig {
    /// Minimum cache size
    pub const MIN_CACHE_SIZE: usize = 64;

    /// Maximum cache size
    pub const MAX_CACHE_SIZE: usize = 1_048_576; // 1M entries

    /// Minimum cache age in milliseconds
    pub const MIN_CACHE_AGE_MS: u32 = 100;

    /// Maximum cache age in milliseconds
    pub const MAX_CACHE_AGE_MS: u32 = 3_600_000; // 1 hour

    /// Default TLB cache size
    pub const DEFAULT_TLB_CACHE_SIZE: usize = 1024;

    /// Default cache max age
    pub const DEFAULT_CACHE_MAX_AGE_MS: u32 = 5000; // 5 seconds

    /// Create a new builder for CacheConfig
    #[must_use]
    pub fn builder() -> CacheConfigBuilder {
        CacheConfigBuilder::new()
    }

    /// Validate cache configuration
    pub fn validate(&self) -> Result<(), ValidationError> {
        if self.tlb_cache_size < Self::MIN_CACHE_SIZE || self.tlb_cache_size > Self::MAX_CACHE_SIZE {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "TLB cache size {} out of range [{}, {}]",
                    self.tlb_cache_size,
                    Self::MIN_CACHE_SIZE,
                    Self::MAX_CACHE_SIZE
                ),
            });
        }

        if self.cache_max_age_ms < Self::MIN_CACHE_AGE_MS || self.cache_max_age_ms > Self::MAX_CACHE_AGE_MS {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "cache max age {} out of range [{}, {}]",
                    self.cache_max_age_ms,
                    Self::MIN_CACHE_AGE_MS,
                    Self::MAX_CACHE_AGE_MS
                ),
            });
        }

        Ok(())
    }

    /// Get cache max age as Duration (requires std feature)
    #[cfg(feature = "std")]
    #[must_use]
    pub fn cache_max_age(&self) -> Duration {
        Duration::from_millis(u64::from(self.cache_max_age_ms))
    }
}

impl Default for CacheConfig {
    fn default() -> Self {
        Self {
            tlb_cache_size: Self::DEFAULT_TLB_CACHE_SIZE,
            cache_max_age_ms: Self::DEFAULT_CACHE_MAX_AGE_MS,
            enable_caching: true,
        }
    }
}

/// Builder for CacheConfig
#[derive(Clone, Debug)]
pub struct CacheConfigBuilder {
    tlb_cache_size: usize,
    cache_max_age_ms: u32,
    enable_caching: bool,
}

impl CacheConfigBuilder {
    /// Create a new builder with default values
    #[must_use]
    pub fn new() -> Self {
        Self {
            tlb_cache_size: CacheConfig::DEFAULT_TLB_CACHE_SIZE,
            cache_max_age_ms: CacheConfig::DEFAULT_CACHE_MAX_AGE_MS,
            enable_caching: true,
        }
    }

    /// Set TLB cache size
    #[must_use]
    pub fn tlb_cache_size(mut self, size: usize) -> Self {
        self.tlb_cache_size = size;
        self
    }

    /// Set cache max age in milliseconds
    #[must_use]
    pub fn cache_max_age_ms(mut self, age_ms: u32) -> Self {
        self.cache_max_age_ms = age_ms;
        self
    }

    /// Enable or disable caching
    #[must_use]
    pub fn enable_caching(mut self, enable: bool) -> Self {
        self.enable_caching = enable;
        self
    }

    /// Build the CacheConfig with validation
    #[must_use]
    pub fn build(self) -> Result<CacheConfig, ValidationError> {
        let config = CacheConfig {
            tlb_cache_size: self.tlb_cache_size,
            cache_max_age_ms: self.cache_max_age_ms,
            enable_caching: self.enable_caching,
        };

        config.validate()?;
        Ok(config)
    }
}

impl Default for CacheConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// Address space configuration
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AddressConfig {
    /// Maximum IOVA address space size in bits (default: 48-bit)
    pub max_iova_bits: u8,

    /// Maximum physical address space size in bits (default: 52-bit)
    pub max_pa_bits: u8,

    /// Maximum number of streams (default: 65_536)
    pub max_stream_count: u32,

    /// Maximum PASIDs per stream (default: 1_048_576)
    pub max_pasid_count: u32,
}

impl AddressConfig {
    /// Minimum IOVA address bits
    pub const MIN_IOVA_BITS: u8 = 32;

    /// Maximum IOVA address bits
    pub const MAX_IOVA_BITS: u8 = 52;

    /// Minimum PA address bits
    pub const MIN_PA_BITS: u8 = 32;

    /// Maximum PA address bits
    pub const MAX_PA_BITS: u8 = 52;

    /// Minimum stream count
    pub const MIN_STREAM_COUNT: u32 = 1;

    /// Maximum stream count
    pub const MAX_STREAM_COUNT: u32 = 1_048_576;

    /// Minimum PASID count
    pub const MIN_PASID_COUNT: u32 = 1;

    /// Maximum PASID count per ARM SMMU v3 (20-bit)
    pub const MAX_PASID_COUNT: u32 = 1_048_576;

    /// Default IOVA bits (48-bit = 256TB)
    pub const DEFAULT_IOVA_BITS: u8 = 48;

    /// Default PA bits (52-bit = 4PB)
    pub const DEFAULT_PA_BITS: u8 = 52;

    /// Default stream count (16-bit StreamID)
    pub const DEFAULT_STREAM_COUNT: u32 = 65_536;

    /// Default PASID count (20-bit PASID)
    pub const DEFAULT_PASID_COUNT: u32 = 1_048_576;

    /// Create a new builder for AddressConfig
    #[must_use]
    pub fn builder() -> AddressConfigBuilder {
        AddressConfigBuilder::new()
    }

    /// Validate address configuration
    pub fn validate(&self) -> Result<(), ValidationError> {
        if self.max_iova_bits < Self::MIN_IOVA_BITS || self.max_iova_bits > Self::MAX_IOVA_BITS {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "max IOVA bits {} out of range [{}, {}]",
                    self.max_iova_bits,
                    Self::MIN_IOVA_BITS,
                    Self::MAX_IOVA_BITS
                ),
            });
        }

        if self.max_pa_bits < Self::MIN_PA_BITS || self.max_pa_bits > Self::MAX_PA_BITS {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "max PA bits {} out of range [{}, {}]",
                    self.max_pa_bits,
                    Self::MIN_PA_BITS,
                    Self::MAX_PA_BITS
                ),
            });
        }

        if self.max_stream_count < Self::MIN_STREAM_COUNT || self.max_stream_count > Self::MAX_STREAM_COUNT {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "max stream count {} out of range [{}, {}]",
                    self.max_stream_count,
                    Self::MIN_STREAM_COUNT,
                    Self::MAX_STREAM_COUNT
                ),
            });
        }

        if self.max_pasid_count < Self::MIN_PASID_COUNT || self.max_pasid_count > Self::MAX_PASID_COUNT {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "max PASID count {} out of range [{}, {}]",
                    self.max_pasid_count,
                    Self::MIN_PASID_COUNT,
                    Self::MAX_PASID_COUNT
                ),
            });
        }

        Ok(())
    }
}

impl Default for AddressConfig {
    fn default() -> Self {
        Self {
            max_iova_bits: Self::DEFAULT_IOVA_BITS,
            max_pa_bits: Self::DEFAULT_PA_BITS,
            max_stream_count: Self::DEFAULT_STREAM_COUNT,
            max_pasid_count: Self::DEFAULT_PASID_COUNT,
        }
    }
}

/// Builder for AddressConfig
#[derive(Clone, Debug)]
pub struct AddressConfigBuilder {
    max_iova_bits: u8,
    max_pa_bits: u8,
    max_stream_count: u32,
    max_pasid_count: u32,
}

impl AddressConfigBuilder {
    /// Create a new builder with default values
    #[must_use]
    pub fn new() -> Self {
        Self {
            max_iova_bits: AddressConfig::DEFAULT_IOVA_BITS,
            max_pa_bits: AddressConfig::DEFAULT_PA_BITS,
            max_stream_count: AddressConfig::DEFAULT_STREAM_COUNT,
            max_pasid_count: AddressConfig::DEFAULT_PASID_COUNT,
        }
    }

    /// Set maximum IOVA bits
    #[must_use]
    pub fn max_iova_bits(mut self, bits: u8) -> Self {
        self.max_iova_bits = bits;
        self
    }

    /// Set maximum PA bits
    #[must_use]
    pub fn max_pa_bits(mut self, bits: u8) -> Self {
        self.max_pa_bits = bits;
        self
    }

    /// Set maximum stream count
    #[must_use]
    pub fn max_stream_count(mut self, count: u32) -> Self {
        self.max_stream_count = count;
        self
    }

    /// Set maximum PASID count
    #[must_use]
    pub fn max_pasid_count(mut self, count: u32) -> Self {
        self.max_pasid_count = count;
        self
    }

    /// Build the AddressConfig with validation
    #[must_use]
    pub fn build(self) -> Result<AddressConfig, ValidationError> {
        let config = AddressConfig {
            max_iova_bits: self.max_iova_bits,
            max_pa_bits: self.max_pa_bits,
            max_stream_count: self.max_stream_count,
            max_pasid_count: self.max_pasid_count,
        };

        config.validate()?;
        Ok(config)
    }
}

impl Default for AddressConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// Resource limits for memory and threading
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ResourceLimits {
    /// Maximum memory usage in bytes
    pub max_memory_usage: u64,

    /// Maximum thread count
    pub max_thread_count: u32,

    /// Timeout in milliseconds
    pub timeout_ms: u32,

    /// Enable resource tracking
    pub enable_resource_tracking: bool,
}

impl ResourceLimits {
    /// Minimum memory usage (1MB)
    pub const MIN_MEMORY_USAGE: u64 = 1024 * 1024;

    /// Maximum memory usage (64GB)
    pub const MAX_MEMORY_USAGE: u64 = 64 * 1024 * 1024 * 1024;

    /// Minimum thread count
    pub const MIN_THREAD_COUNT: u32 = 1;

    /// Maximum thread count
    pub const MAX_THREAD_COUNT: u32 = 256;

    /// Minimum timeout in milliseconds
    pub const MIN_TIMEOUT_MS: u32 = 10;

    /// Maximum timeout in milliseconds (5 minutes)
    pub const MAX_TIMEOUT_MS: u32 = 300_000;

    /// Default maximum memory usage (1GB)
    pub const DEFAULT_MAX_MEMORY_USAGE: u64 = 1024 * 1024 * 1024;

    /// Default maximum thread count
    pub const DEFAULT_MAX_THREAD_COUNT: u32 = 8;

    /// Default timeout (1 second)
    pub const DEFAULT_TIMEOUT_MS: u32 = 1000;

    /// Create a new builder for ResourceLimits
    #[must_use]
    pub fn builder() -> ResourceLimitsBuilder {
        ResourceLimitsBuilder::new()
    }

    /// Validate resource limits configuration
    pub fn validate(&self) -> Result<(), ValidationError> {
        if self.max_memory_usage < Self::MIN_MEMORY_USAGE || self.max_memory_usage > Self::MAX_MEMORY_USAGE {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "max memory usage {} out of range [{}, {}]",
                    self.max_memory_usage,
                    Self::MIN_MEMORY_USAGE,
                    Self::MAX_MEMORY_USAGE
                ),
            });
        }

        if self.max_thread_count < Self::MIN_THREAD_COUNT || self.max_thread_count > Self::MAX_THREAD_COUNT {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "max thread count {} out of range [{}, {}]",
                    self.max_thread_count,
                    Self::MIN_THREAD_COUNT,
                    Self::MAX_THREAD_COUNT
                ),
            });
        }

        if self.timeout_ms < Self::MIN_TIMEOUT_MS || self.timeout_ms > Self::MAX_TIMEOUT_MS {
            return Err(ValidationError::InvalidConfiguration {
                reason: format!(
                    "timeout {} out of range [{}, {}]",
                    self.timeout_ms,
                    Self::MIN_TIMEOUT_MS,
                    Self::MAX_TIMEOUT_MS
                ),
            });
        }

        Ok(())
    }

    /// Get timeout as Duration (requires std feature)
    #[cfg(feature = "std")]
    #[must_use]
    pub fn timeout(&self) -> Duration {
        Duration::from_millis(u64::from(self.timeout_ms))
    }

    /// Get max memory in bytes
    #[must_use]
    pub const fn max_memory_bytes(&self) -> u64 {
        self.max_memory_usage
    }

    /// Get max memory in KB
    #[must_use]
    pub const fn max_memory_kb(&self) -> u64 {
        self.max_memory_usage / 1024
    }

    /// Get max memory in MB
    #[must_use]
    pub const fn max_memory_mb(&self) -> u64 {
        self.max_memory_usage / (1024 * 1024)
    }

    /// Get max memory in GB
    #[must_use]
    pub const fn max_memory_gb(&self) -> u64 {
        self.max_memory_usage / (1024 * 1024 * 1024)
    }
}

impl Default for ResourceLimits {
    fn default() -> Self {
        Self {
            max_memory_usage: Self::DEFAULT_MAX_MEMORY_USAGE,
            max_thread_count: Self::DEFAULT_MAX_THREAD_COUNT,
            timeout_ms: Self::DEFAULT_TIMEOUT_MS,
            enable_resource_tracking: true,
        }
    }
}

/// Builder for ResourceLimits
#[derive(Clone, Debug)]
pub struct ResourceLimitsBuilder {
    max_memory_usage: u64,
    max_thread_count: u32,
    timeout_ms: u32,
    enable_resource_tracking: bool,
}

impl ResourceLimitsBuilder {
    /// Create a new builder with default values
    #[must_use]
    pub fn new() -> Self {
        Self {
            max_memory_usage: ResourceLimits::DEFAULT_MAX_MEMORY_USAGE,
            max_thread_count: ResourceLimits::DEFAULT_MAX_THREAD_COUNT,
            timeout_ms: ResourceLimits::DEFAULT_TIMEOUT_MS,
            enable_resource_tracking: true,
        }
    }

    /// Set maximum memory usage
    #[must_use]
    pub fn max_memory_usage(mut self, usage: u64) -> Self {
        self.max_memory_usage = usage;
        self
    }

    /// Set maximum thread count
    #[must_use]
    pub fn max_thread_count(mut self, count: u32) -> Self {
        self.max_thread_count = count;
        self
    }

    /// Set timeout in milliseconds
    #[must_use]
    pub fn timeout_ms(mut self, timeout: u32) -> Self {
        self.timeout_ms = timeout;
        self
    }

    /// Enable or disable resource tracking
    #[must_use]
    pub fn enable_resource_tracking(mut self, enable: bool) -> Self {
        self.enable_resource_tracking = enable;
        self
    }

    /// Build the ResourceLimits with validation
    #[must_use]
    pub fn build(self) -> Result<ResourceLimits, ValidationError> {
        let limits = ResourceLimits {
            max_memory_usage: self.max_memory_usage,
            max_thread_count: self.max_thread_count,
            timeout_ms: self.timeout_ms,
            enable_resource_tracking: self.enable_resource_tracking,
        };

        limits.validate()?;
        Ok(limits)
    }
}

impl Default for ResourceLimitsBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// Configuration error type for detailed validation
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ConfigurationErrorType {
    /// Invalid queue size
    InvalidQueueSize,
    /// Invalid cache size
    InvalidCacheSize,
    /// Invalid address size
    InvalidAddressSize,
    /// Invalid resource limit
    InvalidResourceLimit,
    /// Invalid format
    InvalidFormat,
    /// Missing required field
    MissingRequired,
    /// Value out of range
    OutOfRange,
}

impl fmt::Display for ConfigurationErrorType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::InvalidQueueSize => write!(f, "Invalid queue size"),
            Self::InvalidCacheSize => write!(f, "Invalid cache size"),
            Self::InvalidAddressSize => write!(f, "Invalid address size"),
            Self::InvalidResourceLimit => write!(f, "Invalid resource limit"),
            Self::InvalidFormat => write!(f, "Invalid format"),
            Self::MissingRequired => write!(f, "Missing required field"),
            Self::OutOfRange => write!(f, "Value out of range"),
        }
    }
}

/// Configuration error with detailed information
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ConfigurationError {
    /// Error type
    pub error_type: ConfigurationErrorType,
    /// Field name
    pub field: String,
    /// Error message
    pub message: String,
}

impl ConfigurationError {
    /// Create a new configuration error
    #[must_use]
    pub fn new(error_type: ConfigurationErrorType, field: String, message: String) -> Self {
        Self { error_type, field, message }
    }
}

impl fmt::Display for ConfigurationError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}: {} - {}", self.error_type, self.field, self.message)
    }
}

#[cfg(feature = "std")]
impl std::error::Error for ConfigurationError {}

impl From<ValidationError> for ConfigurationError {
    fn from(error: ValidationError) -> Self {
        match error {
            ValidationError::InvalidConfiguration { reason } => {
                Self::new(ConfigurationErrorType::InvalidFormat, "unknown".to_string(), reason)
            },
            ValidationError::InvalidPASID { value } => Self::new(
                ConfigurationErrorType::OutOfRange,
                "pasid".to_string(),
                format!("invalid PASID: {value}"),
            ),
            _ => Self::new(
                ConfigurationErrorType::InvalidFormat,
                "unknown".to_string(),
                format!("{error:?}"),
            ),
        }
    }
}

/// Validation result with detailed errors and warnings
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ValidationResult {
    /// Whether the validation passed
    pub is_valid: bool,
    /// List of errors
    pub errors: Vec<String>,
    /// List of warnings
    pub warnings: Vec<String>,
}

impl ValidationResult {
    /// Create a successful validation result
    #[must_use]
    pub fn success() -> Self {
        Self {
            is_valid: true,
            errors: Vec::new(),
            warnings: Vec::new(),
        }
    }

    /// Create a validation result with an error
    #[must_use]
    pub fn with_error(error: String) -> Self {
        Self {
            is_valid: false,
            errors: vec![error],
            warnings: Vec::new(),
        }
    }

    /// Add an error to the validation result
    pub fn add_error(&mut self, error: String) {
        self.is_valid = false;
        self.errors.push(error);
    }

    /// Add a warning to the validation result
    pub fn add_warning(&mut self, warning: String) {
        self.warnings.push(warning);
    }

    /// Merge another validation result into this one
    pub fn merge(&mut self, other: ValidationResult) {
        if !other.is_valid {
            self.is_valid = false;
        }
        self.errors.extend(other.errors);
        self.warnings.extend(other.warnings);
    }
}

impl Default for ValidationResult {
    fn default() -> Self {
        Self {
            is_valid: false,
            errors: Vec::new(),
            warnings: Vec::new(),
        }
    }
}

/// Configuration constants
#[derive(Debug, Clone, Copy)]
pub struct ConfigConstants;

impl ConfigConstants {
    /// Default configuration file name
    pub const DEFAULT_CONFIG_FILE: &'static str = "smmu_config.conf";

    /// Backup configuration file name
    pub const BACKUP_CONFIG_FILE: &'static str = "smmu_config.conf.bak";

    /// Configuration version
    pub const CONFIG_VERSION: &'static str = "v1.0.0";

    /// Environment variable for config file
    pub const ENV_CONFIG_FILE: &'static str = "SMMU_CONFIG_FILE";

    /// Environment variable for queue size
    pub const ENV_QUEUE_SIZE: &'static str = "SMMU_QUEUE_SIZE";

    /// Environment variable for cache size
    pub const ENV_CACHE_SIZE: &'static str = "SMMU_CACHE_SIZE";

    /// Environment variable for memory limit
    pub const ENV_MEMORY_LIMIT: &'static str = "SMMU_MEMORY_LIMIT";
}

/// Global SMMU configuration combining all configuration types
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SMMUConfig {
    /// Queue configuration
    pub queue_config: QueueConfig,

    /// Cache configuration
    pub cache_config: CacheConfig,

    /// Address space configuration
    pub address_config: AddressConfig,

    /// Resource limits
    pub resource_limits: ResourceLimits,
}

impl SMMUConfig {
    /// Create a new builder for SMMUConfig
    #[must_use]
    pub fn builder() -> SMMUConfigBuilder {
        SMMUConfigBuilder::new()
    }

    /// Create a default configuration
    #[must_use]
    pub fn default_config() -> Self {
        Self::default()
    }

    /// Create a high-performance configuration
    #[must_use]
    pub fn high_performance() -> Self {
        Self {
            queue_config: QueueConfig {
                event_queue_size: 2048,
                command_queue_size: 1024,
                pri_queue_size: 512,
            },
            cache_config: CacheConfig {
                tlb_cache_size: 16_384,
                cache_max_age_ms: 10_000,
                enable_caching: true,
            },
            address_config: AddressConfig::default(),
            resource_limits: ResourceLimits::default(),
        }
    }

    /// Create a low-memory configuration
    #[must_use]
    pub fn low_memory() -> Self {
        Self {
            queue_config: QueueConfig {
                event_queue_size: 64,
                command_queue_size: 32,
                pri_queue_size: 16,
            },
            cache_config: CacheConfig {
                tlb_cache_size: 128,
                cache_max_age_ms: 2000,
                enable_caching: true,
            },
            address_config: AddressConfig {
                max_iova_bits: 32,
                max_pa_bits: 40,
                max_stream_count: 256,
                max_pasid_count: 1024,
            },
            resource_limits: ResourceLimits {
                max_memory_usage: 128 * 1024 * 1024, // 128MB
                max_thread_count: 2,
                timeout_ms: 500,
                enable_resource_tracking: true,
            },
        }
    }

    /// Create a minimal configuration
    #[must_use]
    pub fn minimal() -> Self {
        Self {
            queue_config: QueueConfig {
                event_queue_size: QueueConfig::MIN_QUEUE_SIZE,
                command_queue_size: QueueConfig::MIN_QUEUE_SIZE,
                pri_queue_size: QueueConfig::MIN_QUEUE_SIZE,
            },
            cache_config: CacheConfig {
                tlb_cache_size: CacheConfig::MIN_CACHE_SIZE,
                cache_max_age_ms: CacheConfig::MIN_CACHE_AGE_MS,
                enable_caching: false,
            },
            address_config: AddressConfig {
                max_iova_bits: 32,
                max_pa_bits: 32,
                max_stream_count: 1,
                max_pasid_count: 1,
            },
            resource_limits: ResourceLimits {
                max_memory_usage: ResourceLimits::MIN_MEMORY_USAGE,
                max_thread_count: ResourceLimits::MIN_THREAD_COUNT,
                timeout_ms: ResourceLimits::MIN_TIMEOUT_MS,
                enable_resource_tracking: false,
            },
        }
    }

    /// Create a server profile configuration
    #[must_use]
    pub fn server_profile() -> Self {
        Self {
            queue_config: QueueConfig {
                event_queue_size: 4096,
                command_queue_size: 2048,
                pri_queue_size: 1024,
            },
            cache_config: CacheConfig {
                tlb_cache_size: 32_768,
                cache_max_age_ms: 15_000,
                enable_caching: true,
            },
            address_config: AddressConfig::default(),
            resource_limits: ResourceLimits {
                max_memory_usage: 8 * 1024 * 1024 * 1024, // 8GB
                max_thread_count: 32,
                timeout_ms: 5000,
                enable_resource_tracking: true,
            },
        }
    }

    /// Create an embedded profile configuration
    #[must_use]
    pub fn embedded_profile() -> Self {
        Self {
            queue_config: QueueConfig {
                event_queue_size: 64,
                command_queue_size: 32,
                pri_queue_size: 16,
            },
            cache_config: CacheConfig {
                tlb_cache_size: 256,
                cache_max_age_ms: 2000,
                enable_caching: true,
            },
            address_config: AddressConfig {
                max_iova_bits: 32,
                max_pa_bits: 40,
                max_stream_count: 128,
                max_pasid_count: 256,
            },
            resource_limits: ResourceLimits {
                max_memory_usage: 64 * 1024 * 1024, // 64MB
                max_thread_count: 2,
                timeout_ms: 500,
                enable_resource_tracking: false,
            },
        }
    }

    /// Create a development profile configuration
    #[must_use]
    pub fn development_profile() -> Self {
        Self {
            queue_config: QueueConfig::default(),
            cache_config: CacheConfig::default(),
            address_config: AddressConfig::default(),
            resource_limits: ResourceLimits {
                max_memory_usage: 2 * 1024 * 1024 * 1024, // 2GB
                max_thread_count: 8,
                timeout_ms: 10_000, // Longer timeout for debugging
                enable_resource_tracking: true,
            },
        }
    }

    /// Update queue sizes
    pub fn update_queue_sizes(
        &mut self,
        event_size: usize,
        command_size: usize,
        pri_size: usize,
    ) -> Result<(), ValidationError> {
        let new_config = QueueConfig {
            event_queue_size: event_size,
            command_queue_size: command_size,
            pri_queue_size: pri_size,
        };
        new_config.validate()?;
        self.queue_config = new_config;
        Ok(())
    }

    /// Update cache settings
    pub fn update_cache_settings(
        &mut self,
        cache_size: usize,
        max_age: u32,
        enable: bool,
    ) -> Result<(), ValidationError> {
        let new_config = CacheConfig {
            tlb_cache_size: cache_size,
            cache_max_age_ms: max_age,
            enable_caching: enable,
        };
        new_config.validate()?;
        self.cache_config = new_config;
        Ok(())
    }

    /// Update address limits
    pub fn update_address_limits(
        &mut self,
        iova_bits: u8,
        pa_bits: u8,
        stream_count: u32,
        pasid_count: u32,
    ) -> Result<(), ValidationError> {
        let new_config = AddressConfig {
            max_iova_bits: iova_bits,
            max_pa_bits: pa_bits,
            max_stream_count: stream_count,
            max_pasid_count: pasid_count,
        };
        new_config.validate()?;
        self.address_config = new_config;
        Ok(())
    }

    /// Update resource limits
    pub fn update_resource_limits(
        &mut self,
        memory_usage: u64,
        thread_count: u32,
        timeout: u32,
    ) -> Result<(), ValidationError> {
        let new_limits = ResourceLimits {
            max_memory_usage: memory_usage,
            max_thread_count: thread_count,
            timeout_ms: timeout,
            enable_resource_tracking: self.resource_limits.enable_resource_tracking,
        };
        new_limits.validate()?;
        self.resource_limits = new_limits;
        Ok(())
    }

    /// Merge another configuration into this one
    pub fn merge(&mut self, other: &SMMUConfig) -> Result<(), ValidationError> {
        // Validate the other configuration first
        other.validate()?;

        // Merge configurations
        self.queue_config = other.queue_config.clone();
        self.cache_config = other.cache_config.clone();
        self.address_config = other.address_config.clone();
        self.resource_limits = other.resource_limits.clone();

        Ok(())
    }

    /// Reset to default configuration
    pub fn reset(&mut self) {
        *self = Self::default();
    }

    /// Validate entire configuration
    pub fn validate(&self) -> Result<(), ValidationError> {
        self.queue_config.validate()?;
        self.cache_config.validate()?;
        self.address_config.validate()?;
        self.resource_limits.validate()?;
        Ok(())
    }

    /// Set maximum streams (builder-style)
    #[must_use]
    pub fn with_max_streams(mut self, max_streams: usize) -> Self {
        self.address_config.max_stream_count = max_streams as u32;
        self
    }

    /// Get maximum streams
    #[inline]
    #[must_use]
    pub const fn max_streams(&self) -> usize {
        self.address_config.max_stream_count as usize
    }

    /// Get queue configuration
    #[inline]
    #[must_use]
    pub const fn queue_config(&self) -> &QueueConfig {
        &self.queue_config
    }

    /// Validate with detailed results
    #[must_use]
    pub fn validate_detailed(&self) -> ValidationResult {
        let mut result = ValidationResult::success();

        if let Err(e) = self.queue_config.validate() {
            result.add_error(format!("Queue config: {e:?}"));
        }

        if let Err(e) = self.cache_config.validate() {
            result.add_error(format!("Cache config: {e:?}"));
        }

        if let Err(e) = self.address_config.validate() {
            result.add_error(format!("Address config: {e:?}"));
        }

        if let Err(e) = self.resource_limits.validate() {
            result.add_error(format!("Resource limits: {e:?}"));
        }

        // Add warnings for minimal configurations
        if self.queue_config.event_queue_size < 128 {
            result.add_warning("Event queue size is very small".to_string());
        }

        if self.cache_config.tlb_cache_size < 256 {
            result.add_warning("TLB cache size is very small".to_string());
        }

        result
    }

    /// Convert configuration to string representation
    #[cfg(feature = "std")]
    #[must_use]
    pub fn to_string(&self) -> String {
        format!(
            "event_queue_size={}\ncommand_queue_size={}\npri_queue_size={}\n\
             tlb_cache_size={}\ncache_max_age_ms={}\nenable_caching={}\n\
             max_iova_bits={}\nmax_pa_bits={}\nmax_stream_count={}\nmax_pasid_count={}\n\
             max_memory_usage={}\nmax_thread_count={}\ntimeout_ms={}\nenable_resource_tracking={}",
            self.queue_config.event_queue_size,
            self.queue_config.command_queue_size,
            self.queue_config.pri_queue_size,
            self.cache_config.tlb_cache_size,
            self.cache_config.cache_max_age_ms,
            self.cache_config.enable_caching,
            self.address_config.max_iova_bits,
            self.address_config.max_pa_bits,
            self.address_config.max_stream_count,
            self.address_config.max_pasid_count,
            self.resource_limits.max_memory_usage,
            self.resource_limits.max_thread_count,
            self.resource_limits.timeout_ms,
            self.resource_limits.enable_resource_tracking,
        )
    }

    /// Parse configuration from string representation
    #[cfg(feature = "std")]
    pub fn from_string(s: &str) -> Result<Self, ValidationError> {
        let mut config = Self::default();
        let mut map = HashMap::new();

        // Parse key-value pairs
        for line in s.lines() {
            let line = line.trim();

            // Skip empty lines and comments
            if line.is_empty() || line.starts_with('#') {
                continue;
            }

            if let Some(pos) = line.find('=') {
                let key = line[..pos].trim();
                let value = line[pos + 1..].trim();
                map.insert(key.to_string(), value.to_string());
            }
        }

        // Parse queue configuration
        if let Some(v) = map.get("event_queue_size") {
            config.queue_config.event_queue_size = parse_numeric(v, "event_queue_size")?;
        }
        if let Some(v) = map.get("command_queue_size") {
            config.queue_config.command_queue_size = parse_numeric(v, "command_queue_size")?;
        }
        if let Some(v) = map.get("pri_queue_size") {
            config.queue_config.pri_queue_size = parse_numeric(v, "pri_queue_size")?;
        }

        // Parse cache configuration
        if let Some(v) = map.get("tlb_cache_size") {
            config.cache_config.tlb_cache_size = parse_numeric(v, "tlb_cache_size")?;
        }
        if let Some(v) = map.get("cache_max_age_ms") {
            config.cache_config.cache_max_age_ms = parse_numeric(v, "cache_max_age_ms")?;
        }
        if let Some(v) = map.get("enable_caching") {
            config.cache_config.enable_caching = v
                .parse()
                .map_err(|_| ValidationError::InvalidConfiguration { reason: "invalid enable_caching".into() })?;
        }

        // Parse address configuration
        if let Some(v) = map.get("max_iova_bits") {
            config.address_config.max_iova_bits = parse_numeric(v, "max_iova_bits")?;
        }
        if let Some(v) = map.get("max_pa_bits") {
            config.address_config.max_pa_bits = parse_numeric(v, "max_pa_bits")?;
        }
        if let Some(v) = map.get("max_stream_count") {
            config.address_config.max_stream_count = parse_numeric(v, "max_stream_count")?;
        }
        if let Some(v) = map.get("max_pasid_count") {
            config.address_config.max_pasid_count = parse_numeric(v, "max_pasid_count")?;
        }

        // Parse resource limits
        if let Some(v) = map.get("max_memory_usage") {
            config.resource_limits.max_memory_usage = parse_numeric(v, "max_memory_usage")?;
        }
        if let Some(v) = map.get("max_thread_count") {
            config.resource_limits.max_thread_count = parse_numeric(v, "max_thread_count")?;
        }
        if let Some(v) = map.get("timeout_ms") {
            config.resource_limits.timeout_ms = parse_numeric(v, "timeout_ms")?;
        }
        if let Some(v) = map.get("enable_resource_tracking") {
            config.resource_limits.enable_resource_tracking =
                v.parse().map_err(|_| ValidationError::InvalidConfiguration {
                    reason: "invalid enable_resource_tracking".into(),
                })?;
        }

        // Validate the final configuration
        config.validate()?;
        Ok(config)
    }
}

impl Default for SMMUConfig {
    fn default() -> Self {
        Self {
            queue_config: QueueConfig::default(),
            cache_config: CacheConfig::default(),
            address_config: AddressConfig::default(),
            resource_limits: ResourceLimits::default(),
        }
    }
}

/// Builder for SMMUConfig
#[derive(Clone, Debug)]
pub struct SMMUConfigBuilder {
    queue_config: QueueConfig,
    cache_config: CacheConfig,
    address_config: AddressConfig,
    resource_limits: ResourceLimits,
}

impl SMMUConfigBuilder {
    /// Create a new builder with default values
    #[must_use]
    pub fn new() -> Self {
        Self {
            queue_config: QueueConfig::default(),
            cache_config: CacheConfig::default(),
            address_config: AddressConfig::default(),
            resource_limits: ResourceLimits::default(),
        }
    }

    /// Set queue configuration
    #[must_use]
    pub fn queue_config(mut self, config: QueueConfig) -> Self {
        self.queue_config = config;
        self
    }

    /// Set cache configuration
    #[must_use]
    pub fn cache_config(mut self, config: CacheConfig) -> Self {
        self.cache_config = config;
        self
    }

    /// Set address configuration
    #[must_use]
    pub fn address_config(mut self, config: AddressConfig) -> Self {
        self.address_config = config;
        self
    }

    /// Set resource limits
    #[must_use]
    pub fn resource_limits(mut self, limits: ResourceLimits) -> Self {
        self.resource_limits = limits;
        self
    }

    /// Build the SMMUConfig with validation
    #[must_use]
    pub fn build(self) -> Result<SMMUConfig, ValidationError> {
        let config = SMMUConfig {
            queue_config: self.queue_config,
            cache_config: self.cache_config,
            address_config: self.address_config,
            resource_limits: self.resource_limits,
        };

        config.validate()?;
        Ok(config)
    }
}

impl Default for SMMUConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// Convert QueueConfig to SMMUConfig
///
/// Creates a default SMMUConfig with the specified queue configuration.
impl From<QueueConfig> for SMMUConfig {
    fn from(queue_config: QueueConfig) -> Self {
        SMMUConfig {
            queue_config,
            cache_config: CacheConfig::default(),
            address_config: AddressConfig::default(),
            resource_limits: ResourceLimits::default(),
        }
    }
}

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

    // ========================================================================
    // Unit tests for existing config structures
    // ========================================================================

    #[test]
    fn test_queue_config_validation() {
        let config = QueueConfig::default();
        assert!(config.validate().is_ok());
    }

    #[test]
    fn test_cache_config_validation() {
        let config = CacheConfig::default();
        assert!(config.validate().is_ok());
    }

    #[test]
    fn test_address_config_validation() {
        let config = AddressConfig::default();
        assert!(config.validate().is_ok());
    }

    #[test]
    fn test_smmu_config_validation() {
        let config = SMMUConfig::default();
        assert!(config.validate().is_ok());
    }

    // ========================================================================
    // FAILING TESTS for missing ResourceLimits structure
    // These will fail until ResourceLimits is implemented
    // ========================================================================

    #[test]
    fn test_resource_limits_default_construction() {
        let _limits = ResourceLimits::default();
    }

    #[test]
    fn test_resource_limits_builder() {
        let _limits = ResourceLimits::builder()
            .max_memory_usage(1024 * 1024 * 1024)
            .max_thread_count(8)
            .timeout_ms(1000)
            .enable_resource_tracking(true)
            .build();
    }

    #[test]
    fn test_resource_limits_validation() {
        let limits = ResourceLimits::default();
        assert!(limits.validate().is_ok());
    }

    #[test]
    fn test_resource_limits_constants() {
        assert_eq!(ResourceLimits::MIN_MEMORY_USAGE, 1024 * 1024);
        assert_eq!(ResourceLimits::MAX_MEMORY_USAGE, 64 * 1024 * 1024 * 1024);
    }

    // ========================================================================
    // FAILING TESTS for missing SMMUConfig extended methods
    // These will fail until extended methods are implemented
    // ========================================================================

    #[test]
    fn test_smmu_config_server_profile() {
        let _config = SMMUConfig::server_profile();
    }

    #[test]
    fn test_smmu_config_embedded_profile() {
        let _config = SMMUConfig::embedded_profile();
    }

    #[test]
    fn test_smmu_config_development_profile() {
        let _config = SMMUConfig::development_profile();
    }

    #[test]
    fn test_smmu_config_update_queue_sizes() {
        let mut config = SMMUConfig::default();
        assert!(config.update_queue_sizes(1024, 512, 256).is_ok());
    }

    #[test]
    fn test_smmu_config_update_cache_settings() {
        let mut config = SMMUConfig::default();
        assert!(config.update_cache_settings(2048, 10_000, true).is_ok());
    }

    #[test]
    fn test_smmu_config_update_address_limits() {
        let mut config = SMMUConfig::default();
        assert!(config.update_address_limits(40, 44, 1024, 2048).is_ok());
    }

    #[test]
    fn test_smmu_config_update_resource_limits() {
        let mut config = SMMUConfig::default();
        assert!(config.update_resource_limits(2 * 1024 * 1024 * 1024, 16, 2000).is_ok());
    }

    #[test]
    fn test_smmu_config_merge() {
        let mut base = SMMUConfig::default();
        let overlay = SMMUConfig::high_performance();
        assert!(base.merge(&overlay).is_ok());
    }

    #[test]
    fn test_smmu_config_reset() {
        let mut config = SMMUConfig::high_performance();
        config.reset();
        assert_eq!(config, SMMUConfig::default());
    }

    #[test]
    fn test_smmu_config_to_string() {
        let config = SMMUConfig::default();
        let _config_str = config.to_string();
    }

    #[test]
    fn test_smmu_config_from_string() {
        let config_str = "event_queue_size=1024\ntlb_cache_size=2048";
        let _config = SMMUConfig::from_string(config_str);
    }

    #[test]
    fn test_smmu_config_validate_detailed() {
        let config = SMMUConfig::default();
        let result = config.validate_detailed();
        assert!(result.is_valid);
    }

    // ========================================================================
    // FAILING TESTS for missing ConfigurationError types
    // These will fail until ConfigurationError is implemented
    // ========================================================================

    #[test]
    fn test_configuration_error_construction() {
        let _error = ConfigurationError::new(
            ConfigurationErrorType::InvalidQueueSize,
            "event_queue_size".to_string(),
            "value out of range".to_string(),
        );
    }

    #[test]
    fn test_configuration_error_types_exist() {
        let _types = [
            ConfigurationErrorType::InvalidQueueSize,
            ConfigurationErrorType::InvalidCacheSize,
            ConfigurationErrorType::InvalidAddressSize,
            ConfigurationErrorType::InvalidResourceLimit,
            ConfigurationErrorType::InvalidFormat,
            ConfigurationErrorType::MissingRequired,
            ConfigurationErrorType::OutOfRange,
        ];
    }

    // ========================================================================
    // FAILING TESTS for missing ValidationResult structure
    // These will fail until ValidationResult is implemented
    // ========================================================================

    #[test]
    fn test_validation_result_success() {
        let result = ValidationResult::success();
        assert!(result.is_valid);
        assert!(result.errors.is_empty());
    }

    #[test]
    fn test_validation_result_with_error() {
        let result = ValidationResult::with_error("test error".to_string());
        assert!(!result.is_valid);
        assert_eq!(result.errors.len(), 1);
    }

    #[test]
    fn test_validation_result_add_warning() {
        let mut result = ValidationResult::success();
        result.add_warning("test warning".to_string());
        assert!(result.is_valid);
        assert_eq!(result.warnings.len(), 1);
    }

    // ========================================================================
    // FAILING TESTS for missing ConfigConstants
    // These will fail until ConfigConstants is implemented
    // ========================================================================

    #[test]
    fn test_config_constants_default_file() {
        assert_eq!(ConfigConstants::DEFAULT_CONFIG_FILE, "smmu_config.conf");
    }

    #[test]
    fn test_config_constants_env_vars() {
        assert_eq!(ConfigConstants::ENV_CONFIG_FILE, "SMMU_CONFIG_FILE");
        assert_eq!(ConfigConstants::ENV_QUEUE_SIZE, "SMMU_QUEUE_SIZE");
    }

    #[test]
    fn test_config_constants_version() {
        assert!(!ConfigConstants::CONFIG_VERSION.is_empty());
    }
}
