from unittest import mock

from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider


class Test_defender_malware_policy_notifications_internal_users_malware_enabled:
    def test_case_1_default_properly_configured(self):
        defender_client = mock.MagicMock()
        defender_client.audited_tenant = "audited_tenant"
        defender_client.audited_domain = DOMAIN

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_m365_provider(),
            ),
            mock.patch(
                "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online"
            ),
            mock.patch(
                "prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client",
                new=defender_client,
            ),
        ):
            from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import (
                defender_malware_policy_notifications_internal_users_malware_enabled,
            )
            from prowler.providers.m365.services.defender.defender_service import (
                MalwarePolicy,
            )

            defender_client.malware_policies = [
                MalwarePolicy(
                    identity="Default",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=True,
                    internal_sender_admin_address="admin@example.com",
                    file_types=[],
                    is_default=True,
                )
            ]
            defender_client.malware_rules = {}

            check = (
                defender_malware_policy_notifications_internal_users_malware_enabled()
            )
            result = check.execute()
            assert len(result) == 1
            assert result[0].status == "PASS"
            assert (
                result[0].status_extended
                == "Default is the only policy and notifications for internal users sending malware are enabled."
            )
            assert result[0].resource_name == "Default"
            assert result[0].resource_id == "Default"
            assert result[0].resource == defender_client.malware_policies[0].dict()

    def test_case_2_default_and_custom_properly_configured(self):
        defender_client = mock.MagicMock()
        defender_client.audited_tenant = "audited_tenant"
        defender_client.audited_domain = DOMAIN

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_m365_provider(),
            ),
            mock.patch(
                "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online"
            ),
            mock.patch(
                "prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client",
                new=defender_client,
            ),
        ):
            from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import (
                defender_malware_policy_notifications_internal_users_malware_enabled,
            )
            from prowler.providers.m365.services.defender.defender_service import (
                MalwarePolicy,
                MalwareRule,
            )

            defender_client.malware_policies = [
                MalwarePolicy(
                    identity="Default",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=True,
                    internal_sender_admin_address="admin@example.com",
                    file_types=[],
                    is_default=True,
                ),
                MalwarePolicy(
                    identity="Policy1",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=True,
                    internal_sender_admin_address="admin@example.com",
                    file_types=[],
                    is_default=False,
                ),
            ]

            defender_client.malware_rules = {
                "Policy1": MalwareRule(
                    state="Enabled",
                    priority=1,
                    users=["user@example.com"],
                    groups=["group1"],
                    domains=["domain.com"],
                )
            }

            check = (
                defender_malware_policy_notifications_internal_users_malware_enabled()
            )
            result = check.execute()
            assert len(result) == 2

            assert result[0].status == "PASS"
            assert (
                result[0].status_extended
                == "Default is the default policy and notifications for internal users sending malware are enabled, but it could be overridden by another misconfigured Custom Policy."
            )
            assert result[0].resource_name == "Default"
            assert result[0].resource_id == "Default"
            assert result[0].resource == defender_client.malware_policies[0].dict()

            assert result[1].status == "PASS"
            assert (
                result[1].status_extended
                == "Custom Malware policy Policy1 is properly configured and includes users: user@example.com; groups: group1; domains: domain.com, "
                "with priority 1 (0 is the highest). Also, the default policy is properly configured, so entities not included by this custom policy could still be correctly protected."
            )
            assert result[1].resource_name == "Policy1"
            assert result[1].resource_id == "Policy1"
            assert result[1].resource == defender_client.malware_policies[1].dict()

    def test_case_3_default_ok_custom_not_configured(self):
        defender_client = mock.MagicMock()
        defender_client.audited_tenant = "audited_tenant"
        defender_client.audited_domain = DOMAIN

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_m365_provider(),
            ),
            mock.patch(
                "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online"
            ),
            mock.patch(
                "prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client",
                new=defender_client,
            ),
        ):
            from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import (
                defender_malware_policy_notifications_internal_users_malware_enabled,
            )
            from prowler.providers.m365.services.defender.defender_service import (
                MalwarePolicy,
                MalwareRule,
            )

            defender_client.malware_policies = [
                MalwarePolicy(
                    identity="Default",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=True,
                    internal_sender_admin_address="admin@example.com",
                    file_types=[],
                    is_default=True,
                ),
                MalwarePolicy(
                    identity="Policy1",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=False,
                    internal_sender_admin_address="",
                    file_types=[],
                    is_default=False,
                ),
            ]

            defender_client.malware_rules = {
                "Policy1": MalwareRule(
                    state="Enabled",
                    priority=2,
                    users=["internal@example.com"],
                    groups=["group2"],
                    domains=["example.org"],
                )
            }

            check = (
                defender_malware_policy_notifications_internal_users_malware_enabled()
            )
            result = check.execute()
            assert len(result) == 2

            assert result[0].status == "PASS"
            assert (
                result[0].status_extended
                == "Default is the default policy and notifications for internal users sending malware are enabled, but it could be overridden by another misconfigured Custom Policy."
            )
            assert result[0].resource_name == "Default"
            assert result[0].resource_id == "Default"
            assert result[0].resource == defender_client.malware_policies[0].dict()

            assert result[1].status == "FAIL"
            assert (
                result[1].status_extended
                == "Custom Malware policy Policy1 is not properly configured and includes users: internal@example.com; groups: group2; domains: example.org, "
                "with priority 2 (0 is the highest). However, the default policy is properly configured, so entities not included by this custom policy could be correctly protected."
            )
            assert result[1].resource_name == "Policy1"
            assert result[1].resource_id == "Policy1"
            assert result[1].resource == defender_client.malware_policies[1].dict()

    def test_case_4_default_not_ok_custom_properly_configured(self):
        defender_client = mock.MagicMock()
        defender_client.audited_tenant = "audited_tenant"
        defender_client.audited_domain = DOMAIN

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_m365_provider(),
            ),
            mock.patch(
                "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online"
            ),
            mock.patch(
                "prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client",
                new=defender_client,
            ),
        ):
            from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import (
                defender_malware_policy_notifications_internal_users_malware_enabled,
            )
            from prowler.providers.m365.services.defender.defender_service import (
                MalwarePolicy,
                MalwareRule,
            )

            defender_client.malware_policies = [
                MalwarePolicy(
                    identity="Default",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=False,
                    internal_sender_admin_address="",
                    file_types=[],
                    is_default=True,
                ),
                MalwarePolicy(
                    identity="Policy1",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=True,
                    internal_sender_admin_address="admin@example.com",
                    file_types=[],
                    is_default=False,
                ),
            ]

            defender_client.malware_rules = {
                "Policy1": MalwareRule(
                    state="Enabled",
                    priority=0,
                    users=["user@example.com"],
                    groups=["group1"],
                    domains=["domain.com"],
                )
            }

            check = (
                defender_malware_policy_notifications_internal_users_malware_enabled()
            )
            result = check.execute()
            assert len(result) == 2

            assert result[0].status == "FAIL"
            assert (
                result[0].status_extended
                == "Default is the default policy and notifications for internal users sending malware are not enabled, but it could be overridden by another well-configured Custom Policy."
            )
            assert result[0].resource_name == "Default"
            assert result[0].resource_id == "Default"
            assert result[0].resource == defender_client.malware_policies[0].dict()

            assert result[1].status == "PASS"
            assert (
                result[1].status_extended
                == "Custom Malware policy Policy1 is properly configured and includes users: user@example.com; groups: group1; domains: domain.com, "
                "with priority 0 (0 is the highest). However, the default policy is not properly configured, so entities not included by this custom policy could not be correctly protected."
            )
            assert result[1].resource_name == "Policy1"
            assert result[1].resource_id == "Policy1"
            assert result[1].resource == defender_client.malware_policies[1].dict()

    def test_case_5_only_default_not_ok(self):
        defender_client = mock.MagicMock()
        defender_client.audited_tenant = "audited_tenant"
        defender_client.audited_domain = DOMAIN

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_m365_provider(),
            ),
            mock.patch(
                "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online"
            ),
            mock.patch(
                "prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client",
                new=defender_client,
            ),
        ):
            from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import (
                defender_malware_policy_notifications_internal_users_malware_enabled,
            )
            from prowler.providers.m365.services.defender.defender_service import (
                MalwarePolicy,
            )

            defender_client.malware_policies = [
                MalwarePolicy(
                    identity="Default",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=False,
                    internal_sender_admin_address="",
                    file_types=[],
                    is_default=True,
                )
            ]
            defender_client.malware_rules = {}

            check = (
                defender_malware_policy_notifications_internal_users_malware_enabled()
            )
            result = check.execute()
            assert len(result) == 1
            assert result[0].status == "FAIL"
            assert (
                result[0].status_extended
                == "Default is the only policy and notifications for internal users sending malware are not enabled."
            )
            assert result[0].resource_name == "Default"
            assert result[0].resource_id == "Default"
            assert result[0].resource == defender_client.malware_policies[0].dict()

    def test_case_6_default_and_custom_not_configured(self):
        defender_client = mock.MagicMock()
        defender_client.audited_tenant = "audited_tenant"
        defender_client.audited_domain = DOMAIN

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_m365_provider(),
            ),
            mock.patch(
                "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online"
            ),
            mock.patch(
                "prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client",
                new=defender_client,
            ),
        ):
            from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import (
                defender_malware_policy_notifications_internal_users_malware_enabled,
            )
            from prowler.providers.m365.services.defender.defender_service import (
                MalwarePolicy,
                MalwareRule,
            )

            defender_client.malware_policies = [
                MalwarePolicy(
                    identity="Default",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=False,
                    internal_sender_admin_address="",
                    file_types=[],
                    is_default=True,
                ),
                MalwarePolicy(
                    identity="Policy1",
                    enable_file_filter=False,
                    enable_internal_sender_admin_notifications=False,
                    internal_sender_admin_address="",
                    file_types=[],
                    is_default=False,
                ),
            ]

            defender_client.malware_rules = {
                "Policy1": MalwareRule(
                    state="Enabled",
                    priority=3,
                    users=["u@example.com"],
                    groups=["g1"],
                    domains=["d.com"],
                )
            }

            check = (
                defender_malware_policy_notifications_internal_users_malware_enabled()
            )
            result = check.execute()
            assert len(result) == 2

            assert result[0].status == "FAIL"
            assert (
                result[0].status_extended
                == "Default is the default policy and notifications for internal users sending malware are not enabled, but it could be overridden by another well-configured Custom Policy."
            )
            assert result[0].resource_name == "Default"
            assert result[0].resource_id == "Default"
            assert result[0].resource == defender_client.malware_policies[0].dict()

            assert result[1].status == "FAIL"
            assert (
                result[1].status_extended
                == "Custom Malware policy Policy1 is not properly configured and includes users: u@example.com; groups: g1; domains: d.com, "
                "with priority 3 (0 is the highest). Also, the default policy is not properly configured, so entities not included by this custom policy could not be correctly protected."
            )
            assert result[1].resource_name == "Policy1"
            assert result[1].resource_id == "Policy1"
            assert result[1].resource == defender_client.malware_policies[1].dict()

    def test_no_malware_policies(self):
        defender_client = mock.MagicMock()
        defender_client.audited_tenant = "audited_tenant"
        defender_client.audited_domain = DOMAIN

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_m365_provider(),
            ),
            mock.patch(
                "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online"
            ),
            mock.patch(
                "prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client",
                new=defender_client,
            ),
        ):
            from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import (
                defender_malware_policy_notifications_internal_users_malware_enabled,
            )

            defender_client.malware_policies = []
            defender_client.malware_rules = {}

            check = (
                defender_malware_policy_notifications_internal_users_malware_enabled()
            )
            result = check.execute()
            assert len(result) == 0
