#[cfg(test)]
mod test {
    use std::{collections::HashSet, str::FromStr};

    use defguard_common::{
        config::{DefGuardConfig, SERVER_CONFIG},
        db::{
            models::{
                Device, DeviceType, Session, SessionState, Settings, WireguardNetwork,
                settings::initialize_current_settings,
                wireguard::{LocationMfaMode, ServiceLocationMode},
            },
            setup_pool,
        },
    };
    use ipnetwork::IpNetwork;
    use sqlx::postgres::{PgConnectOptions, PgPoolOptions};
    use tokio::sync::broadcast;

    use super::super::*;
    use crate::{
        enterprise::{
            db::models::openid_provider::{DirectorySyncTarget, OpenIdProviderKind},
            license::{License, LicenseTier, SupportType, set_cached_license},
            limits::{get_counts, update_counts},
        },
        grpc::proto::enterprise::license::LicenseLimits,
    };

    async fn get_test_network(pool: &PgPool) -> WireguardNetwork<Id> {
        WireguardNetwork::find_by_name(pool, "test")
            .await
            .unwrap()
            .unwrap()
            .pop()
            .unwrap()
    }

    async fn make_test_provider(
        pool: &PgPool,
        user_behavior: DirectorySyncUserBehavior,
        admin_behavior: DirectorySyncUserBehavior,
        target: DirectorySyncTarget,
        prefetch_users: bool,
    ) -> OpenIdProvider<Id> {
        Settings::initialize_runtime_defaults(pool).await.unwrap();
        initialize_current_settings(pool).await.unwrap();

        let current = OpenIdProvider::get_current(pool).await.unwrap();

        if let Some(provider) = current {
            provider.delete(pool).await.unwrap();
        }

        WireguardNetwork::new(
            "test".to_string(),
            1234,
            "123.123.123.123".to_string(),
            None,
            Vec::new(),
            true,
            false,
            false,
            LocationMfaMode::Disabled,
            ServiceLocationMode::Disabled,
        )
        .set_address([IpNetwork::from_str("10.10.10.1/24").unwrap()])
        .unwrap()
        .save(pool)
        .await
        .unwrap();

        OpenIdProvider::new(
            "Test".to_string(),
            "base_url".to_string(),
            OpenIdProviderKind::Google,
            "client_id".to_string(),
            "client_secret".to_string(),
            Some("display_name".to_string()),
            Some("google_service_account_key".to_string()),
            Some("google_service_account_email".to_string()),
            Some("admin_email".to_string()),
            true,
            60,
            user_behavior,
            admin_behavior,
            target,
            None,
            None,
            Vec::new(),
            None,
            prefetch_users,
            None,
        )
        .save(pool)
        .await
        .unwrap()
    }

    async fn make_test_user_and_device(name: &str, pool: &PgPool) -> User<Id> {
        let mut transaction = pool.begin().await.unwrap();

        let user = User::new(
            name,
            None,
            "lastname",
            "firstname",
            format!("{name}@email.com").as_str(),
            None,
        )
        .save(&mut *transaction)
        .await
        .unwrap();

        let dev = Device::new(
            format!("{name}-device"),
            format!("{name}-key"),
            user.id,
            DeviceType::User,
            None,
            true,
        )
        .save(&mut *transaction)
        .await
        .unwrap();

        dev.add_to_all_networks(&mut transaction).await.unwrap();

        transaction.commit().await.unwrap();

        user
    }

    async fn get_test_user(pool: &PgPool, name: &str) -> Option<User<Id>> {
        User::find_by_username(pool, name).await.unwrap()
    }

    async fn make_admin(pool: &PgPool, user: &User<Id>) {
        let admin_group = Group::find_by_name(pool, "admin").await.unwrap().unwrap();
        user.add_to_group(pool, &admin_group).await.unwrap();
    }

