//! Configuration types for LatticeArc cryptographic operations.
//!
//! Provides hierarchical configuration for encryption, signatures, zero-trust
//! authentication, and hardware acceleration. All types are pure Rust with
//! zero FFI dependencies.

use crate::types::{
    PerformancePreference, SecurityLevel, UseCase,
    error::{Result, TypeError},
};

/// Core cryptographic configuration settings.
///
/// This struct provides the foundational configuration that all specialized
/// configurations inherit from. Settings here affect all cryptographic operations.
///
/// # Security Level
/// - `Standard`: 128-bit security, suitable for most applications
/// - `High`: 192-bit security, recommended for sensitive data
/// - `Maximum`: 256-bit security, for high-value assets
///
/// # Examples
/// ```rust
/// use latticearc::types::config::CoreConfig;
/// use latticearc::types::types::{SecurityLevel, PerformancePreference};
///
/// // Create a high-security configuration
/// let config = CoreConfig::new()
///     .with_security_level(SecurityLevel::High)
///     .with_performance_preference(PerformancePreference::Balanced)
///     .build()
///     .expect("Failed to build config");
///
/// // Use for development with relaxed settings
/// let dev_config = CoreConfig::for_development();
///
/// // Use for production with maximum security
/// let prod_config = CoreConfig::for_production();
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CoreConfig {
    /// Security level for cryptographic operations.
    ///
    /// Higher security levels provide stronger protection but may impact performance.
    /// Default: `SecurityLevel::High`
    ///
    /// Consumer: `CryptoPolicyEngine::select_encryption_scheme()`, `select_signature_scheme()`, `select_encryption_scheme_typed()`
    pub security_level: SecurityLevel,

    /// Performance preference for cryptographic operations.
    ///
    /// Affects algorithm selection and optimization strategies.
    /// Default: `PerformancePreference::Balanced`
    ///
    /// Consumer: `CryptoPolicyEngine::select_encryption_scheme()`
    pub performance_preference: PerformancePreference,

    /// Whether hardware acceleration is enabled.
    ///
    /// Uses CPU features like AVX2/AVX-512 or GPU acceleration when available.
    /// Default: `true`
    ///
    /// Consumer: `CryptoPolicyEngine::select_encryption_scheme()` — unused since audit (all levels now return hybrid PQC)
    pub hardware_acceleration: bool,

    /// Whether fallback to software implementations is enabled.
    ///
    /// If hardware acceleration fails, fallback to portable software implementations.
    /// Default: `true`
    ///
    /// Consumer: `CoreConfig::validate()`
    pub fallback_enabled: bool,

    /// Whether strict validation is enabled.
    ///
    /// Performs additional validation checks that may impact performance.
    /// Default: `true`
    ///
    /// Consumer: `CoreConfig::validate()`
    pub strict_validation: bool,
}

impl Default for CoreConfig {
    fn default() -> Self {
        Self {
            security_level: SecurityLevel::High,
            performance_preference: PerformancePreference::Balanced,
            hardware_acceleration: true,
            fallback_enabled: true,
            strict_validation: true,
        }
    }
}

impl CoreConfig {
    /// Create a new configuration with sensible defaults.
    ///
    /// This provides a balanced configuration suitable for most applications.
    /// For specific use cases, use the builder methods or environment-specific constructors.
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    /// Create a configuration optimized for development.
    ///
    /// Uses relaxed security settings to prioritize development speed over security.
    /// Not suitable for production use.
    #[must_use]
    pub fn for_development() -> Self {
        Self::default().with_security_level(SecurityLevel::Standard).with_strict_validation(false)
    }

    /// Create a configuration optimized for production.
    ///
    /// Uses maximum security settings suitable for production environments.
    #[must_use]
    pub fn for_production() -> Self {
        Self::default().with_security_level(SecurityLevel::Maximum).with_strict_validation(true)
    }

    /// Set the security level and return self for method chaining.
    #[must_use]
    pub fn with_security_level(mut self, level: SecurityLevel) -> Self {
        self.security_level = level;
        self
    }

    /// Set the performance preference and return self for method chaining.
    #[must_use]
    pub fn with_performance_preference(mut self, preference: PerformancePreference) -> Self {
        self.performance_preference = preference;
        self
    }

    /// Set hardware acceleration and return self for method chaining.
    #[must_use]
    pub fn with_hardware_acceleration(mut self, enabled: bool) -> Self {
        self.hardware_acceleration = enabled;
        self
    }

