use super::*;

#[test]
fn cloudflare_bypass_headers_contain_expected_headers() {
    let headers = cloudflare_bypass_headers();
    assert_eq!(headers.len(), 3);

    let names: Vec<&str> = headers.iter().map(|(k, _)| k.as_str()).collect();
    assert!(names.contains(&"CF-Connecting-IP"));
    assert!(names.contains(&"True-Client-IP"));
    assert!(names.contains(&"X-Forwarded-For"));

    // All values should be 127.0.0.1
    for (_, value) in &headers {
        assert_eq!(value, "127.0.0.1");
    }
}

#[test]
fn generic_bypass_headers_use_provided_ip() {
    let headers = generic_bypass_headers("10.0.0.1");
    assert_eq!(headers.len(), 6);

    // First 4 should use the provided IP
    for (_, value) in &headers[..4] {
        assert_eq!(value, "10.0.0.1");
    }

    // X-Host and X-Forwarded-Host always use 127.0.0.1
    assert_eq!(headers[4].1, "127.0.0.1");
    assert_eq!(headers[5].1, "127.0.0.1");
}

#[test]
fn generic_bypass_headers_no_duplicates() {
    let headers = generic_bypass_headers("192.168.1.1");
    let mut names: Vec<&str> = headers.iter().map(|(k, _)| k.as_str()).collect();
    let len_before = names.len();
    names.sort_unstable();
    names.dedup();
    assert_eq!(names.len(), len_before, "header names should be unique");
}

#[test]
fn cloudflare_bypass_overlaps_with_generic() {
    let cf = cloudflare_bypass_headers();
    let generic = generic_bypass_headers("127.0.0.1");

    // X-Forwarded-For should appear in both
    let cf_names: Vec<&str> = cf.iter().map(|(k, _)| k.as_str()).collect();
    let gen_names: Vec<&str> = generic.iter().map(|(k, _)| k.as_str()).collect();
    assert!(cf_names.contains(&"X-Forwarded-For"));
    assert!(gen_names.contains(&"X-Forwarded-For"));
}

#[test]
fn access_control_bypass_headers_use_protected_path_for_rewrite_headers() {
    let headers = access_control_bypass_headers("/wp-admin");

    assert!(
        headers
            .iter()
            .any(|header| { header.name == "X-Original-URL" && header.value == "/wp-admin" })
    );
    assert!(
        headers
            .iter()
            .any(|header| { header.name == "X-Rewrite-URL" && header.value == "/wp-admin" })
    );
    assert!(!headers.iter().any(|header| {
        (header.name == "X-Original-URL" || header.name == "X-Rewrite-URL")
            && header.value == "/admin"
    }));
}

#[test]
fn access_control_bypass_headers_cover_proxy_trust_headers() {
    let headers = access_control_bypass_headers("/admin");
    let names: Vec<&str> = headers.iter().map(|header| header.name).collect();

    for expected in [
        "X-Forwarded-For",
        "X-Real-IP",
        "X-Client-IP",
        "X-Originating-IP",
        "True-Client-IP",
        "CF-Connecting-IP",
        "X-Forwarded-Host",
    ] {
        assert!(
            names.contains(&expected),
            "{expected} missing from access-control bypass headers"
        );
    }
}

#[test]
fn access_control_bypass_catalog_has_expected_floor() {
    assert_eq!(ACCESS_CONTROL_BYPASS_HEADER_TEMPLATES.len(), 12);
    assert!(
        ACCESS_CONTROL_BYPASS_HEADER_TEMPLATES
            .iter()
            .all(|template| { !template.name.is_empty() && !template.label.is_empty() })
    );
}

#[test]
fn access_control_bypass_headers_have_unique_names() {
    let headers = access_control_bypass_headers("/admin");
    let mut names: Vec<&str> = headers.iter().map(|header| header.name).collect();
    let before = names.len();
    names.sort_unstable();
    names.dedup();

    assert_eq!(
        names.len(),
        before,
        "access-control bypass header names should be unique"
    );
}