    // Keep both users and admins
    #[sqlx::test]
    async fn test_users_state_keep_both(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();
        let user1 = make_test_user_and_device("user1", &pool).await;
        make_test_user_and_device("user2", &pool).await;
        make_test_user_and_device("testuser", &pool).await;
        make_admin(&pool, &user1).await;

        assert!(get_test_user(&pool, "user1").await.is_some());
        assert!(get_test_user(&pool, "user2").await.is_some());
        assert!(get_test_user(&pool, "testuser").await.is_some());

        let all_users = client.get_all_users().await.unwrap();
        sync_all_users_state(&pool, &wg_tx, &all_users, None)
            .await
            .unwrap();

        assert!(get_test_user(&pool, "user1").await.is_some());
        assert!(get_test_user(&pool, "user2").await.is_some());
        assert!(get_test_user(&pool, "testuser").await.is_some());

        // No events
        assert!(wg_rx.try_recv().is_err());
    }

    // Delete users, keep admins
    #[sqlx::test]
    async fn test_users_state_delete_users(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        let user1 = make_test_user_and_device("user1", &pool).await;
        let user2 = make_test_user_and_device("user2", &pool).await;
        make_test_user_and_device("testuser", &pool).await;
        make_admin(&pool, &user1).await;

        assert!(get_test_user(&pool, "user1").await.is_some());
        assert!(get_test_user(&pool, "user2").await.is_some());
        assert!(get_test_user(&pool, "testuser").await.is_some());

        let all_users = client.get_all_users().await.unwrap();
        sync_all_users_state(&pool, &wg_tx, &all_users, None)
            .await
            .unwrap();

        assert!(get_test_user(&pool, "user1").await.is_some());
        assert!(get_test_user(&pool, "user2").await.is_none());
        assert!(get_test_user(&pool, "testuser").await.is_some());

        let event = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event {
            assert_eq!(dev.device.user_id, user2.id);
        } else {
            panic!("Expected a DeviceDeleted event");
        }
    }
    #[sqlx::test]
    async fn test_users_state_delete_admins(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);
        User::init_admin_user(&pool, "pass123").await.unwrap();

        let _ = make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        let user1 = make_test_user_and_device("user1", &pool).await;
        make_test_user_and_device("user2", &pool).await;
        let user3 = make_test_user_and_device("user3", &pool).await;
        make_test_user_and_device("testuser", &pool).await;
        make_admin(&pool, &user1).await;
        make_admin(&pool, &user3).await;

        assert!(get_test_user(&pool, "user1").await.is_some());
        assert!(get_test_user(&pool, "user2").await.is_some());
        assert!(get_test_user(&pool, "testuser").await.is_some());
        let all_users = client.get_all_users().await.unwrap();
        sync_all_users_state(&pool, &wg_tx, &all_users, None)
            .await
            .unwrap();

        assert!(
            get_test_user(&pool, "user1").await.is_none()
                || get_test_user(&pool, "user3").await.is_none()
        );
        assert!(
            get_test_user(&pool, "user1").await.is_some()
                || get_test_user(&pool, "user3").await.is_some()
        );
        assert!(get_test_user(&pool, "user2").await.is_some());
        assert!(get_test_user(&pool, "testuser").await.is_some());