    /// Set fallback mode and return self for method chaining.
    #[must_use]
    pub fn with_fallback(mut self, enabled: bool) -> Self {
        self.fallback_enabled = enabled;
        self
    }

    /// Set strict validation and return self for method chaining.
    #[must_use]
    pub fn with_strict_validation(mut self, enabled: bool) -> Self {
        self.strict_validation = enabled;
        self
    }

    /// Build and validate the configuration.
    ///
    /// Performs comprehensive validation of the configuration and returns
    /// a validated configuration ready for use.
    ///
    /// # Errors
    ///
    /// Returns an error if:
    /// - Strict validation is enabled with `SecurityLevel::Standard`
    /// - Speed performance preference is configured without fallback enabled
    pub fn build(self) -> Result<Self> {
        self.validate()?;
        Ok(self)
    }

    /// Validates the configuration settings.
    ///
    /// # Errors
    ///
    /// Returns an error if:
    /// - Strict validation is enabled with `SecurityLevel::Standard` (requires at least `High`)
    /// - Speed performance preference is configured without fallback enabled
    pub fn validate(&self) -> Result<()> {
        if self.strict_validation && matches!(self.security_level, SecurityLevel::Standard) {
            return Err(TypeError::ConfigurationError(
                "Strict validation mode requires SecurityLevel::High or above. \
                 SecurityLevel::Standard (NIST Level 1) is not permitted in strict mode."
                    .to_string(),
            ));
        }

        if matches!(self.performance_preference, PerformancePreference::Speed)
            && !self.fallback_enabled
        {
            return Err(TypeError::ConfigurationError(
                "Speed preference should have fallback enabled for reliability".to_string(),
            ));
        }

        Ok(())
    }
}

/// Configuration for encryption operations.
///
/// Wraps [`CoreConfig`] for encryption-specific use cases.
///
/// Backwards-compatible alias (was a single-field wrapper around `CoreConfig`).
pub type EncryptionConfig = CoreConfig;

/// Backwards-compatible alias (was a single-field wrapper around `CoreConfig`).
pub type SignatureConfig = CoreConfig;

/// Configuration for zero-trust authentication operations.
///
/// Extends [`CoreConfig`] with settings for challenge-response authentication,
/// proof complexity, and continuous verification intervals.
#[derive(Debug, Clone)]
pub struct ZeroTrustConfig {
    /// Base configuration inherited from [`CoreConfig`].
    ///
    /// Consumer: `ZeroTrustAuth::new()`
    pub base: CoreConfig,
    /// Timeout in milliseconds for challenge responses.
    ///
    /// Consumer: `ZeroTrustAuth::initiate_authentication()`
    pub challenge_timeout_ms: u64,
    /// Complexity level for zero-knowledge proofs.
    ///
    /// Consumer: `ZeroTrustAuth::generate_proof()`, `verify_proof_data()`
    pub proof_complexity: ProofComplexity,
    /// Whether continuous session verification is enabled.
    ///
    /// Consumer: `ContinuousSession::new()`
    pub continuous_verification: bool,
    /// Interval in milliseconds between verification checks.
    ///
    /// Consumer: `ContinuousSession::check_session_validity()`
    pub verification_interval_ms: u64,
}

impl Default for ZeroTrustConfig {
    fn default() -> Self {
        Self {
            base: CoreConfig::default(),
            challenge_timeout_ms: 5000,
            proof_complexity: ProofComplexity::Medium,
            continuous_verification: true,
            verification_interval_ms: 30000,
        }
    }
}

impl ZeroTrustConfig {
    /// Creates a new zero-trust configuration with default settings.
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    /// Sets the challenge timeout in milliseconds.
    #[must_use]
    pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
        self.challenge_timeout_ms = timeout_ms;
        self
    }

    /// Sets the proof complexity level.
    #[must_use]
    pub fn with_complexity(mut self, complexity: ProofComplexity) -> Self {
        self.proof_complexity = complexity;
        self
    }

    /// Enables or disables continuous session verification.
    #[must_use]
    pub fn with_continuous_verification(mut self, enabled: bool) -> Self {
        self.continuous_verification = enabled;
        self
    }

    /// Sets the verification interval in milliseconds.
    #[must_use]
    pub fn with_verification_interval(mut self, interval_ms: u64) -> Self {
        self.verification_interval_ms = interval_ms;
        self
    }

    /// Validates the zero-trust configuration settings.
    ///
    /// # Errors
    ///
    /// Returns an error if:
    /// - The base configuration validation fails
    /// - Challenge timeout is set to zero
    /// - Continuous verification is enabled with a zero verification interval
    pub fn validate(&self) -> Result<()> {
        self.base.validate()?;

        if self.challenge_timeout_ms == 0 {
            return Err(TypeError::ConfigurationError(
                "Challenge timeout cannot be zero".to_string(),
            ));
        }

        if self.continuous_verification && self.verification_interval_ms == 0 {
            return Err(TypeError::ConfigurationError(
                "Continuous verification requires non-zero interval".to_string(),
            ));
        }

        Ok(())
    }
}

