// Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.

//! HTTP client for communicating with the KDC Agent.

use std::fs;
use std::sync::OnceLock;
use std::time::Duration;

use openssl::ec::EcKey;
use openssl::pkey::PKey;
use parking_lot::Mutex;
use reqwest::blocking::Client;

use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine as _};
use common::constants::{CommonError, MAX_INNER_REQUEST_SIZE, PSK_LEN, TRUSTED_REGISTER_PSK_REQ};
use common::http_types::{KdcHttpRequest, KdcHttpResponse};

use crate::config_manager::get_config_center;
use crate::proxy_log;
use crate::types::{
    KDC_LOG_DEBUG, KDC_LOG_ERROR, KDC_LOG_INFO, KDC_LOG_WARN, KDC_PROTOCOL_VERSION,
};
use common::psk::{psk_decrypt_with_key, psk_encrypt_with_key};

static KDC_AGENT_CLIENT: OnceLock<Mutex<Option<Client>>> = OnceLock::new();

fn get_client_holder() -> &'static Mutex<Option<Client>> {
    KDC_AGENT_CLIENT.get_or_init(|| Mutex::new(None))
}

fn build_kdc_agent_client() -> Result<Client, CommonError> {
    let config = get_config_center().lock();
    if config.capath.is_empty() {
        proxy_log!(KDC_LOG_ERROR, "CA certificate path is empty");
        return Err(CommonError::ConfigError);
    }
    let ca_pem = fs::read(&config.capath).map_err(|e| {
        proxy_log!(
            KDC_LOG_ERROR,
            &format!("failed to read CA certificate file '{}': {}", config.capath, e)
        );
        CommonError::ConfigError
    })?;
    let has_client_cert = !config.certpath.is_empty() && !config.privatepath.is_empty();
    let client_cert = if has_client_cert {
        let cert_pem = fs::read(&config.certpath).map_err(|e| {
            proxy_log!(
                KDC_LOG_ERROR,
                &format!("failed to read client certificate file '{}': {}", config.certpath, e)
            );
            CommonError::ConfigError
        })?;
        let key_pem = fs::read(&config.privatepath).map_err(|e| {
            proxy_log!(
                KDC_LOG_ERROR,
                &format!("failed to read private key file '{}': {}", config.privatepath, e)
            );
            CommonError::ConfigError
        })?;
        let key_pwd = config.key_pwd.clone();
        Some((cert_pem, key_pem, key_pwd))
    } else {
        None
    };
    let crlpath = config.crlpath.clone();
    drop(config);

    let ca_cert = reqwest::Certificate::from_pem(&ca_pem).map_err(|e| {
        proxy_log!(KDC_LOG_ERROR, &format!("failed to parse CA certificate PEM: {:?}", e));
        CommonError::ConfigError
    })?;

    let mut builder = Client::builder()
        .connect_timeout(Duration::from_secs(5))
        .timeout(Duration::from_secs(30))
        .pool_idle_timeout(Duration::from_secs(7200))
        .add_root_certificate(ca_cert);

    if let Ok(crl_bytes) = fs::read(&crlpath) {
        if let Ok(crls) = reqwest::tls::CertificateRevocationList::from_pem_bundle(&crl_bytes) {
            if !crls.is_empty() {
                for crl in crls { builder = builder.add_crl(crl); }
                proxy_log!(KDC_LOG_DEBUG, "CRL loaded for client verification");
            } else {
                proxy_log!(
                    KDC_LOG_WARN,
                    &format!(
                        "CRL file '{}' is empty or contains no valid CRL entries, treating as no CRL",
                        crlpath
                    )
                );
            }
        }
    }

    if let Some((cert_pem, key_pem, key_pwd)) = client_cert {
        let decrypted_key_pem = if !key_pwd.is_empty() {
            proxy_log!(KDC_LOG_DEBUG, "decrypting private key with password");
            let rsa = PKey::private_key_from_pem_passphrase(&key_pem, key_pwd.as_bytes())
                .map_err(|e| {
                    proxy_log!(KDC_LOG_ERROR, &format!("failed to decrypt private key: {}", e));
                    CommonError::ConfigError
                })?;
            rsa.private_key_to_pem_pkcs8()
                .map_err(|e| {
                    proxy_log!(
                        KDC_LOG_ERROR,
                        &format!("failed to convert private key to PKCS8 PEM: {}", e)
                    );
                    CommonError::ConfigError
                })?
        } else {
            key_pem
        };
        let mut pem_buf = cert_pem;
        pem_buf.extend_from_slice(&decrypted_key_pem);
        let identity =
            reqwest::Identity::from_pem(&pem_buf).map_err(|e| {
                proxy_log!(KDC_LOG_ERROR, &format!("failed to create client identity: {:?}", e));
                CommonError::ConfigError
            })?;
        builder = builder.identity(identity);
    }

    let client = builder.build().map_err(|e| {
        proxy_log!(KDC_LOG_ERROR, &format!("failed to build HTTPS client: {:?}", e));
        CommonError::ConfigError
    })?;
    Ok(client)
}

fn ensure_client() -> Result<Client, CommonError> {
    let mut guard = get_client_holder().lock();
    if let Some(ref client) = *guard {
        proxy_log!(KDC_LOG_DEBUG, "reusing cached HTTPS client");
        return Ok(client.clone());
    }
    let client = build_kdc_agent_client()?;
    *guard = Some(client.clone());
    proxy_log!(KDC_LOG_DEBUG, "HTTPS client created successfully");
    Ok(client)
}

fn prepare_request_data(
    psk: Option<[u8; PSK_LEN]>,
    data: Option<&str>,
) -> Result<Option<String>, CommonError> {
    match (psk, data) {
        (Some(key), Some(payload)) => {
            let encrypted = psk_encrypt_with_key(payload.as_bytes(), &key)
                .map_err(|e| {
                    proxy_log!(KDC_LOG_ERROR, &format!("failed to encrypt request data: {}", e));
                    CommonError::InternalError
                })?;
            Ok(Some(BASE64_STANDARD.encode(&encrypted)))
        }
        _ => Ok(data.map(String::from)),
    }
}

fn decrypt_response_data(
    psk: Option<[u8; PSK_LEN]>,
    data: Option<String>,
) -> Result<Option<String>, CommonError> {
    match (psk, &data) {
        (Some(key), Some(enc_data)) => {
            let decoded = BASE64_STANDARD.decode(enc_data).map_err(|e| {
                proxy_log!(
                    KDC_LOG_ERROR,
                    &format!("failed to decode base64 response data: {}", e)
                );
                CommonError::InternalError
            })?;
            let decrypted =
                psk_decrypt_with_key(&decoded, &key).map_err(|e| {
                    proxy_log!(KDC_LOG_ERROR, &format!("failed to decrypt response data: {}", e));
                    CommonError::InternalError
                })?;
            Ok(Some(
                String::from_utf8(decrypted).map_err(|e| {
                    proxy_log!(
                        KDC_LOG_ERROR,
                        &format!("failed to convert decrypted data to UTF-8: {}", e)
                    );
                    CommonError::InternalError
                })?,
            ))
        }
        _ => Ok(data),
    }
}

