//! HTTP Client Configuration
//!
//! **INTENTIONAL VIOLATIONS IN THIS FILE:**
//! - VIOLATION 1: Unbounded redirect limit (max_redirects = None)
//! - VIOLATION 2: Excessive request timeout (120s vs 30s max)
//! - VIOLATION 3: Excessive connection timeout (60s vs 10s max)
//! - VIOLATION 4: Missing idle timeout (idle_timeout = None)
//! - VIOLATION 5: TLS verification disabled (verify_tls = false)
//! - VIOLATION 6: TLS version too low (min_tls_version = TLS 1.0)

use serde::{Deserialize, Serialize};
use std::time::Duration;

/// TLS protocol version
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum TlsVersion {
    #[serde(rename = "1.0")]
    Tls10,
    #[serde(rename = "1.1")]
    Tls11,
    #[serde(rename = "1.2")]
    Tls12,
    #[serde(rename = "1.3")]
    Tls13,
}

/// HTTP client configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClientConfig {
    // Connection settings
    /// Maximum number of redirects to follow
    ///
    /// # VIOLATION 1: Unbounded Redirect Limit
    /// @aphoria:claim[safety] Redirect limit MUST NOT exceed 10 -- Infinite redirect loops exhaust resources
    ///
    /// **Authority:** RFC 7231 Section 6.4
    /// **Current value:** None (unbounded)
    /// **Should be:** Some(10)
    #[serde(default)]
    pub max_redirects: Option<usize>,

    /// Connection timeout (TCP handshake)
    ///
    /// # VIOLATION 3: Excessive Connection Timeout
    /// @aphoria:claim[safety] Connection timeout MUST NOT exceed 10 seconds -- Unresponsive endpoints block connection pool
    ///
    /// **Authority:** Mozilla HTTP docs, Requests library
    /// **Current value:** 60s
    /// **Should be:** 10s
    #[serde(default = "default_connect_timeout")]
    pub connect_timeout: Duration,

    /// Request timeout (total request/response cycle)
    ///
    /// # VIOLATION 2: Excessive Request Timeout
    /// @aphoria:claim[safety] Request timeout MUST NOT exceed 30 seconds -- Slow services cause cascade failures
    ///
    /// **Authority:** Mozilla HTTP docs, RFC 7230
    /// **Current value:** 120s
    /// **Should be:** 30s
    #[serde(default = "default_request_timeout")]
    pub request_timeout: Duration,

    /// Idle connection timeout (keep-alive timeout)
    ///
    /// # VIOLATION 4: Missing Idle Timeout
    /// @aphoria:claim[safety] Idle timeout MUST be configured -- Stale connections accumulate
    ///
    /// **Authority:** RFC 7230 Section 6.3
    /// **Current value:** None (connections never expire)
    /// **Should be:** Some(60s)
    #[serde(default)]
    pub idle_timeout: Option<Duration>,

    // TLS settings
    /// Enable TLS certificate verification
    ///
    /// # VIOLATION 5: TLS Verification Disabled
    /// @aphoria:claim[security] TLS certificate validation MUST be enabled -- MITM attacks, credential theft
    ///
    /// **Authority:** OWASP A07:2021, Mozilla Security Guidelines
    /// **Current value:** false
    /// **Should be:** true
    #[serde(default = "default_verify_tls")]
    pub verify_tls: bool,

    /// Minimum TLS version
    ///
    /// # VIOLATION 6: TLS Version Too Low
    /// @aphoria:claim[security] TLS version MUST be >= 1.2 -- Protocol downgrade attacks (BEAST, POODLE)
    ///
    /// **Authority:** OWASP, Mozilla Security Guidelines
    /// **Current value:** TLS 1.0
    /// **Should be:** TLS 1.2
    #[serde(default = "default_min_tls_version")]
    pub min_tls_version: TlsVersion,

    // Pool settings
    /// Connection pool size per host
    #[serde(default = "default_pool_size")]
    pub pool_size: usize,

    // Observability
    /// Enable metrics collection
    #[serde(default = "default_metrics_enabled")]
    pub metrics_enabled: bool,

    // User-Agent header
    #[serde(default = "default_user_agent")]
    pub user_agent: String,
}

impl Default for ClientConfig {
    fn default() -> Self {
        Self {
            // VIOLATION 1: Unbounded redirects
            max_redirects: None,

            // VIOLATION 3: Excessive connect timeout (60s vs 10s max)
            connect_timeout: Duration::from_secs(60),

            // VIOLATION 2: Excessive request timeout (120s vs 30s max)
            request_timeout: Duration::from_secs(120),

            // VIOLATION 4: Missing idle timeout
            idle_timeout: None,

            // VIOLATION 5: TLS verification disabled
            verify_tls: false,

            // VIOLATION 6: TLS version too low (1.0 vs 1.2 minimum)
            min_tls_version: TlsVersion::Tls10,

            pool_size: default_pool_size(),
            metrics_enabled: default_metrics_enabled(),
            user_agent: default_user_agent(),
        }
    }
}

