//! Header injection utilities for testing WAF bypasses.

const LOOPBACK_IP: &str = "127.0.0.1";

/// Static header/value pair used by compatibility helpers.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StaticBypassHeader {
    /// Header name.
    pub name: &'static str,
    /// Header value.
    pub value: &'static str,
}

/// Header value strategy for access-control bypass probes.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccessControlBypassValue {
    /// Use the protected path being probed.
    RewritePath,
    /// Use a fixed value.
    Static(&'static str),
}

/// Static access-control bypass header template.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AccessControlBypassTemplate {
    /// Header name.
    pub name: &'static str,
    /// Header value strategy.
    pub value: AccessControlBypassValue,
    /// Stable short label for reports.
    pub label: &'static str,
}

/// Materialized access-control bypass header.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AccessControlBypassHeader {
    /// Header name.
    pub name: &'static str,
    /// Header value.
    pub value: String,
    /// Stable short label for reports.
    pub label: &'static str,
}

impl AccessControlBypassTemplate {
    /// Materialize this template for a protected path.
    #[must_use]
    pub fn materialize(self, protected_path: &str) -> AccessControlBypassHeader {
        let value = match self.value {
            AccessControlBypassValue::RewritePath => protected_path,
            AccessControlBypassValue::Static(value) => value,
        };
        AccessControlBypassHeader {
            name: self.name,
            value: value.to_string(),
            label: self.label,
        }
    }
}

/// Header templates commonly used to bypass Cloudflare and similar WAFs.
pub const CLOUDFLARE_BYPASS_HEADER_TEMPLATES: &[StaticBypassHeader] = &[
    StaticBypassHeader {
        name: "CF-Connecting-IP",
        value: LOOPBACK_IP,
    },
    StaticBypassHeader {
        name: "True-Client-IP",
        value: LOOPBACK_IP,
    },
    StaticBypassHeader {
        name: "X-Forwarded-For",
        value: LOOPBACK_IP,
    },
];

include!(concat!(
    env!("OUT_DIR"),
    "/access_control_bypass_headers.rs"
));

/// Returns a list of headers commonly used to bypass Cloudflare and similar WAFs.
#[must_use]
pub fn cloudflare_bypass_headers() -> Vec<(String, String)> {
    CLOUDFLARE_BYPASS_HEADER_TEMPLATES
        .iter()
        .map(|header| (header.name.to_string(), header.value.to_string()))
        .collect()
}

/// Returns a list of generic headers commonly used to spoof internal IP addresses.
#[must_use]
pub fn generic_bypass_headers(internal_ip: &str) -> Vec<(String, String)> {
    vec![
        ("X-Forwarded-For".to_string(), internal_ip.to_string()),
        ("X-Real-IP".to_string(), internal_ip.to_string()),
        ("X-Originating-IP".to_string(), internal_ip.to_string()),
        ("X-Client-IP".to_string(), internal_ip.to_string()),
        ("X-Host".to_string(), "127.0.0.1".to_string()),
        ("X-Forwarded-Host".to_string(), "127.0.0.1".to_string()),
    ]
}

/// Materialize access-control bypass headers for a protected path.
#[must_use]
pub fn access_control_bypass_headers(protected_path: &str) -> Vec<AccessControlBypassHeader> {
    ACCESS_CONTROL_BYPASS_HEADER_TEMPLATES
        .iter()
        .map(|template| template.materialize(protected_path))
        .collect()
}