pub fn send_to_kdc_agent(
    msg_type: u32,
    data: Option<&str>,
) -> Result<KdcHttpResponse, CommonError> {
    let config = get_config_center().lock();
    let url = config.kdc_agent_url.clone();
    let psk = config.psk.as_ref().map(|s| s.0);
    drop(config);

    if url.is_empty() {
        proxy_log!(KDC_LOG_ERROR, "kdc_agent URL not configured");
        return Err(CommonError::ConfigError);
    }

    let effective_psk = if msg_type == TRUSTED_REGISTER_PSK_REQ {
        None
    } else {
        psk
    };

    let task_id = uuid::Uuid::new_v4().to_string();
    proxy_log!(KDC_LOG_INFO, &format!("sending request type=0x{:04X} to {}", msg_type, url));
    let encrypted_data = prepare_request_data(effective_psk, data)?;

    let request = KdcHttpRequest {
        task_id,
        version: KDC_PROTOCOL_VERSION.to_string(),
        msg_type,
        data: encrypted_data,
    };

    let body_bytes = serde_json::to_vec(&request).map_err(|e| {
        proxy_log!(KDC_LOG_ERROR, &format!("failed to serialize request: {}", e));
        CommonError::InternalError
    })?;
    if body_bytes.len() > MAX_INNER_REQUEST_SIZE {
        proxy_log!(
            KDC_LOG_ERROR,
            &format!(
                "request body too large: {} bytes (max {})",
                body_bytes.len(),
                MAX_INNER_REQUEST_SIZE
            )
        );
        return Err(CommonError::RequestError);
    }

    let client = ensure_client()?;

    let response = client
        .post(&url)
        .body(body_bytes)
        .header("Content-Type", "application/json")
        .send()
        .map_err(|e| {
            proxy_log!(KDC_LOG_ERROR, &format!("HTTPS request failed: {:?}", e));
            CommonError::NetworkError
        })?;

    if !response.status().is_success() {
        let status = response.status();
        proxy_log!(KDC_LOG_ERROR, &format!("HTTPS request returned non-success status: {}", status));
        return Err(CommonError::NetworkError);
    }

    let mut kdc_response: KdcHttpResponse = response.json().map_err(|e| {
        proxy_log!(KDC_LOG_ERROR, &format!("failed to parse response: {:?}", e));
        CommonError::NetworkError
    })?;

    if kdc_response.ret_code == CommonError::PskMismatchError as u32 {
        proxy_log!(KDC_LOG_WARN, "PSK mismatch detected, re-registration needed");
        return Err(CommonError::PskMismatchError);
    }

    kdc_response.data = decrypt_response_data(effective_psk, kdc_response.data)?;

    proxy_log!(
        KDC_LOG_INFO, &format!(
            "request type=0x{:04X} completed, ret_code={}, ret_msg={}",
            msg_type, kdc_response.ret_code, kdc_response.ret_msg)
    );
    Ok(kdc_response)
}

pub fn request_token_from_ra_agent(
    ec_key: Option<&EcKey<openssl::pkey::Private>>,
) -> Result<String, CommonError> {
    let config = get_config_center().lock();
    let url = config.ra_agent_url.clone();
    drop(config);

    if url.is_empty() {
        proxy_log!(KDC_LOG_ERROR, "RA agent URL not configured");
        return Err(CommonError::ConfigError);
    }

    let ra_body = match ec_key {
        Some(key) => {
            let pub_pkey = PKey::from_ec_key(key.clone()).map_err(|e| {
                proxy_log!(KDC_LOG_ERROR, &format!("failed to get PKey: {}", e));
                CommonError::InternalError
            })?;
            let pub_pem = pub_pkey.public_key_to_pem().map_err(|e| {
                proxy_log!(KDC_LOG_ERROR, &format!("failed to get PEM: {}", e));
                CommonError::InternalError
            })?;
            let pub_pem_str = String::from_utf8(pub_pem).map_err(|e| {
                proxy_log!(KDC_LOG_ERROR, &format!("invalid PEM UTF-8: {}", e));
                CommonError::InternalError
            })?;
            proxy_log!(KDC_LOG_DEBUG, "ra_body: [REDACTED - contains public key]");
            build_ra_request_body(&pub_pem_str)
        }
        None => {
            serde_json::json!({
                "attester_info": [{"attester_type": "virt_cca"}],
                "challenge": false,
                "token_fmt": "eat"
            })
        }
    };

    proxy_log!(KDC_LOG_INFO, &format!("sending attestation request to RA agent: {}", url));

    let client = ensure_client()?;

    let response = client.post(&url).json(&ra_body).send().map_err(|e| {
        proxy_log!(KDC_LOG_ERROR, &format!("RA agent request failed: {:?}", e));
        CommonError::NetworkError
    })?;

    let ra_response: serde_json::Value = response.json().map_err(|e| {
        proxy_log!(KDC_LOG_ERROR, &format!("failed to parse RA agent response: {:?}", e));
        CommonError::NetworkError
    })?;

    let token = ra_response
        .get("token")
        .and_then(|v| v.as_str())
        .ok_or_else(|| {
            let msg = ra_response
                .get("message")
                .and_then(|v| v.as_str())
                .unwrap_or("unknown error");
            proxy_log!(KDC_LOG_ERROR, &format!("RA agent returned error message: {}", msg));
            CommonError::InternalError
        })?
        .to_string();

    proxy_log!(KDC_LOG_INFO, "received attestation token from RA agent");
    Ok(token)
}

pub fn build_ra_request_body(pub_pem_str: &str) -> serde_json::Value {
    serde_json::json!({
        "attester_info": [{"attester_type": "virt_cca"}],
        "challenge": true,
        "token_fmt": "eat",
        "attester_data": {"public_key": pub_pem_str}
    })
}