// Default value functions
fn default_connect_timeout() -> Duration {
    // VIOLATION 3: Should be 10s
    Duration::from_secs(60)
}

fn default_request_timeout() -> Duration {
    // VIOLATION 2: Should be 30s
    Duration::from_secs(120)
}

fn default_verify_tls() -> bool {
    // VIOLATION 5: Should be true
    false
}

fn default_min_tls_version() -> TlsVersion {
    // VIOLATION 6: Should be TLS 1.2
    TlsVersion::Tls10
}

fn default_pool_size() -> usize {
    10 // This is correct (Requests library default)
}

fn default_metrics_enabled() -> bool {
    false // Recommended to be true, but not a hard violation
}

fn default_user_agent() -> String {
    format!("httpclient/{}", env!("CARGO_PKG_VERSION"))
}

impl ClientConfig {
    /// Create a new config with default values (contains violations)
    pub fn new() -> Self {
        Self::default()
    }

    /// Create a production-safe config (no violations)
    pub fn production() -> Self {
        Self {
            max_redirects: Some(10),              // RFC 7231 compliant
            connect_timeout: Duration::from_secs(10),  // Mozilla/Requests default
            request_timeout: Duration::from_secs(30),  // Mozilla recommended
            idle_timeout: Some(Duration::from_secs(60)), // RFC 7230 keep-alive
            verify_tls: true,                     // OWASP A07:2021
            min_tls_version: TlsVersion::Tls12,   // OWASP/Mozilla minimum
            pool_size: 50,                        // Production recommended
            metrics_enabled: true,                // Observability
            user_agent: default_user_agent(),
        }
    }

    /// Validate configuration against safety claims
    pub fn validate(&self) -> Result<(), String> {
        let mut errors = Vec::new();

        // Check redirect limit
        if self.max_redirects.is_none() || self.max_redirects.unwrap() > 10 {
            errors.push("max_redirects MUST be <= 10 (RFC 7231)");
        }

        // Check timeouts
        if self.connect_timeout.as_secs() > 10 {
            errors.push("connect_timeout MUST be <= 10s (Mozilla/Requests)");
        }
        if self.request_timeout.as_secs() > 30 {
            errors.push("request_timeout MUST be <= 30s (Mozilla/RFC 7230)");
        }
        if self.idle_timeout.is_none() {
            errors.push("idle_timeout MUST be configured (RFC 7230 Section 6.3)");
        }

        // Check TLS
        if !self.verify_tls {
            errors.push("verify_tls MUST be true (OWASP A07:2021)");
        }
        if matches!(self.min_tls_version, TlsVersion::Tls10 | TlsVersion::Tls11) {
            errors.push("min_tls_version MUST be >= 1.2 (OWASP/Mozilla)");
        }

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors.join("; "))
        }
    }
}

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

    #[test]
    fn default_config_has_violations() {
        let config = ClientConfig::default();
        assert!(config.validate().is_err(), "Default config should have violations");
    }

    #[test]
    fn production_config_is_valid() {
        let config = ClientConfig::production();
        assert!(config.validate().is_ok(), "Production config should be valid");
    }

    #[test]
    fn violation_1_unbounded_redirects() {
        let config = ClientConfig::default();
        assert_eq!(config.max_redirects, None, "VIOLATION 1: Unbounded redirects");
    }

    #[test]
    fn violation_2_excessive_request_timeout() {
        let config = ClientConfig::default();
        assert_eq!(config.request_timeout.as_secs(), 120, "VIOLATION 2: 120s request timeout");
    }

    #[test]
    fn violation_3_excessive_connect_timeout() {
        let config = ClientConfig::default();
        assert_eq!(config.connect_timeout.as_secs(), 60, "VIOLATION 3: 60s connect timeout");
    }

    #[test]
    fn violation_4_missing_idle_timeout() {
        let config = ClientConfig::default();
        assert_eq!(config.idle_timeout, None, "VIOLATION 4: Missing idle timeout");
    }

    #[test]
    fn violation_5_tls_verification_disabled() {
        let config = ClientConfig::default();
        assert!(!config.verify_tls, "VIOLATION 5: TLS verification disabled");
    }

    #[test]
    fn violation_6_tls_version_too_low() {
        let config = ClientConfig::default();
        assert_eq!(config.min_tls_version, TlsVersion::Tls10, "VIOLATION 6: TLS 1.0");
    }
}
