from typing import List

from prowler.lib.check.models import Check, CheckReportM365
from prowler.providers.m365.services.defender.defender_client import defender_client


class defender_malware_policy_notifications_internal_users_malware_enabled(Check):
    """
    Check if notifications for internal users sending malware are enabled in the Defender anti-malware policy.

    Attributes:
        metadata: Metadata associated with the check (inherited from Check).
    """

    def execute(self) -> List[CheckReportM365]:
        """
        Execute the check to verify if notifications for internal users sending malware are enabled.

        This method evaluates the Defender anti-malware policies to ensure internal sender notifications
        are properly configured.

        Returns:
            List[CheckReportM365]: A list of reports with the results of the check.
        """
        findings = []

        if defender_client.malware_policies:
            # Only Default Defender Malware Policy exists
            if not defender_client.malware_rules:
                policy = defender_client.malware_policies[0]

                report = CheckReportM365(
                    metadata=self.metadata(),
                    resource=policy,
                    resource_name=policy.identity,
                    resource_id=policy.identity,
                )

                if self._are_notifications_enabled(policy):
                    # Case 1: Default policy exists and has notifications enabled
                    report.status = "PASS"
                    report.status_extended = f"{policy.identity} is the only policy and notifications for internal users sending malware are enabled."
                else:
                    # Case 5: Default policy exists but doesn't have notifications enabled
                    report.status = "FAIL"
                    report.status_extended = f"{policy.identity} is the only policy and notifications for internal users sending malware are not enabled."
                findings.append(report)

            # Multiple Defender Malware Policies exist
            else:
                default_policy_well_configured = False

                for policy in defender_client.malware_policies:
                    report = CheckReportM365(
                        metadata=self.metadata(),
                        resource=policy,
                        resource_name=policy.identity,
                        resource_id=policy.identity,
                    )

                    if policy.is_default:
                        if not self._are_notifications_enabled(policy):
                            # Case 4: Default policy not configured
                            report.status = "FAIL"
                            report.status_extended = (
                                f"{policy.identity} 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."
                            )
                            findings.append(report)
                        else:
                            # Case 2: Default policy is properly configured
                            report.status = "PASS"
                            report.status_extended = (
                                f"{policy.identity} is the default policy and notifications for internal users sending malware are enabled, "
                                "but it could be overridden by another misconfigured Custom Policy."
                            )
                            default_policy_well_configured = True
                            findings.append(report)
                    else:
                        if not self._are_notifications_enabled(policy):
                            included_resources = []

                            if defender_client.malware_rules[policy.identity].users:
                                included_resources.append(
                                    f"users: {', '.join(defender_client.malware_rules[policy.identity].users)}"
                                )
                            if defender_client.malware_rules[policy.identity].groups:
                                included_resources.append(
                                    f"groups: {', '.join(defender_client.malware_rules[policy.identity].groups)}"
                                )
                            if defender_client.malware_rules[policy.identity].domains:
                                included_resources.append(
                                    f"domains: {', '.join(defender_client.malware_rules[policy.identity].domains)}"
                                )

                            included_resources_str = "; ".join(included_resources)

                            if default_policy_well_configured:
                                # Case 3: Default policy is configured, custom one isn't
                                report.status = "FAIL"
                                report.status_extended = (
                                    f"Custom Malware policy {policy.identity} is not properly configured and includes {included_resources_str}, "
                                    f"with priority {defender_client.malware_rules[policy.identity].priority} (0 is the highest). "
                                    "However, the default policy is properly configured, so entities not included by this custom policy could be correctly protected."
                                )
                                findings.append(report)
                            else:
                                # Case 5: Neither default nor custom policy is properly configured
                                report.status = "FAIL"
                                report.status_extended = (
                                    f"Custom Malware policy {policy.identity} is not properly configured and includes {included_resources_str}, "
                                    f"with priority {defender_client.malware_rules[policy.identity].priority} (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."
                                )
                                findings.append(report)
                        else:
                            included_resources = []

                            if defender_client.malware_rules[policy.identity].users:
                                included_resources.append(
                                    f"users: {', '.join(defender_client.malware_rules[policy.identity].users)}"
                                )
                            if defender_client.malware_rules[policy.identity].groups:
                                included_resources.append(
                                    f"groups: {', '.join(defender_client.malware_rules[policy.identity].groups)}"
                                )
                            if defender_client.malware_rules[policy.identity].domains:
                                included_resources.append(
                                    f"domains: {', '.join(defender_client.malware_rules[policy.identity].domains)}"
                                )

                            included_resources_str = "; ".join(included_resources)

                            if default_policy_well_configured:
                                # Case 2: Both default and custom policies are properly configured
                                report.status = "PASS"
                                report.status_extended = (
                                    f"Custom Malware policy {policy.identity} is properly configured and includes {included_resources_str}, "
                                    f"with priority {defender_client.malware_rules[policy.identity].priority} (0 is the highest). "
                                    "Also, the default policy is properly configured, so entities not included by this custom policy could still be correctly protected."
                                )
                                findings.append(report)
                            else:
                                # Case 6: Default policy not configured, custom policy is
                                report.status = "PASS"
                                report.status_extended = (
                                    f"Custom Malware policy {policy.identity} is properly configured and includes {included_resources_str}, "
                                    f"with priority {defender_client.malware_rules[policy.identity].priority} (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."
                                )
                                findings.append(report)

        return findings

    def _are_notifications_enabled(self, policy) -> bool:
        if (
            not policy.is_default
            and policy.identity in defender_client.malware_rules
            and defender_client.malware_rules[policy.identity].state.lower()
            != "enabled"
        ):
            return False

        return (
            policy.enable_internal_sender_admin_notifications
            and policy.internal_sender_admin_address
        )