/// Complexity level for zero-knowledge proofs.
///
/// Higher complexity provides stronger security guarantees but requires
/// more computation and bandwidth.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(kani, derive(kani::Arbitrary))]
pub enum ProofComplexity {
    /// Low complexity: 32-byte challenges, basic verification.
    Low,
    /// Medium complexity: 64-byte challenges with timestamp binding.
    Medium,
    /// High complexity: 128-byte challenges with timestamp and public key binding.
    High,
}

/// Configuration tailored for a specific use case.
///
/// Combines encryption, signature, and zero-trust configurations
/// with settings optimized for the given use case.
///
/// **Note:** `UseCaseConfig` is not yet wired to the unified `encrypt()`/`sign_with_key()` API.
/// For use-case-based algorithm selection, use `CryptoConfig::new().use_case(UseCase::...)`.
/// `UseCaseConfig` remains available for advanced per-component configuration.
#[derive(Debug, Clone)]
pub struct UseCaseConfig {
    /// The use case this configuration is optimized for.
    ///
    /// Consumer: None — reserved for unified API integration
    pub use_case: UseCase,
    /// Encryption configuration for this use case.
    ///
    /// Consumer: None — reserved for unified API integration
    pub encryption: CoreConfig,
    /// Signature configuration for this use case.
    ///
    /// Consumer: None — reserved for unified API integration
    pub signature: CoreConfig,
    /// Zero-trust configuration for this use case.
    ///
    /// Consumer: None — reserved for unified API integration
    pub zero_trust: ZeroTrustConfig,
}

impl UseCaseConfig {
    /// Creates a new configuration optimized for the specified use case.
    #[must_use]
    pub fn new(use_case: UseCase) -> Self {
        let base_config = match use_case {
            // Communication: Low latency requirements
            UseCase::SecureMessaging | UseCase::ApiSecurity => {
                CoreConfig::new().with_performance_preference(PerformancePreference::Speed)
            }
            UseCase::EmailEncryption => CoreConfig::new().with_security_level(SecurityLevel::High),
            UseCase::VpnTunnel => CoreConfig::new()
                .with_performance_preference(PerformancePreference::Speed)
                .with_hardware_acceleration(true),

            // Storage: Long-term security
            UseCase::FileStorage | UseCase::CloudStorage | UseCase::BackupArchive => {
                CoreConfig::new().with_security_level(SecurityLevel::Maximum)
            }
            UseCase::DatabaseEncryption | UseCase::ConfigSecrets => {
                CoreConfig::new().with_performance_preference(PerformancePreference::Memory)
            }

            // Authentication & Identity
            UseCase::Authentication | UseCase::DigitalCertificate => {
                CoreConfig::new().with_security_level(SecurityLevel::Maximum)
            }
            UseCase::SessionToken => {
                CoreConfig::new().with_performance_preference(PerformancePreference::Speed)
            }
            UseCase::KeyExchange => CoreConfig::new().with_security_level(SecurityLevel::Maximum),

            // Financial & Legal: Highest security
            UseCase::FinancialTransactions | UseCase::LegalDocuments => {
                CoreConfig::new().with_security_level(SecurityLevel::Maximum)
            }
            UseCase::BlockchainTransaction => {
                CoreConfig::new().with_performance_preference(PerformancePreference::Balanced)
            }

            // Regulated Industries: Maximum security + compliance
            UseCase::HealthcareRecords | UseCase::GovernmentClassified | UseCase::PaymentCard => {
                CoreConfig::new().with_security_level(SecurityLevel::Maximum)
            }

            // IoT & Embedded: Resource-constrained (strict validation off for Standard level)
            UseCase::IoTDevice => CoreConfig::new()
                .with_security_level(SecurityLevel::Standard)
                .with_performance_preference(PerformancePreference::Memory)
                .with_strict_validation(false),
            UseCase::FirmwareSigning => CoreConfig::new().with_security_level(SecurityLevel::High),

            // General Purpose
            UseCase::AuditLog => CoreConfig::new().with_security_level(SecurityLevel::High),
        };

        Self {
            use_case,
            encryption: base_config.clone(),
            signature: base_config.clone(),
            zero_trust: ZeroTrustConfig { base: base_config, ..Default::default() },
        }
    }

