pub mod config;
pub mod error;
pub mod modules;

pub use config::Config;
pub use error::Error;

#[cfg(e2e_test)]
mod e2e_test {
    use opnsense_config_xml::StaticMap;
    use std::net::Ipv4Addr;

    use crate::Config;

    #[tokio::test]
    async fn test_public_sdk() {
        use pretty_assertions::assert_eq;
        let mac = "11:22:33:44:55:66";
        let ip = Ipv4Addr::new(10, 100, 8, 200);
        let hostname = "test_hostname";

        remove_static_mapping(mac).await;

        // Make sure static mapping does not exist anymore
        let static_mapping_removed = get_static_mappings().await;
        assert!(!static_mapping_removed.iter().any(|e| e.mac == mac));

        add_static_mapping(mac, ip, hostname).await;

        // Make sure static mapping has been added successfully
        let static_mapping_added = get_static_mappings().await;
        assert_eq!(static_mapping_added.len(), static_mapping_removed.len() + 1);
        assert!(static_mapping_added.iter().any(|e| e.mac == mac));
    }

    async fn initialize_config() -> Config {
        Config::from_credentials(
            std::net::IpAddr::V4(Ipv4Addr::new(192, 168, 5, 229)),
            None,
            "root",
            "opnsense",
        )
        .await
    }

    async fn get_static_mappings() -> Vec<StaticMap> {
        let mut config = initialize_config().await;
        config.dhcp().get_static_mappings().await.unwrap()
    }

    async fn add_static_mapping(mac: &str, ip: Ipv4Addr, hostname: &str) {
        let mut config = initialize_config().await;
        config.dhcp().add_static_mapping(mac, ip, hostname).unwrap();
        config.apply().await.unwrap();
    }

    async fn remove_static_mapping(mac: &str) {
        let mut config = initialize_config().await;
        config.dhcp().remove_static_mapping(mac);
        config.apply().await.unwrap();
    }
}