#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
    use super::*;
    use common::psk::generate_random_psk;
    use zeroize::Zeroizing;
    use crate::config_manager::SecurePsk;

    fn reset_config() {
        let config = get_config_center();
        let mut guard = config.lock();
        guard.capath = String::new();
        guard.certpath = String::new();
        guard.privatepath = String::new();
        guard.key_pwd = Zeroizing::new(String::new());
        guard.psk = None;
        guard.kdc_agent_url = String::new();
        guard.ra_agent_url = String::new();
    }

    fn reset_client_holder() {
        let holder = get_client_holder();
        let mut guard = holder.lock();
        *guard = None;
    }

    fn create_self_signed_ca(
        temp_name: &str,
    ) -> (
        std::path::PathBuf,
        openssl::pkey::PKey<openssl::pkey::Private>,
    ) {
        use openssl::asn1::Asn1Time;
        use openssl::bn::BigNum;
        use openssl::x509::X509Builder;

        let rsa = openssl::rsa::Rsa::generate(2048).unwrap();
        let pkey = openssl::pkey::PKey::from_rsa(rsa).unwrap();
        let mut builder = X509Builder::new().unwrap();
        builder.set_version(2).unwrap();
        let serial = BigNum::from_u32(1).unwrap().to_asn1_integer().unwrap();
        builder.set_serial_number(&serial).unwrap();
        builder.set_pubkey(&pkey).unwrap();
        builder
            .set_not_before(Asn1Time::days_from_now(0).unwrap().as_ref())
            .unwrap();
        builder
            .set_not_after(Asn1Time::days_from_now(365).unwrap().as_ref())
            .unwrap();
        builder
            .sign(&pkey, openssl::hash::MessageDigest::sha256())
            .unwrap();
        let cert = builder.build();
        let pem = cert.to_pem().unwrap();

        let path = std::env::temp_dir().join(temp_name);
        std::fs::write(&path, &pem).unwrap();
        (path, pkey)
    }

    // Test: verify build_ra_request_body produces correct JSON structure
    #[test]
    fn test_build_ra_request_body() {
        let pub_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n-----END PUBLIC KEY-----";
        let body = build_ra_request_body(pub_key);
        assert!(body.get("attester_info").is_some());
        let info = body.get("attester_info").unwrap().as_array().unwrap();
        assert_eq!(info[0]["attester_type"], "virt_cca");
        assert_eq!(body["challenge"], true);
        assert_eq!(body["token_fmt"], "eat");
        assert_eq!(body["attester_data"]["public_key"], pub_key);
    }

    // Test: verify PSK mismatch detection from response JSON
    #[test]
    fn test_psk_mismatch_detection() {
        let json = r#"{"retCode": 2, "retMsg": "PSK mismatch"}"#;
        let resp: KdcHttpResponse = serde_json::from_str(json).unwrap();
        assert_eq!(resp.ret_code, CommonError::PskMismatchError as u32);
    }

    // Test: verify prepare_request_data with no PSK returns plaintext unchanged
    #[test]
    fn test_prepare_request_data_without_psk() {
        let result = prepare_request_data(None, Some("plaintext")).unwrap();
        assert_eq!(result, Some("plaintext".to_string()));
    }

    // Test: verify prepare_request_data with PSK returns encrypted hex data
    #[test]
    fn test_prepare_request_data_with_psk() {
        let key = generate_random_psk().unwrap();
        let result = prepare_request_data(Some(key), Some("secret message")).unwrap();
        let encrypted_hex = result.unwrap();
        assert_ne!(encrypted_hex, "secret message");
        assert!(BASE64_STANDARD.decode(&encrypted_hex).is_ok());
    }

    // Test: verify prepare_request_data with None PSK and None data returns None
    #[test]
    fn test_prepare_request_data_none_none() {
        let result = prepare_request_data(None, None).unwrap();
        assert_eq!(result, None);
    }

    // Test: verify decrypt_response_data PSK encrypt/decrypt roundtrip
    #[test]
    fn test_decrypt_response_data_roundtrip() {
        let key = generate_random_psk().unwrap();
        let plaintext = "response payload";
        let encrypted = psk_encrypt_with_key(plaintext.as_bytes(), &key).unwrap();
        let encrypted_hex = BASE64_STANDARD.encode(&encrypted);
        let decrypted = decrypt_response_data(Some(key), Some(encrypted_hex)).unwrap();
        assert_eq!(decrypted, Some(plaintext.to_string()));
    }

    // Test: verify decrypt_response_data with invalid hex returns error
    #[test]
    fn test_decrypt_response_data_invalid_hex() {
        let key = generate_random_psk().unwrap();
        let result = decrypt_response_data(Some(key), Some("zz".to_string()));
        assert!(result.is_err());
    }

    // Test: verify decrypt_response_data with None PSK and None data returns None
    #[test]
    fn test_decrypt_response_data_none_none() {
        let result = decrypt_response_data(None, None).unwrap();
        assert_eq!(result, None);
    }

    // Test: verify decrypt_response_data with None PSK passes data through unchanged
    #[test]
    fn test_decrypt_response_data_none_some() {
        let result = decrypt_response_data(None, Some("hello".to_string())).unwrap();
        assert_eq!(result, Some("hello".to_string()));
    }

    // Test: verify send_to_kdc_agent returns ConfigError when URL is not configured
    #[test]
    fn test_send_to_kdc_agent_no_config() {
        reset_config();
        let result = send_to_kdc_agent(0x0010, Some("test"));
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
    }

    // Test: verify send_to_kdc_agent returns ConfigError when URL is empty
    #[test]
    fn test_a_send_to_kdc_agent_empty_url() {
        reset_config();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = String::new();
        }
        let result = send_to_kdc_agent(0x0010, Some("test"));
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
        reset_config();
    }

    // Test: verify request_token_from_ra_agent returns ConfigError with empty URL
    #[test]
    fn test_request_token_from_ra_agent_no_config() {
        reset_config();
        let (ec_key, _pub_pem) = crate::crypto::generate_ec_keypair().unwrap();
        let result = request_token_from_ra_agent(Some(&ec_key));
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
    }

    // Test: verify build_kdc_agent_client returns ConfigError when capath is empty
    #[test]
    fn test_build_client_needs_config() {
        let result = build_kdc_agent_client();
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
    }

    // Test: verify ensure_client returns error when capath is not configured
    #[test]
    fn test_ensure_client_no_config() {
        reset_config();
        let result = ensure_client();
        assert!(result.is_err());
        reset_config();
    }

    // Test: verify ensure_client creates and caches client with valid CA
    #[test]
    fn test_a_ensure_client_creates_and_caches() {
        reset_config();
        reset_client_holder();

        let (ca_path, _) = create_self_signed_ca("kdc_test_ensure_ca.pem");

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let client1 = ensure_client();
        assert!(client1.is_ok(), "first ensure_client should succeed");

        let client2 = ensure_client();
        assert!(
            client2.is_ok(),
            "second ensure_client should return cached client"
        );

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    // Test: verify build_kdc_agent_client returns error for nonexistent CA path
    #[test]
    fn test_build_kdc_agent_client_nonexistent_ca() {
        reset_config();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = "/nonexistent/path/ca.pem".to_string();
        }
        let result = build_kdc_agent_client();
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
        reset_config();
    }

    // Test: verify build succeeds with valid CA file only (no client cert)
    #[test]
    fn test_build_kdc_agent_client_with_valid_ca() {
        reset_config();

        let (ca_path, _) = create_self_signed_ca("kdc_test_valid_ca.pem");

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let result = build_kdc_agent_client();
        assert!(result.is_ok());

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
    }

    // Test: verify build fails when cert file exists but key file does not
    #[test]
    fn test_build_kdc_agent_client_cert_not_found() {
        reset_config();

        let (ca_path, _) = create_self_signed_ca("kdc_test_ca_cnf.pem");

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = "/nonexistent/cert.pem".to_string();
            guard.privatepath = "/nonexistent/key.pem".to_string();
        }
        let result = build_kdc_agent_client();
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
    }

    // Test: verify build fails when cert exists but key file does not
    #[test]
    fn test_build_kdc_agent_client_key_not_found() {
        reset_config();

        let (ca_path, _) = create_self_signed_ca("kdc_test_ca_knf.pem");
        let cert_path = std::env::temp_dir().join("kdc_test_cert_knf.pem");
        let cert_pem = std::fs::read(&ca_path).unwrap();
        std::fs::write(&cert_path, &cert_pem).unwrap();

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = cert_path.to_str().unwrap().to_string();
            guard.privatepath = "/nonexistent/key.pem".to_string();
        }
        let result = build_kdc_agent_client();
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
        let _ = std::fs::remove_file(&ca_path);
        let _ = std::fs::remove_file(&cert_path);
        reset_config();
    }

    // Test: verify build succeeds with valid CA, cert, and key files
    #[test]
    fn test_build_kdc_agent_client_with_cert_and_key() {
        reset_config();

        let (ca_path, pkey) = create_self_signed_ca("kdc_test_ca_ck.pem");
        let key_pem = pkey.private_key_to_pem_pkcs8().unwrap();
        let cert_pem = std::fs::read(&ca_path).unwrap();

        let cert_path = std::env::temp_dir().join("kdc_test_cert_ck.pem");
        let key_path = std::env::temp_dir().join("kdc_test_key_ck.pem");
        std::fs::write(&cert_path, &cert_pem).unwrap();
        std::fs::write(&key_path, &key_pem).unwrap();

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = cert_path.to_str().unwrap().to_string();
            guard.privatepath = key_path.to_str().unwrap().to_string();
        }

        let result = build_kdc_agent_client();
        assert!(result.is_ok());

        let _ = std::fs::remove_file(&ca_path);
        let _ = std::fs::remove_file(&cert_path);
        let _ = std::fs::remove_file(&key_path);
        reset_config();
    }

    // Test: verify build with key password but nonexistent files returns ConfigError
    #[test]
    fn test_build_kdc_agent_client_with_key_pwd() {
        reset_config();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = "/nonexistent/ca.pem".to_string();
            guard.certpath = "/nonexistent/cert.pem".to_string();
            guard.privatepath = "/nonexistent/key.pem".to_string();
            guard.key_pwd = Zeroizing::new("secret".to_string());
        }
        let result = build_kdc_agent_client();
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
        reset_config();
    }

    // Test: verify build succeeds with encrypted private key and correct password
    #[test]
    fn test_build_kdc_agent_client_with_encrypted_key() {
        use openssl::asn1::Asn1Time;
        use openssl::bn::BigNum;
        use openssl::x509::X509Builder;

        reset_config();

        let password = "test_password";

        let ca_path = std::env::temp_dir().join("kdc_test_ca_enc.pem");

        let rsa = openssl::rsa::Rsa::generate(2048).unwrap();
        let pkey = openssl::pkey::PKey::from_rsa(rsa).unwrap();

        // Generate a self-signed cert using this key (used as both CA and client cert)
        let mut builder = X509Builder::new().unwrap();
        builder.set_version(2).unwrap();
        let serial = BigNum::from_u32(1).unwrap().to_asn1_integer().unwrap();
        builder.set_serial_number(&serial).unwrap();
        builder.set_pubkey(&pkey).unwrap();
        builder
            .set_not_before(Asn1Time::days_from_now(0).unwrap().as_ref())
            .unwrap();
        builder
            .set_not_after(Asn1Time::days_from_now(365).unwrap().as_ref())
            .unwrap();
        builder
            .sign(&pkey, openssl::hash::MessageDigest::sha256())
            .unwrap();
        let cert = builder.build();
        let cert_pem = cert.to_pem().unwrap();
        std::fs::write(&ca_path, &cert_pem).unwrap();

        let unencrypted_key_pem = pkey.private_key_to_pem_pkcs8().unwrap();
        let plain_key_path = std::env::temp_dir().join("kdc_test_plain_key_enc.pem");
        std::fs::write(&plain_key_path, &unencrypted_key_pem).unwrap();

        let enc_result = std::process::Command::new("openssl")
            .args([
                "rsa",
                "-aes128",
                "-in",
                plain_key_path.to_str().unwrap(),
                "-passout",
                &format!("pass:{}", password),
            ])
            .output();

        let encrypted_key_pem = match enc_result {
            Ok(out) if out.status.success() => out.stdout,
            Ok(out) => {
                let _ = std::fs::remove_file(&ca_path);
                let _ = std::fs::remove_file(&plain_key_path);
                reset_config();
                panic!(
                    "openssl rsa encryption failed: {}",
                    String::from_utf8_lossy(&out.stderr)
                );
            }
            Err(e) => {
                let _ = std::fs::remove_file(&ca_path);
                let _ = std::fs::remove_file(&plain_key_path);
                reset_config();
                panic!("failed to spawn openssl command: {}", e);
            }
        };

        let _ = std::fs::remove_file(&plain_key_path);

        let cert_path = std::env::temp_dir().join("kdc_test_cert_enc.pem");
        let key_path = std::env::temp_dir().join("kdc_test_key_enc.pem");
        std::fs::write(&cert_path, &cert_pem).unwrap();
        std::fs::write(&key_path, &encrypted_key_pem).unwrap();

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = cert_path.to_str().unwrap().to_string();
            guard.privatepath = key_path.to_str().unwrap().to_string();
            guard.key_pwd = Zeroizing::new(password.to_string());
        }

        let result = build_kdc_agent_client();
        assert!(
            result.is_ok(),
            "should succeed with encrypted key and correct password"
        );

        let _ = std::fs::remove_file(&ca_path);
        let _ = std::fs::remove_file(&cert_path);
        let _ = std::fs::remove_file(&key_path);
        reset_config();
    }

    // Test: verify certpath only (no privatepath) builds successfully
    #[test]
    fn test_build_kdc_agent_client_only_certpath_no_key() {
        reset_config();

        let (ca_path, _) = create_self_signed_ca("kdc_test_ca_certonly.pem");

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = ca_path.to_str().unwrap().to_string();
            guard.privatepath = String::new();
        }

        let result = build_kdc_agent_client();
        assert!(result.is_ok());

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
    }

    // Test: verify keypath only (no certpath) builds successfully
    #[test]
    fn test_build_kdc_agent_client_only_keypath_no_cert() {
        reset_config();

        let (ca_path, _) = create_self_signed_ca("kdc_test_ca_keyonly.pem");

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = String::new();
            guard.privatepath = ca_path.to_str().unwrap().to_string();
        }

        let result = build_kdc_agent_client();
        assert!(result.is_ok());

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
    }

    // Test: verify request body exceeds MAX_INNER_REQUEST_SIZE limit with large data
    #[test]
    fn test_request_body_size_limit() {
        let large_data = "x".repeat(110_000);
        let req = KdcHttpRequest {
            task_id: "test".to_string(),
            version: "1.0".to_string(),
            msg_type: 0x0011,
            data: Some(large_data),
        };
        let body = serde_json::to_vec(&req).unwrap();
        assert!(
            body.len() > MAX_INNER_REQUEST_SIZE,
            "body should exceed 100KB limit"
        );
    }

    // Test: verify request body within MAX_INNER_REQUEST_SIZE with small data
    #[test]
    fn test_request_body_within_limit() {
        let req = KdcHttpRequest {
            task_id: "test".to_string(),
            version: "1.0".to_string(),
            msg_type: 0x0011,
            data: Some("small payload".to_string()),
        };
        let body = serde_json::to_vec(&req).unwrap();
        assert!(
            body.len() <= MAX_INNER_REQUEST_SIZE,
            "body should be within 100KB limit"
        );
    }

    // Test: verify prepare_request_data with Some PSK and None data returns None
    #[test]
    fn test_prepare_request_data_psk_none_data() {
        let key = generate_random_psk().unwrap();
        let result = prepare_request_data(Some(key), None).unwrap();
        assert_eq!(result, None);
    }

    // Test: verify decrypt_response_data with Some PSK and None data returns None
    #[test]
    fn test_decrypt_response_data_psk_none_data() {
        let key = generate_random_psk().unwrap();
        let result = decrypt_response_data(Some(key), None).unwrap();
        assert_eq!(result, None);
    }

    // Test: verify decrypt_response_data with wrong key returns error
    #[test]
    fn test_decrypt_response_data_wrong_key() {
        let key_a = generate_random_psk().unwrap();
        let key_b = generate_random_psk().unwrap();
        let encrypted = psk_encrypt_with_key(b"secret", &key_a).unwrap();
        let encrypted_hex = BASE64_STANDARD.encode(&encrypted);
        let result = decrypt_response_data(Some(key_b), Some(encrypted_hex));
        assert!(result.is_err());
    }

    // Test: verify decrypt_response_data with invalid UTF-8 after decryption returns error
    #[test]
    fn test_decrypt_response_data_invalid_utf8() {
        let key = generate_random_psk().unwrap();
        let invalid_utf8: Vec<u8> = vec![0xFF, 0xFE, 0xFD, 0xFC];
        let encrypted = psk_encrypt_with_key(&invalid_utf8, &key).unwrap();
        let encrypted_hex = BASE64_STANDARD.encode(&encrypted);
        let result = decrypt_response_data(Some(key), Some(encrypted_hex));
        assert!(result.is_err());
    }

    // Test: verify send_to_kdc_agent with TRUSTED_REGISTER_PSK_REQ skips PSK encryption
    #[test]
    fn test_send_to_kdc_agent_register_skips_psk() {
        reset_config();
        reset_client_holder();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = "https://127.0.0.1:1".to_string();
            let (ca_path, _) = create_self_signed_ca("kdc_test_register_ca.pem");
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.psk = Some(SecurePsk([1u8; PSK_LEN]));
        }
        let result = send_to_kdc_agent(TRUSTED_REGISTER_PSK_REQ, Some("test_data"));
        assert!(result.is_err());
        reset_config();
        reset_client_holder();
    }

    // Test: verify send_to_kdc_agent with PSK set encrypts data
    #[test]
    fn test_send_to_kdc_agent_with_psk_encrypts() {
        reset_config();
        reset_client_holder();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = "https://127.0.0.1:1".to_string();
            let (ca_path, _) = create_self_signed_ca("kdc_test_psk_ca.pem");
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.psk = Some(SecurePsk([2u8; PSK_LEN]));
        }
        let result = send_to_kdc_agent(0x0020, Some("test_data"));
        assert!(result.is_err());
        reset_config();
        reset_client_holder();
    }

    // Test: verify request_token_from_ra_agent with no ec_key uses default body
    #[test]
    fn test_request_token_no_ec_key() {
        reset_config();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.ra_agent_url = String::new();
        }
        let result = request_token_from_ra_agent(None);
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), CommonError::ConfigError);
    }

    // Test: verify build_kdc_agent_client with invalid CRL path still succeeds
    #[test]
    fn test_build_kdc_agent_client_with_invalid_crl() {
        reset_config();

        let (ca_path, _) = create_self_signed_ca("kdc_test_bad_crl_ca.pem");

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.crlpath = "/nonexistent/crl.pem".to_string();
        }

        let result = build_kdc_agent_client();
        assert!(result.is_ok(), "should succeed even with invalid CRL path");

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
    }

    // Test: verify build_kdc_agent_client with CRL file containing valid PEM
    #[test]
    fn test_build_kdc_agent_client_with_crl() {
        reset_config();

        let (ca_path, pkey) = create_self_signed_ca("kdc_test_crl_ca.pem");

        let crl_path = std::env::temp_dir().join("kdc_test_crl.pem");
        let crl_result = generate_test_crl_pem(&pkey);
        match crl_result {
            Some(pem) => {
                std::fs::write(&crl_path, &pem).unwrap();

                {
                    let config = get_config_center();
                    let mut guard = config.lock();
                    guard.capath = ca_path.to_str().unwrap().to_string();
                    guard.crlpath = crl_path.to_str().unwrap().to_string();
                }

                let result = build_kdc_agent_client();
                assert!(result.is_ok(), "should succeed with valid CA and CRL");

                let _ = std::fs::remove_file(&crl_path);
            }
            None => {
                let (ca_path2, _) = create_self_signed_ca("kdc_test_crl_ca_fallback.pem");
                {
                    let config = get_config_center();
                    let mut guard = config.lock();
                    guard.capath = ca_path2.to_str().unwrap().to_string();
                    guard.crlpath = "/nonexistent/crl.pem".to_string();
                }
                let result = build_kdc_agent_client();
                assert!(result.is_ok());
                let _ = std::fs::remove_file(&ca_path2);
            }
        }

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
    }

    // Test: verify ensure_client returns cached client on second call
    #[test]
    fn test_ensure_client_caching() {
        reset_config();
        reset_client_holder();

        let (ca_path, _) = create_self_signed_ca("kdc_test_cache_ca.pem");

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let client1 = ensure_client().unwrap();
        let client2 = ensure_client().unwrap();

        let _ = client1;
        let _ = client2;

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    // Test: verify get_client_holder returns singleton
    #[test]
    fn test_get_client_holder_singleton() {
        let holder1 = get_client_holder();
        let holder2 = get_client_holder();
        assert!(std::ptr::eq(holder1, holder2));
    }

    fn generate_test_crl_pem(_pkey: &openssl::pkey::PKey<openssl::pkey::Private>) -> Option<Vec<u8>> {
        let crl_result = std::process::Command::new("openssl")
            .args(["ca", "-gencrl"])
            .output()
            .ok()?;

        if crl_result.status.success() {
            Some(crl_result.stdout)
        } else {
            None
        }
    }

    // Test: verify prepare_request_data with Some PSK and empty string data
    #[test]
    fn test_prepare_request_data_psk_empty_data() {
        let key = generate_random_psk().unwrap();
        let result = prepare_request_data(Some(key), Some("")).unwrap();
        let encrypted_hex = result.unwrap();
        assert!(!encrypted_hex.is_empty());
        assert_ne!(encrypted_hex, "");
    }

    // Test: verify decrypt_response_data with Some PSK and Some valid data roundtrip
    #[test]
    fn test_decrypt_response_data_valid_roundtrip_long() {
        let key = generate_random_psk().unwrap();
        let plaintext = "a longer response payload with special chars: \u{4e2d}\u{6587}";
        let encrypted = psk_encrypt_with_key(plaintext.as_bytes(), &key).unwrap();
        let encrypted_hex = BASE64_STANDARD.encode(&encrypted);
        let decrypted = decrypt_response_data(Some(key), Some(encrypted_hex)).unwrap();
        assert_eq!(decrypted, Some(plaintext.to_string()));
    }

    // Test: verify get_client_holder returns consistent singleton
    #[test]
    fn test_get_client_holder_consistent() {
        let h1 = get_client_holder();
        let h2 = get_client_holder();
        assert!(std::ptr::eq(h1, h2));
        let guard = h1.lock();
        let _ = guard;
    }

    // Test: verify build_kdc_agent_client with key password and valid encrypted key
    #[test]
    fn test_build_kdc_agent_client_with_password_valid() {
        use openssl::asn1::Asn1Time;
        use openssl::bn::BigNum;
        use openssl::x509::X509Builder;

        reset_config();
        reset_client_holder();

        let password = "test_pwd_123";

        let rsa = openssl::rsa::Rsa::generate(2048).unwrap();
        let pkey = openssl::pkey::PKey::from_rsa(rsa).unwrap();

        let ca_path = std::env::temp_dir().join("kdc_test_pwd_ca.pem");
        let mut builder = X509Builder::new().unwrap();
        builder.set_version(2).unwrap();
        let serial = BigNum::from_u32(1).unwrap().to_asn1_integer().unwrap();
        builder.set_serial_number(&serial).unwrap();
        builder.set_pubkey(&pkey).unwrap();
        builder
            .set_not_before(Asn1Time::days_from_now(0).unwrap().as_ref())
            .unwrap();
        builder
            .set_not_after(Asn1Time::days_from_now(365).unwrap().as_ref())
            .unwrap();
        builder
            .sign(&pkey, openssl::hash::MessageDigest::sha256())
            .unwrap();
        let cert = builder.build();
        let cert_pem = cert.to_pem().unwrap();
        std::fs::write(&ca_path, &cert_pem).unwrap();

        let plain_key = pkey.private_key_to_pem_pkcs8().unwrap();
        let plain_key_path = std::env::temp_dir().join("kdc_test_pwd_plain.pem");
        std::fs::write(&plain_key_path, &plain_key).unwrap();

        let enc_output = std::process::Command::new("openssl")
            .args([
                "rsa", "-aes128", "-in", plain_key_path.to_str().unwrap(),
                "-passout", &format!("pass:{}", password),
            ])
            .output()
            .unwrap();

        if !enc_output.status.success() {
            let _ = std::fs::remove_file(&ca_path);
            let _ = std::fs::remove_file(&plain_key_path);
            reset_config();
            reset_client_holder();
            return;
        }

        let key_path = std::env::temp_dir().join("kdc_test_pwd_enc_key.pem");
        std::fs::write(&key_path, &enc_output.stdout).unwrap();

        let cert_only_path = std::env::temp_dir().join("kdc_test_pwd_cert.pem");
        std::fs::write(&cert_only_path, &cert_pem).unwrap();

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = cert_only_path.to_str().unwrap().to_string();
            guard.privatepath = key_path.to_str().unwrap().to_string();
            guard.key_pwd = Zeroizing::new(password.to_string());
        }

        let result = build_kdc_agent_client();
        assert!(result.is_ok(), "should succeed with encrypted key and password");

        let _ = std::fs::remove_file(&ca_path);
        let _ = std::fs::remove_file(&plain_key_path);
        let _ = std::fs::remove_file(&key_path);
        let _ = std::fs::remove_file(&cert_only_path);
        reset_config();
        reset_client_holder();
    }

    // Test: verify ensure_client with wrong password returns ConfigError
    #[test]
    fn test_build_client_wrong_password() {
        use openssl::asn1::Asn1Time;
        use openssl::bn::BigNum;
        use openssl::x509::X509Builder;

        reset_config();

        let rsa = openssl::rsa::Rsa::generate(2048).unwrap();
        let pkey = openssl::pkey::PKey::from_rsa(rsa).unwrap();

        let ca_path = std::env::temp_dir().join("kdc_test_wrong_pwd_ca.pem");
        let mut builder = X509Builder::new().unwrap();
        builder.set_version(2).unwrap();
        let serial = BigNum::from_u32(1).unwrap().to_asn1_integer().unwrap();
        builder.set_serial_number(&serial).unwrap();
        builder.set_pubkey(&pkey).unwrap();
        builder
            .set_not_before(Asn1Time::days_from_now(0).unwrap().as_ref())
            .unwrap();
        builder
            .set_not_after(Asn1Time::days_from_now(365).unwrap().as_ref())
            .unwrap();
        builder
            .sign(&pkey, openssl::hash::MessageDigest::sha256())
            .unwrap();
        let cert = builder.build();
        std::fs::write(&ca_path, cert.to_pem().unwrap()).unwrap();

        let plain_key = pkey.private_key_to_pem_pkcs8().unwrap();
        let plain_key_path = std::env::temp_dir().join("kdc_test_wrong_pwd_plain.pem");
        std::fs::write(&plain_key_path, &plain_key).unwrap();

        let enc_output = std::process::Command::new("openssl")
            .args([
                "rsa", "-aes128", "-in", plain_key_path.to_str().unwrap(),
                "-passout", "pass:correct_password",
            ])
            .output()
            .unwrap();

        if !enc_output.status.success() {
            let _ = std::fs::remove_file(&ca_path);
            let _ = std::fs::remove_file(&plain_key_path);
            reset_config();
            return;
        }

        let key_path = std::env::temp_dir().join("kdc_test_wrong_pwd_key.pem");
        std::fs::write(&key_path, &enc_output.stdout).unwrap();

        let cert_path = std::env::temp_dir().join("kdc_test_wrong_pwd_cert.pem");
        std::fs::write(&cert_path, cert.to_pem().unwrap()).unwrap();

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = cert_path.to_str().unwrap().to_string();
            guard.privatepath = key_path.to_str().unwrap().to_string();
            guard.key_pwd = Zeroizing::new("wrong_password".to_string());
        }

        let result = build_kdc_agent_client();
        assert!(result.is_err(), "should fail with wrong password");

        let _ = std::fs::remove_file(&ca_path);
        let _ = std::fs::remove_file(&plain_key_path);
        let _ = std::fs::remove_file(&key_path);
        let _ = std::fs::remove_file(&cert_path);
        reset_config();
    }

    // Test: verify request_token_from_ra_agent with non-empty URL attempts connection
    #[test]
    fn test_request_token_with_url_set_attempts_connection() {
        reset_config();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.ra_agent_url = "https://127.0.0.1:1/nonexistent".to_string();
        }
        let result = request_token_from_ra_agent(None);
        assert!(result.is_err(), "should fail connecting to non-existent server");
        reset_config();
    }

    #[test]
    fn test_request_token_with_ec_key_unreachable_url() {
        reset_config();
        reset_client_holder();
        let (ca_path, _) = create_self_signed_ca("kdc_test_ra_ec_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.ra_agent_url = "https://127.0.0.1:1/ra".to_string();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }
        let (ec_key, _pub_pem) = crate::crypto::generate_ec_keypair().unwrap();
        let result = request_token_from_ra_agent(Some(&ec_key));
        assert!(result.is_err(), "should fail with unreachable URL");
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_send_to_kdc_agent_network_unreachable() {
        reset_config();
        reset_client_holder();
        let (ca_path, _) = create_self_signed_ca("kdc_test_net_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = "https://127.0.0.1:1/kdc".to_string();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }
        let result = send_to_kdc_agent(0x0020, Some("test"));
        assert!(result.is_err());
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_send_to_kdc_agent_no_psk_no_encrypt() {
        reset_config();
        reset_client_holder();
        let (ca_path, _) = create_self_signed_ca("kdc_test_nopsk_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = "https://127.0.0.1:1/kdc".to_string();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }
        let result = send_to_kdc_agent(0x0020, Some("plaintext"));
        assert!(result.is_err());
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_decrypt_response_data_psk_empty_data() {
        let key = generate_random_psk().unwrap();
        let result = decrypt_response_data(Some(key), Some(String::new()));
        assert!(result.is_err(), "empty base64 should fail decode");
    }

    #[test]
    fn test_build_kdc_agent_client_mismatched_cert_key() {
        reset_config();

        let (ca_path, _) = create_self_signed_ca("kdc_test_mismatch_ca.pem");
        let rsa = openssl::rsa::Rsa::generate(2048).unwrap();
        let other_pkey = openssl::pkey::PKey::from_rsa(rsa).unwrap();
        let other_key_pem = other_pkey.private_key_to_pem_pkcs8().unwrap();

        let cert_pem = std::fs::read(&ca_path).unwrap();
        let cert_path = std::env::temp_dir().join("kdc_test_mismatch_cert.pem");
        let key_path = std::env::temp_dir().join("kdc_test_mismatch_key.pem");
        std::fs::write(&cert_path, &cert_pem).unwrap();
        std::fs::write(&key_path, &other_key_pem).unwrap();

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = cert_path.to_str().unwrap().to_string();
            guard.privatepath = key_path.to_str().unwrap().to_string();
        }

        let result = build_kdc_agent_client();
        assert!(result.is_err(), "mismatched cert/key should fail");

        let _ = std::fs::remove_file(&ca_path);
        let _ = std::fs::remove_file(&cert_path);
        let _ = std::fs::remove_file(&key_path);
        reset_config();
    }

    #[test]
    fn test_request_token_ec_key_unreachable_network_error() {
        reset_config();
        reset_client_holder();
        let (ca_path, _) = create_self_signed_ca("kdc_test_ra_net_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.ra_agent_url = "https://127.0.0.1:1/ra".to_string();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }
        let (ec_key, _pub_pem) = crate::crypto::generate_ec_keypair().unwrap();
        let result = request_token_from_ra_agent(Some(&ec_key));
        assert!(result.is_err());
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_ensure_client_recreates_after_reset() {
        reset_config();
        reset_client_holder();

        let (ca_path, _) = create_self_signed_ca("kdc_test_recreate_ca.pem");

        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let client1 = ensure_client();
        assert!(client1.is_ok());

        reset_client_holder();

        let client2 = ensure_client();
        assert!(client2.is_ok());

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_send_to_kdc_agent_psk_network_error() {
        reset_config();
        reset_client_holder();
        let (ca_path, _) = create_self_signed_ca("kdc_test_psk_net_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = "https://127.0.0.1:1/kdc".to_string();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.psk = Some(SecurePsk([3u8; PSK_LEN]));
        }
        let result = send_to_kdc_agent(0x0020, Some("test"));
        assert!(result.is_err());
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_build_kdc_agent_client_invalid_ca_cert_content() {
        reset_config();
        let dir = std::env::temp_dir().join("kdc_test_inv_ca");
        let _ = std::fs::create_dir_all(&dir);
        let ca_path = dir.join("invalid_ca.pem");
        std::fs::write(
            &ca_path,
            "-----BEGIN CERTIFICATE-----\nAAAA\n-----END CERTIFICATE-----\n",
        )
        .unwrap();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }
        let result = build_kdc_agent_client();
        assert!(result.is_err(), "invalid CA cert content should fail");
        let _ = std::fs::remove_dir_all(&dir);
        reset_config();
    }

    #[test]
    fn test_build_kdc_agent_client_invalid_identity_key() {
        reset_config();
        let (ca_path, _) = create_self_signed_ca("kdc_test_inv_id_ca.pem");
        let cert_pem = std::fs::read(&ca_path).unwrap();
        let dir = std::env::temp_dir().join("kdc_test_inv_id");
        let _ = std::fs::create_dir_all(&dir);
        let cert_path = dir.join("cert.pem");
        let key_path = dir.join("key.pem");
        std::fs::write(&cert_path, &cert_pem).unwrap();
        std::fs::write(
            &key_path,
            "-----BEGIN PRIVATE KEY-----\nAAAA\n-----END PRIVATE KEY-----\n",
        )
        .unwrap();
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.certpath = cert_path.to_str().unwrap().to_string();
            guard.privatepath = key_path.to_str().unwrap().to_string();
        }
        let result = build_kdc_agent_client();
        assert!(result.is_err(), "invalid identity key should fail");
        let _ = std::fs::remove_file(&ca_path);
        let _ = std::fs::remove_dir_all(&dir);
        reset_config();
    }

    #[test]
    fn test_send_to_kdc_agent_non_json_response() {
        reset_config();
        reset_client_holder();

        let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        let handle = std::thread::spawn(move || {
            let (mut stream, _) = listener.accept().unwrap();
            let mut buf = vec![0u8; 4096];
            let _ = std::io::Read::read(&mut stream, &mut buf);
            let resp = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello";
            let _ = std::io::Write::write_all(&mut stream, resp.as_bytes());
        });

        let (ca_path, _) = create_self_signed_ca("kdc_test_mock_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = format!("http://127.0.0.1:{}/kdc", port);
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let result = send_to_kdc_agent(0x0020, Some("test"));
        assert!(result.is_err());

        let _ = handle.join();
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_request_token_ra_no_token_in_response() {
        reset_config();
        reset_client_holder();

        let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        let handle = std::thread::spawn(move || {
            let (mut stream, _) = listener.accept().unwrap();
            let mut buf = vec![0u8; 4096];
            let _ = std::io::Read::read(&mut stream, &mut buf);
            let body = r#"{"status":"error","message":"denied"}"#;
            let resp = format!(
                "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}",
                body.len(),
                body
            );
            let _ = std::io::Write::write_all(&mut stream, resp.as_bytes());
        });

        let (ca_path, _) = create_self_signed_ca("kdc_test_ra_mock_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.ra_agent_url = format!("http://127.0.0.1:{}/ra", port);
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let result = request_token_from_ra_agent(None);
        assert!(result.is_err());

        let _ = handle.join();
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_request_token_ra_non_json_response() {
        reset_config();
        reset_client_holder();

        let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        let handle = std::thread::spawn(move || {
            let (mut stream, _) = listener.accept().unwrap();
            let mut buf = vec![0u8; 4096];
            let _ = std::io::Read::read(&mut stream, &mut buf);
            let resp = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello";
            let _ = std::io::Write::write_all(&mut stream, resp.as_bytes());
        });

        let (ca_path, _) = create_self_signed_ca("kdc_test_ra_nj_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.ra_agent_url = format!("http://127.0.0.1:{}/ra", port);
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let result = request_token_from_ra_agent(None);
        assert!(result.is_err());

        let _ = handle.join();
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_send_to_kdc_agent_psk_mismatch_response() {
        reset_config();
        reset_client_holder();

        let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        let handle = std::thread::spawn(move || {
            let (mut stream, _) = listener.accept().unwrap();
            let mut buf = vec![0u8; 4096];
            let _ = std::io::Read::read(&mut stream, &mut buf);
            let body = r#"{"retCode":2,"retMsg":"PSK mismatch","data":null}"#;
            let resp = format!(
                "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}",
                body.len(),
                body
            );
            let _ = std::io::Write::write_all(&mut stream, resp.as_bytes());
        });

        let (ca_path, _) = create_self_signed_ca("kdc_test_psk_mismatch_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = format!("http://127.0.0.1:{}/kdc", port);
            guard.capath = ca_path.to_str().unwrap().to_string();
            guard.psk = Some(SecurePsk([4u8; PSK_LEN]));
        }

        let result = send_to_kdc_agent(0x0020, Some("test"));
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), CommonError::PskMismatchError);

        let _ = handle.join();
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_request_token_ra_with_ec_key_success() {
        reset_config();
        reset_client_holder();

        let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        let handle = std::thread::spawn(move || {
            let (mut stream, _) = listener.accept().unwrap();
            let mut buf = vec![0u8; 4096];
            let _ = std::io::Read::read(&mut stream, &mut buf);
            let body = r#"{"token":"test_attestation_token_123"}"#;
            let resp = format!(
                "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}",
                body.len(),
                body
            );
            let _ = std::io::Write::write_all(&mut stream, resp.as_bytes());
        });

        let (ca_path, _) = create_self_signed_ca("kdc_test_ra_ec_ok_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.ra_agent_url = format!("http://127.0.0.1:{}/ra", port);
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let (ec_key, _pub_pem) = crate::crypto::generate_ec_keypair().unwrap();
        let result = request_token_from_ra_agent(Some(&ec_key));
        assert!(result.is_ok(), "should succeed with mock server");
        let token = result.unwrap();
        assert_eq!(token, "test_attestation_token_123");

        let _ = handle.join();
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_send_to_kdc_agent_request_too_large() {
        reset_config();
        reset_client_holder();

        let (ca_path, _) = create_self_signed_ca("kdc_test_large_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = "http://127.0.0.1:1/kdc".to_string();
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let large_data = "x".repeat(110_000);
        let result = send_to_kdc_agent(0x0020, Some(&large_data));
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), CommonError::RequestError);

        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_send_to_kdc_agent_success_response() {
        reset_config();
        reset_client_holder();

        let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        let handle = std::thread::spawn(move || {
            let (mut stream, _) = listener.accept().unwrap();
            let mut buf = vec![0u8; 4096];
            let _ = std::io::Read::read(&mut stream, &mut buf);
            let body = r#"{"retCode":0,"retMsg":"ok","data":"hello"}"#;
            let resp = format!(
                "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}",
                body.len(),
                body
            );
            let _ = std::io::Write::write_all(&mut stream, resp.as_bytes());
        });

        let (ca_path, _) = create_self_signed_ca("kdc_test_success_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = format!("http://127.0.0.1:{}/kdc", port);
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let result = send_to_kdc_agent(TRUSTED_REGISTER_PSK_REQ, Some("test"));
        assert!(result.is_ok(), "should succeed with 200 OK response");
        let resp = result.unwrap();
        assert_eq!(resp.ret_code, 0);

        let _ = handle.join();
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_request_token_ra_without_ec_key_success() {
        reset_config();
        reset_client_holder();

        let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        let handle = std::thread::spawn(move || {
            let (mut stream, _) = listener.accept().unwrap();
            let mut buf = vec![0u8; 4096];
            let _ = std::io::Read::read(&mut stream, &mut buf);
            let body = r#"{"token":"ra_token_abc"}"#;
            let resp = format!(
                "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}",
                body.len(),
                body
            );
            let _ = std::io::Write::write_all(&mut stream, resp.as_bytes());
        });

        let (ca_path, _) = create_self_signed_ca("kdc_test_ra_no_ec_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.ra_agent_url = format!("http://127.0.0.1:{}/ra", port);
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let result = request_token_from_ra_agent(None);
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), "ra_token_abc");

        let _ = handle.join();
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_send_to_kdc_agent_http_error_status() {
        reset_config();
        reset_client_holder();

        let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        let handle = std::thread::spawn(move || {
            let (mut stream, _) = listener.accept().unwrap();
            let mut buf = vec![0u8; 4096];
            let _ = std::io::Read::read(&mut stream, &mut buf);
            let resp = "HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n";
            let _ = std::io::Write::write_all(&mut stream, resp.as_bytes());
        });

        let (ca_path, _) = create_self_signed_ca("kdc_test_500_ca.pem");
        {
            let config = get_config_center();
            let mut guard = config.lock();
            guard.kdc_agent_url = format!("http://127.0.0.1:{}/kdc", port);
            guard.capath = ca_path.to_str().unwrap().to_string();
        }

        let result = send_to_kdc_agent(0x0020, Some("test"));
        assert!(result.is_err());

        let _ = handle.join();
        let _ = std::fs::remove_file(&ca_path);
        reset_config();
        reset_client_holder();
    }

    #[test]
    fn test_build_kdc_agent_client_with_valid_crl_pem() {
        reset_config();

        let tmp_dir = std::env::temp_dir().join("kdc_test_crl_gen");
        let _ = std::fs::create_dir_all(&tmp_dir);

        let key_path = tmp_dir.join("ca_key.pem");
        let cert_path = tmp_dir.join("ca_cert.pem");
        let crl_path_file = tmp_dir.join("ca.crl.pem");
        let db_path = tmp_dir.join("index.txt");
        let serial_path = tmp_dir.join("serial");
        let crlnum_path = tmp_dir.join("crlnumber");
        let cnf_path = tmp_dir.join("openssl.cnf");

        let _ = std::fs::write(&db_path, "");
        let _ = std::fs::write(&serial_path, "01\n");
        let _ = std::fs::write(&crlnum_path, "01\n");

        let cnf_content = format!(
            "[ca]\ndefault_ca = CA_default\n\n[CA_default]\ndatabase = {}\ncrlnumber = {}\ndefault_md = sha256\ndefault_crl_days = 30\n",
            db_path.display(),
            crlnum_path.display()
        );
        let _ = std::fs::write(&cnf_path, &cnf_content);

        let gen = std::process::Command::new("openssl")
            .args([
                "req",
                "-x509",
                "-newkey",
                "rsa:2048",
                "-keyout",
                key_path.to_str().unwrap(),
                "-out",
                cert_path.to_str().unwrap(),
                "-days",
                "365",
                "-nodes",
                "-subj",
                "/CN=kdc-test-ca",
            ])
            .output();

        let gen = match gen {
            Ok(o) if o.status.success() => o,
            _ => {
                let _ = std::fs::remove_dir_all(&tmp_dir);
                reset_config();
                return;
            }
        };
        let _ = gen;

        let crl_gen = std::process::Command::new("openssl")
            .args([
                "ca",
                "-gencrl",
                "-keyfile",
                key_path.to_str().unwrap(),
                "-cert",
                cert_path.to_str().unwrap(),
                "-out",
                crl_path_file.to_str().unwrap(),
                "-config",
                cnf_path.to_str().unwrap(),
            ])
            .output();

        let crl_valid = match crl_gen {
            Ok(o) if o.status.success() && crl_path_file.exists() => true,
            _ => false,
        };

        if crl_valid {
            {
                let config = get_config_center();
                let mut guard = config.lock();
                guard.capath = cert_path.to_str().unwrap().to_string();
                guard.crlpath = crl_path_file.to_str().unwrap().to_string();
            }
            let _ = build_kdc_agent_client();
        }

        let _ = std::fs::remove_dir_all(&tmp_dir);
        reset_config();
    }
}