    /// Validates all nested configuration settings for the use case.
    ///
    /// # Errors
    ///
    /// Returns an error if any of the nested configurations fail validation:
    /// - Encryption `CoreConfig` validation fails
    /// - Signature `CoreConfig` validation fails
    /// - Zero-trust configuration validation fails
    pub fn validate(&self) -> Result<()> {
        self.encryption.validate()?;
        self.signature.validate()?;
        self.zero_trust.validate()?;
        Ok(())
    }
}

#[cfg(kani)]
impl kani::Arbitrary for CoreConfig {
    fn any() -> Self {
        Self {
            security_level: kani::any(),
            performance_preference: kani::any(),
            hardware_acceleration: kani::any(),
            fallback_enabled: kani::any(),
            strict_validation: kani::any(),
        }
    }
}

// Formal verification with Kani
#[cfg(kani)]
mod kani_proofs {
    use super::*;

    /// Proves CoreConfig::default() always passes validation.
    /// Security: default configuration must always be safe.
    #[kani::proof]
    fn core_config_default_validates() {
        let config = CoreConfig::default();
        kani::assert(config.validate().is_ok(), "Default CoreConfig must validate");
    }

    /// Proves for_production() always passes validation.
    #[kani::proof]
    fn core_config_for_production_validates() {
        let config = CoreConfig::for_production();
        kani::assert(config.validate().is_ok(), "Production config must validate");
    }

    /// Proves for_development() always passes validation.
    #[kani::proof]
    fn core_config_for_development_validates() {
        let config = CoreConfig::for_development();
        kani::assert(config.validate().is_ok(), "Development config must validate");
    }

    /// BI-CONDITIONAL: For ANY CoreConfig, validate() succeeds IFF
    /// both safety invariants hold. This is the most powerful proof —
    /// it verifies validation has no false positives AND no false negatives.
    /// Exhaustive over all CoreConfig combinations.
    #[kani::proof]
    fn core_config_validation_biconditional() {
        let config: CoreConfig = kani::any();
        let result = config.validate();

        let should_pass = !((config.strict_validation
            && matches!(config.security_level, SecurityLevel::Standard))
            || (matches!(config.performance_preference, PerformancePreference::Speed)
                && !config.fallback_enabled));

        kani::assert(result.is_ok() == should_pass, "validate() passes iff both invariants hold");
    }

    // EncryptionConfig/SignatureConfig Kani proofs removed — they are now type
    // aliases for CoreConfig, so core_config_validates_with_valid_inputs already covers them.
}

#[cfg(test)]
#[allow(
    clippy::panic,
    clippy::unwrap_used,
    clippy::expect_used,
    clippy::indexing_slicing,
    clippy::arithmetic_side_effects,
    clippy::panic_in_result_fn,
    clippy::unnecessary_wraps,
    clippy::redundant_clone,
    clippy::useless_vec,
    clippy::cast_possible_truncation,
    clippy::cast_sign_loss,
    clippy::clone_on_copy,
    clippy::len_zero,
    clippy::single_match,
    clippy::unnested_or_patterns,
    clippy::default_constructed_unit_structs,
    clippy::redundant_closure_for_method_calls,
    clippy::semicolon_if_nothing_returned,
    clippy::unnecessary_unwrap,
    clippy::redundant_pattern_matching,
    clippy::missing_const_for_thread_local,
    clippy::get_first,
    clippy::float_cmp,
    clippy::needless_borrows_for_generic_args,
    unused_qualifications,
    deprecated
)]
mod tests {
    use super::*;

    #[test]
    fn test_core_config_default_fields_are_correct() {
        let config = CoreConfig::new();
        assert_eq!(config.security_level, SecurityLevel::High);
        assert_eq!(config.performance_preference, PerformancePreference::Balanced);
        assert!(config.hardware_acceleration);
        assert!(config.fallback_enabled);
        assert!(config.strict_validation);
    }