        // Check that we received a device deleted event for whichever admin was removed
        let event = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event {
            assert!(dev.device.user_id == user1.id || dev.device.user_id == user3.id);
        } else {
            panic!("Expected a DeviceDeleted event");
        }
    }

    #[sqlx::test]
    async fn test_users_state_delete_both(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        User::init_admin_user(&pool, "pass123").await.unwrap();
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        let user1 = make_test_user_and_device("user1", &pool).await;
        let user2 = make_test_user_and_device("user2", &pool).await;
        let user3 = make_test_user_and_device("user3", &pool).await;
        make_test_user_and_device("testuser", &pool).await;
        make_admin(&pool, &user1).await;
        make_admin(&pool, &user3).await;

        assert!(get_test_user(&pool, "user1").await.is_some());
        assert!(get_test_user(&pool, "user2").await.is_some());
        assert!(get_test_user(&pool, "testuser").await.is_some());
        let all_users = client.get_all_users().await.unwrap();
        sync_all_users_state(&pool, &wg_tx, &all_users, None)
            .await
            .unwrap();

        assert!(
            get_test_user(&pool, "user1").await.is_none()
                || get_test_user(&pool, "user3").await.is_none()
        );
        assert!(
            get_test_user(&pool, "user1").await.is_some()
                || get_test_user(&pool, "user3").await.is_some()
        );
        assert!(get_test_user(&pool, "user2").await.is_none());
        assert!(get_test_user(&pool, "testuser").await.is_some());

        // Check for device deletion events
        let event1 = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event1 {
            assert!(
                dev.device.user_id == user1.id
                    || dev.device.user_id == user2.id
                    || dev.device.user_id == user3.id
            );
        } else {
            panic!("Expected a DeviceDeleted event");
        }

        let event2 = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event2 {
            assert!(
                dev.device.user_id == user1.id
                    || dev.device.user_id == user2.id
                    || dev.device.user_id == user3.id
            );
        } else {
            panic!("Expected a DeviceDeleted event");
        }
    }

    #[sqlx::test]
    async fn test_users_state_disable_users(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Disable,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        let user1 = make_test_user_and_device("user1", &pool).await;
        make_test_user_and_device("user2", &pool).await;
        make_test_user_and_device("testuser", &pool).await;
        make_test_user_and_device("testuserdisabled", &pool).await;
        make_admin(&pool, &user1).await;

        let user1 = get_test_user(&pool, "user1").await.unwrap();
        let user2 = get_test_user(&pool, "user2").await.unwrap();
        let testuser = get_test_user(&pool, "testuser").await.unwrap();
        let testuserdisabled = get_test_user(&pool, "testuserdisabled").await.unwrap();
        let disabled_user_session = Session::new(
            testuserdisabled.id,
            SessionState::PasswordVerified,
            "127.0.0.1".into(),
            None,
        );
        disabled_user_session.save(&pool).await.unwrap();
        assert!(
            Session::find_by_id(&pool, &disabled_user_session.id)
                .await
                .unwrap()
                .is_some()
        );

        assert!(user1.is_active);
        assert!(user2.is_active);
        assert!(testuser.is_active);
        assert!(testuserdisabled.is_active);

        let all_users = client.get_all_users().await.unwrap();
        sync_all_users_state(&pool, &wg_tx, &all_users, None)
            .await
            .unwrap();

        // Check for device disconnection events
        let event1 = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event1 {
            assert!(dev.device.user_id == user2.id || dev.device.user_id == testuserdisabled.id);
        } else {
            panic!("Expected a DeviceDisconnected event");
        }

        let event2 = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event2 {
            assert!(dev.device.user_id == user2.id || dev.device.user_id == testuserdisabled.id);
        } else {
            panic!("Expected a DeviceDisconnected event");
        }

        let user1 = get_test_user(&pool, "user1").await.unwrap();
        let user2 = get_test_user(&pool, "user2").await.unwrap();
        let testuser = get_test_user(&pool, "testuser").await.unwrap();
        let testuserdisabled = get_test_user(&pool, "testuserdisabled").await.unwrap();

        assert!(
            Session::find_by_id(&pool, &disabled_user_session.id)
                .await
                .unwrap()
                .is_none()
        );
        assert!(user1.is_active);
        assert!(!user2.is_active);
        assert!(testuser.is_active);
        assert!(!testuserdisabled.is_active);
    }
    #[sqlx::test]
    async fn test_users_state_disable_admins(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16); // Added mut wg_rx
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Disable,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        let user1 = make_test_user_and_device("user1", &pool).await;
        make_test_user_and_device("user2", &pool).await;
        let user3 = make_test_user_and_device("user3", &pool).await;
        make_test_user_and_device("testuser", &pool).await;
        make_test_user_and_device("testuserdisabled", &pool).await;
        make_admin(&pool, &user1).await;
        make_admin(&pool, &user3).await;

        let user1 = get_test_user(&pool, "user1").await.unwrap();
        let user2 = get_test_user(&pool, "user2").await.unwrap();
        let testuser = get_test_user(&pool, "testuser").await.unwrap();
        let testuserdisabled = get_test_user(&pool, "testuserdisabled").await.unwrap();

        assert!(user1.is_active);
        assert!(user2.is_active);
        assert!(user3.is_active);
        assert!(testuser.is_active);
        assert!(testuserdisabled.is_active);

        let all_users = client.get_all_users().await.unwrap();
        sync_all_users_state(&pool, &wg_tx, &all_users, None)
            .await
            .unwrap();

        // Check for device disconnection events
        let event1 = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event1 {
            assert!(
                dev.device.user_id == user1.id
                    || dev.device.user_id == user3.id
                    || dev.device.user_id == testuserdisabled.id
            );
        } else {
            panic!("Expected a DeviceDisconnected event");
        }

        let event2 = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event2 {
            assert!(
                dev.device.user_id == user1.id
                    || dev.device.user_id == user3.id
                    || dev.device.user_id == testuserdisabled.id
            );
        } else {
            panic!("Expected a DeviceDisconnected event");
        }

        let user1 = get_test_user(&pool, "user1").await.unwrap();
        let user2 = get_test_user(&pool, "user2").await.unwrap();
        let user3 = get_test_user(&pool, "user3").await.unwrap();
        let testuser = get_test_user(&pool, "testuser").await.unwrap();
        let testuserdisabled = get_test_user(&pool, "testuserdisabled").await.unwrap();

        assert!(!user1.is_active || !user3.is_active);
        assert!(user1.is_active || user3.is_active);
        assert!(user2.is_active);
        assert!(testuser.is_active);
        assert!(!testuserdisabled.is_active);
    }

    #[sqlx::test]
    async fn test_users_groups(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, _) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        make_test_user_and_device("testuser", &pool).await;
        make_test_user_and_device("testuser2", &pool).await;
        make_test_user_and_device("testuserdisabled", &pool).await;
        let all_users = client.get_all_users().await.unwrap();
        sync_all_users_groups(&client, &pool, &wg_tx, Some(&all_users))
            .await
            .unwrap();

        let mut groups = Group::all(&pool).await.unwrap();

        let testuser = get_test_user(&pool, "testuser").await.unwrap();
        let testuser2 = get_test_user(&pool, "testuser2").await.unwrap();
        let testuserdisabled = get_test_user(&pool, "testuserdisabled").await.unwrap();

        let testuser_groups = testuser.member_of(&pool).await.unwrap();
        let testuser2_groups = testuser2.member_of(&pool).await.unwrap();
        let testuserdisabled_groups = testuserdisabled.member_of(&pool).await.unwrap();

        assert_eq!(testuser_groups.len(), 3);
        assert_eq!(testuser2_groups.len(), 3);
        assert_eq!(testuserdisabled_groups.len(), 3);
        groups.sort_by(|a, b| a.name.cmp(&b.name));

        let group_present =
            |groups: &Vec<Group<Id>>, name: &str| groups.iter().any(|g| g.name == name);

        assert!(group_present(&testuser_groups, "group1"));
        assert!(group_present(&testuser_groups, "group2"));
        assert!(group_present(&testuser_groups, "group3"));

        assert!(group_present(&testuser2_groups, "group1"));
        assert!(group_present(&testuser2_groups, "group2"));
        assert!(group_present(&testuser2_groups, "group3"));

        assert!(group_present(&testuserdisabled_groups, "group1"));
        assert!(group_present(&testuserdisabled_groups, "group2"));
        assert!(group_present(&testuserdisabled_groups, "group3"));
    }

    #[sqlx::test]
    async fn test_sync_user_groups(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, _) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();
        let user = make_test_user_and_device("testuser", &pool).await;
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 0);
        sync_user_groups_if_configured(&user, &pool, &wg_tx)
            .await
            .unwrap();
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 1);
        let group = Group::find_by_name(&pool, "group1").await.unwrap().unwrap();
        assert_eq!(user_groups[0].id, group.id);
    }

    #[sqlx::test]
    async fn test_sync_target_users(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, _) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::Users,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();
        let user = make_test_user_and_device("testuser", &pool).await;
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 0);
        do_directory_sync(&pool, &wg_tx).await.unwrap();
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 0);
    }

    #[sqlx::test]
    async fn test_sync_target_all(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let network = get_test_network(&pool).await;
        let mut transaction = pool.begin().await.unwrap();
        let group = Group::new("group1").save(&mut *transaction).await.unwrap();
        network
            .set_allowed_groups(&mut transaction, &[group.name])
            .await
            .unwrap();
        transaction.commit().await.unwrap();
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();
        let user = make_test_user_and_device("testuser", &pool).await;
        let user2_pre_sync = make_test_user_and_device("user2", &pool).await;
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 0);
        do_directory_sync(&pool, &wg_tx).await.unwrap();
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 3);
        let user2 = get_test_user(&pool, "user2").await;
        assert!(user2.is_none());
        let mut transaction = pool.begin().await.unwrap();
        sync_allowed_user_devices(&user, &mut transaction, &wg_tx)
            .await
            .unwrap();
        transaction.commit().await.unwrap();
        let event = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceDeleted(dev)) = event {
            assert_eq!(dev.device.user_id, user2_pre_sync.id);
        } else {
            panic!("Expected DeviceDeleted event");
        }
        let event = wg_rx.try_recv();
        if let Ok(GatewayEvent::DeviceCreated(dev)) = event {
            panic!("Unexpected DeviceCreated event: {dev:?}");
        }
    }

    #[sqlx::test]
    async fn test_sync_target_groups(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, _) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::Groups,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();
        let user = make_test_user_and_device("testuser", &pool).await;
        make_test_user_and_device("user2", &pool).await;
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 0);
        do_directory_sync(&pool, &wg_tx).await.unwrap();
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 3);
        let user2 = get_test_user(&pool, "user2").await;
        assert!(user2.is_some());
    }

    #[sqlx::test]
    async fn test_sync_unassign_last_admin_group(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, _) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        // Make one admin and check if he's deleted
        let user = make_test_user_and_device("testuser", &pool).await;
        let admin_grp = Group::find_by_name(&pool, "admin").await.unwrap().unwrap();
        user.add_to_group(&pool, &admin_grp).await.unwrap();
        let user_groups = user.member_of(&pool).await.unwrap();
        assert_eq!(user_groups.len(), 1);
        assert!(user.is_admin(&pool).await.unwrap());

        do_directory_sync(&pool, &wg_tx).await.unwrap();

        // He should still be an admin as it's the last one
        assert!(user.is_admin(&pool).await.unwrap());

        // Make another admin and check if one of them is deleted
        let user2 = make_test_user_and_device("testuser2", &pool).await;
        user2.add_to_group(&pool, &admin_grp).await.unwrap();

        do_directory_sync(&pool, &wg_tx).await.unwrap();

        let admins = User::find_admins(&pool).await.unwrap();
        // There should be only one admin left
        assert_eq!(admins.len(), 1);

        let defguard_user = make_test_user_and_device("defguard", &pool).await;
        make_admin(&pool, &defguard_user).await;

        do_directory_sync(&pool, &wg_tx).await.unwrap();
    }

    #[sqlx::test]
    async fn test_sync_delete_last_admin_user(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, _) = broadcast::channel::<GatewayEvent>(16);
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncUserBehavior::Delete,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        // a user that's not in the directory
        let defguard_user = make_test_user_and_device("defguard", &pool).await;
        make_admin(&pool, &defguard_user).await;
        assert!(defguard_user.is_admin(&pool).await.unwrap());

        do_directory_sync(&pool, &wg_tx).await.unwrap();

        // The user should still be an admin
        assert!(defguard_user.is_admin(&pool).await.unwrap());

        // remove his admin status
        let admin_grp = Group::find_by_name(&pool, "admin").await.unwrap().unwrap();
        defguard_user
            .remove_from_group(&pool, &admin_grp)
            .await
            .unwrap();

        do_directory_sync(&pool, &wg_tx).await.unwrap();
        let user = User::find_by_username(&pool, "defguard").await.unwrap();
        assert!(user.is_none());
    }

    #[sqlx::test]
    async fn test_users_no_prefetch(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);

        // disable prefetching users
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            false,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        // no users in Defguard before sync
        let defguard_users = User::all(&pool).await.unwrap();
        assert!(defguard_users.is_empty());

        do_directory_sync(&pool, &wg_tx).await.unwrap();

        // no users in Defguard after sync
        let defguard_users = User::all(&pool).await.unwrap();
        assert!(defguard_users.is_empty());

        // No events
        assert!(wg_rx.try_recv().is_err());
    }

    #[sqlx::test]
    async fn test_users_prefetch(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);

        // enable prefetching users
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            true,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        // no users in Defguard before sync
        let defguard_users = User::all(&pool).await.unwrap();
        assert!(defguard_users.is_empty());

        do_directory_sync(&pool, &wg_tx).await.unwrap();

        // all active directory users were synced
        let defguard_users = User::all(&pool).await.unwrap();
        assert_eq!(defguard_users.len(), 3);

        // No events
        assert!(wg_rx.try_recv().is_err());
    }

    #[sqlx::test]
    async fn test_users_prefetch_group_filter(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);

        // enable prefetching users, import only members of group1
        let mut provider = make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            true,
        )
        .await;
        provider.directory_sync_user_groups = Some(vec!["group1".to_string()]);
        provider.save(&pool).await.unwrap();

        // no users in Defguard before sync
        let defguard_users = User::all(&pool).await.unwrap();
        assert!(defguard_users.is_empty());

        do_directory_sync(&pool, &wg_tx).await.unwrap();

        // all directory users are members of group1, so all of them were imported
        let defguard_users = User::all(&pool).await.unwrap();
        assert_eq!(defguard_users.len(), 3);

        // No events
        assert!(wg_rx.try_recv().is_err());
    }

    #[sqlx::test]
    async fn test_users_prefetch_group_filter_no_match(
        _: PgPoolOptions,
        options: PgConnectOptions,
    ) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);

        // enable prefetching users, import only members of a group that doesn't exist
        // in the directory
        let mut provider = make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::Users,
            true,
        )
        .await;
        provider.directory_sync_user_groups = Some(vec!["nonexistent-group".to_string()]);
        provider.save(&pool).await.unwrap();

        do_directory_sync(&pool, &wg_tx).await.unwrap();

        // no users were imported
        let defguard_users = User::all(&pool).await.unwrap();
        assert!(defguard_users.is_empty());

        // No events
        assert!(wg_rx.try_recv().is_err());
    }

    #[sqlx::test]
    async fn test_users_prefetch_allowed_emails(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);

        // enable prefetching users
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            true,
        )
        .await;
        let mut client = DirectorySyncClient::build(&pool).await.unwrap();
        client.prepare().await.unwrap();

        // no users in Defguard before sync
        let defguard_users = User::all(&pool).await.unwrap();
        assert!(defguard_users.is_empty());

        // only allow one of the directory users to be imported
        let allowed_emails = HashSet::from(["testuser@email.com".to_string()]);
        let all_users = client.get_all_users().await.unwrap();
        sync_all_users_state(&pool, &wg_tx, &all_users, Some(allowed_emails))
            .await
            .unwrap();

        // only the allowed user was imported
        let defguard_users = User::all(&pool).await.unwrap();
        assert_eq!(defguard_users.len(), 1);
        assert_eq!(defguard_users[0].email, "testuser@email.com");

        // No events
        assert!(wg_rx.try_recv().is_err());
    }

    #[sqlx::test]
    async fn test_user_in_directory_groups(_: PgPoolOptions, options: PgConnectOptions) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config.clone());
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            false,
        )
        .await;

        // the test provider returns group1 as the only group of any user
        assert!(
            user_in_directory_groups(&pool, "testuser@email.com", &["group1".to_string()])
                .await
                .unwrap()
        );
        assert!(
            !user_in_directory_groups(&pool, "testuser@email.com", &["group2".to_string()])
                .await
                .unwrap()
        );
    }

    #[sqlx::test]
    async fn test_users_prefetch_respects_license_user_limit(
        _: PgPoolOptions,
        options: PgConnectOptions,
    ) {
        let pool = setup_pool(options).await;

        let config = DefGuardConfig::new_test_config();
        let _ = SERVER_CONFIG.set(config);
        let (wg_tx, mut wg_rx) = broadcast::channel::<GatewayEvent>(16);

        // enable prefetching users
        make_test_provider(
            &pool,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncUserBehavior::Keep,
            DirectorySyncTarget::All,
            true,
        )
        .await;

        let user_limit = 1;
        let license = License::new(
            "test".to_string(),
            false,
            None,
            Some(LicenseLimits {
                users: user_limit,
                devices: 100,
                locations: 100,
                network_devices: Some(100),
            }),
            None,
            LicenseTier::Business,
            SupportType::Basic,
        );
        set_cached_license(Some(license));
        update_counts(&pool).await.unwrap();

        do_directory_sync(&pool, &wg_tx).await.unwrap();
        update_counts(&pool).await.unwrap();

        let user_count = get_counts().user();
        assert!(user_count <= user_limit);

        let defguard_users = User::all(&pool).await.unwrap();
        assert_eq!(defguard_users.len(), user_limit as usize);

        // No events
        assert!(wg_rx.try_recv().is_err());
    }
}
