use std::collections::HashSet;

use online_config::OnlineConfig;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default, OnlineConfig)]
#[serde(default)]
#[serde(rename_all = "kebab-case")]
pub struct SecurityConfig {
    // SSL configs.
    #[online_config(skip)]
    pub ca_path: String,
    #[online_config(skip)]
    pub cert_path: String,
    #[online_config(skip)]
    pub key_path: String,
    // Test purpose only.
    #[serde(skip)]
    #[online_config(skip)]
    pub override_ssl_target: String,
    #[online_config(skip)]
    pub cert_allowed_cn: HashSet<String>,
    // pub redact_info_log: RedactOption,
    // #[online_config(skip)]
    // pub encryption: EncryptionConfig,
}

impl SecurityConfig {
    pub fn is_valid(&self) -> bool {
        !self.ca_path.is_empty() && !self.cert_path.is_empty() && !self.key_path.is_empty()
    }
}

#[cfg(test)]
mod tests {

    use super::SecurityConfig;
    #[test]
    fn test_parse_from_toml() {
        let toml_str = r#"
        ca-path = "/path/to/ca.pem"
        cert-path = "/path/to/cert.pem"
        key-path = "/path/to/key.pem"
        cert-allowed-cn = ["example.com", "test.com"]
        "#;

        let config: SecurityConfig = toml::from_str(toml_str).unwrap();
        assert_eq!(config.ca_path, "/path/to/ca.pem");
        assert_eq!(config.cert_path, "/path/to/cert.pem");
        assert_eq!(config.key_path, "/path/to/key.pem");
        assert!(config.cert_allowed_cn.contains("example.com"));
        assert!(config.cert_allowed_cn.contains("test.com"));
    }

    #[test]
    fn test_is_valid() {
        let valid_config = SecurityConfig {
            ca_path: "/path/to/ca.pem".to_string(),
            cert_path: "/path/to/cert.pem".to_string(),
            key_path: "/path/to/key.pem".to_string(),
            ..Default::default()
        };
        assert!(valid_config.is_valid());

        let invalid_config = SecurityConfig {
            ca_path: "".to_string(),
            cert_path: "/path/to/cert.pem".to_string(),
            key_path: "/path/to/key.pem".to_string(),
            ..Default::default()
        };
        assert!(!invalid_config.is_valid());
    }
}