    #[test]
    fn test_core_config_for_development_succeeds() {
        let config = CoreConfig::for_development();
        assert_eq!(config.security_level, SecurityLevel::Standard);
        assert!(!config.strict_validation);
    }

    #[test]
    fn test_core_config_for_production_succeeds() {
        let config = CoreConfig::for_production();
        assert_eq!(config.security_level, SecurityLevel::Maximum);
        assert!(config.strict_validation);
    }

    #[test]
    fn test_core_config_builder_pattern_succeeds() {
        let config = CoreConfig::new()
            .with_security_level(SecurityLevel::Maximum)
            .with_performance_preference(PerformancePreference::Speed)
            .with_hardware_acceleration(true)
            .with_fallback(true)
            .with_strict_validation(true);
        assert_eq!(config.security_level, SecurityLevel::Maximum);
        assert_eq!(config.performance_preference, PerformancePreference::Speed);
    }

    #[test]
    fn test_core_config_validation_success_succeeds() -> Result<()> {
        let config = CoreConfig::new().with_security_level(SecurityLevel::Maximum);
        config.validate()?;
        Ok(())
    }

    #[test]
    fn test_core_config_strict_validation_rejects_standard_fails() {
        let config = CoreConfig::new()
            .with_security_level(SecurityLevel::Standard)
            .with_strict_validation(true);
        let result = config.validate();
        assert!(result.is_err());
    }

    #[test]
    fn test_core_config_strict_validation_allows_high_succeeds() -> Result<()> {
        let config =
            CoreConfig::new().with_security_level(SecurityLevel::High).with_strict_validation(true);
        config.validate()?;
        Ok(())
    }

    #[test]
    fn test_core_config_build_success_succeeds() -> Result<()> {
        let config = CoreConfig::new()
            .with_security_level(SecurityLevel::High)
            .with_hardware_acceleration(true)
            .build()?;
        assert_eq!(config.security_level, SecurityLevel::High);
        Ok(())
    }

    #[test]
    fn test_encryption_config_is_core_config_succeeds() {
        // EncryptionConfig is now a type alias for CoreConfig
        let config = EncryptionConfig::default();
        assert_eq!(config.security_level, SecurityLevel::High);
        assert!(config.validate().is_ok());
    }

    #[test]
    fn test_signature_config_is_core_config_succeeds() {
        // SignatureConfig is now a type alias for CoreConfig
        let config = SignatureConfig::default();
        assert_eq!(config.security_level, SecurityLevel::High);
        assert!(config.validate().is_ok());
    }

    #[test]
    fn test_zero_trust_config_default_fields_are_correct() {
        let config = ZeroTrustConfig::default();
        assert_eq!(config.challenge_timeout_ms, 5000);
        assert_eq!(config.proof_complexity, ProofComplexity::Medium);
        assert!(config.continuous_verification);
    }

    #[test]
    fn test_use_case_config_financial_transactions_selects_maximum_security_succeeds() {
        let config = UseCaseConfig::new(UseCase::FinancialTransactions);
        assert_eq!(config.use_case, UseCase::FinancialTransactions);
        assert_eq!(config.encryption.security_level, SecurityLevel::Maximum);
    }

    #[test]
    fn test_use_case_config_iot_device_succeeds() {
        let config = UseCaseConfig::new(UseCase::IoTDevice);
        assert_eq!(config.encryption.security_level, SecurityLevel::Standard);
        assert_eq!(config.encryption.performance_preference, PerformancePreference::Memory);
    }

    // =========================================================================
    // Parameter Influence Tests (Audit 4.12)
    // =========================================================================

    #[test]
    fn test_strict_validation_rejects_standard_security_level_fails() {
        // strict_validation=true + Standard → error
        let config = CoreConfig::new()
            .with_strict_validation(true)
            .with_security_level(SecurityLevel::Standard);
        assert!(config.validate().is_err());
    }

    #[test]
    fn test_strict_validation_accepts_high_security_level_succeeds() {
        // strict_validation=true + High → ok
        let config =
            CoreConfig::new().with_strict_validation(true).with_security_level(SecurityLevel::High);
        assert!(config.validate().is_ok());
    }

    #[test]
    fn test_strict_validation_false_accepts_standard_security_level_succeeds() {
        // strict_validation=false + Standard → ok (parameter changes outcome)
        let config = CoreConfig::new()
            .with_strict_validation(false)
            .with_security_level(SecurityLevel::Standard);
        assert!(config.validate().is_ok());
    }
}
