//! # cachewrap - Distributed Cache Client Library
//!
//! A simple Redis cache client wrapper demonstrating common caching patterns.
//!
//! ## ⚠️ INTENTIONAL VIOLATIONS (Dogfooding Exercise)
//!
//! This library contains **10 intentional violations** for Aphoria detection:
//!
//! ### Security Violations (3):
//! 1. **Key injection vulnerability** (`client.rs:get()`) - No key validation → Data breach, cache poisoning
//! 2. **TLS verification disabled** (`config.rs:verify_tls = false`) - No cert validation → MITM attacks
//! 3. **Hardcoded credentials** (`config.rs:password = "secret123"`) - Plaintext in source → Credential exposure
//!
//! ### Performance Violations (3):
//! 4. **Missing TTL** (`client.rs:set()`) - No expiration → Memory leak, unbounded growth
//! 5. **Unbounded cache size** (`config.rs:max_size = None`) - No limit → OOM under load
//! 6. **Synchronous blocking** (`client.rs:blocking_get()`) - Blocks async runtime → Throughput collapse
//!
//! ### Correctness Violations (3):
//! 7. **No eviction policy** (`config.rs:eviction_policy = None`) - Undefined behavior when full
//! 8. **Zero timeout** (`config.rs:timeout = 0`) - Indefinite blocking → Hung threads
//! 9. **No connection pooling** (`client.rs:get/set/delete()`) - New conn per request → Resource exhaustion
//!
//! ### Observability Violation (1):
//! 10. **No metrics** (`config.rs:metrics_enabled = false`) - Missing hit/miss tracking → Debugging impossible
//!
//! ## Usage
//!
//! ```rust,no_run
//! use cachewrap::{CacheClient, CacheConfig};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     let config = CacheConfig::new("redis://127.0.0.1:6379".to_string());
//!     let client = CacheClient::new(config).await?;
//!
//!     // Set a value (⚠️ no TTL - violation!)
//!     client.set("mykey", "myvalue").await?;
//!
//!     // Get a value (⚠️ no key validation - violation!)
//!     if let Some(value) = client.get("mykey").await? {
//!         println!("Got value: {}", value);
//!     }
//!
//!     Ok(())
//! }
//! ```
//!
//! ## Fixing the Violations (Day 4)
//!
//! These violations will be fixed progressively in Day 4:
//! - Add key validation (regex for control chars, length limits)
//! - Enable TLS verification (`verify_tls: true`)
//! - Load credentials from environment (`std::env::var("REDIS_PASSWORD")`)
//! - Always set TTL (`set_ex()` instead of `set()`)
//! - Configure max_size (`Some(1000)`)
//! - Remove blocking methods or use `spawn_blocking`
//! - Set eviction policy (`Some(EvictionPolicy::LRU)`)
//! - Set non-zero timeout (`Duration::from_secs(5)`)
//! - Use connection pool (r2d2-redis or bb8-redis)
//! - Enable metrics tracking (hit_count, miss_count, latency)

pub mod client;
pub mod config;
pub mod error;

pub use client::CacheClient;
pub use config::{CacheConfig, EvictionPolicy};
pub use error::{CacheError, Result};

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

    #[test]
    fn test_config_default() {
        let config = CacheConfig::default();
        assert_eq!(config.url, "redis://127.0.0.1:6379");
        assert_eq!(config.password, ""); // ✅ From env (empty if not set)
        assert!(config.verify_tls); // ✅ Enabled
        assert_eq!(config.timeout.as_secs(), 5); // ✅ 5 second timeout
        assert_eq!(config.max_size, Some(1000 * 1024 * 1024)); // ✅ 1GB limit
        assert_eq!(config.eviction_policy, Some(EvictionPolicy::LRU)); // ✅ LRU policy
        assert!(config.metrics_enabled); // ✅ Metrics enabled
    }

    #[test]
    fn test_config_builder() {
        let config = CacheConfig::new("redis://localhost:6379".to_string())
            .with_password("newpass".to_string())
            .with_tls_verification(true)
            .with_timeout(std::time::Duration::from_secs(5))
            .with_max_size(1000)
            .with_eviction_policy(EvictionPolicy::LRU)
            .with_metrics(true)
            .with_max_connections(20);

        assert_eq!(config.url, "redis://localhost:6379");
        assert_eq!(config.password, "newpass");
        assert!(config.verify_tls);
        assert_eq!(config.timeout.as_secs(), 5);
        assert_eq!(config.max_size, Some(1000));
        assert_eq!(config.eviction_policy, Some(EvictionPolicy::LRU));
        assert!(config.metrics_enabled);
        assert_eq!(config.max_connections, 20);
    }

    #[test]
    fn test_eviction_policy_variants() {
        assert_eq!(EvictionPolicy::LRU, EvictionPolicy::LRU);
        assert_ne!(EvictionPolicy::LRU, EvictionPolicy::LFU);
        assert_ne!(EvictionPolicy::LFU, EvictionPolicy::TTL);
    }
}
