import ipaddress

import pytest_mock
from temporalio.testing import ActivityEnvironment

from csirtmu.beta_temporal.commons.actions.alpha_common_actions import AlphaCommonActions
from csirtmu.beta_temporal.config import Config as WorkerConfig
from csirtmu.beta_temporal.external_services.alpha.client import AlphaClient
from csirtmu.beta_temporal.external_services.alpha.structs import CIDR, NetboxAsset, Tenant


class TestGetNetboxNetworkInfo:
    async def test_get_empty_ips(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        assert (await test_activity_env.run(activities.get_netbox_network_info, [])) == {}

    async def test_get_empty_ips_no_netbox_data(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = None
        assert (await test_activity_env.run(activities.get_netbox_network_info, [])) == {}

    async def test_get_no_netbox_data(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = None
        assert (await test_activity_env.run(activities.get_netbox_network_info, ["1.1.1.1"])) == {
            "Departments": ["Unknown"],
            "Networks": ["Outside / Unknown"],
            "IP Mapping": ["IP: 1.1.1.1,\tNetwork: Outside / Unknown,\tDepartment: Unknown"],
        }
        netbox_data_patch.assert_called_once_with(["1.1.1.1"])

    async def test_get_no_subnet_info(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = {"1.1.1.1": "Test"}
        subnet_info_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.get_subnet_info_for_ip"
        )
        subnet_info_patch.return_value = None
        assert (await test_activity_env.run(activities.get_netbox_network_info, ["1.1.1.1"])) == {
            "Departments": ["Unknown"],
            "Networks": ["Outside / Unknown"],
            "IP Mapping": ["IP: 1.1.1.1,\tNetwork: Outside / Unknown,\tDepartment: Unknown"],
        }
        netbox_data_patch.assert_called_once_with(["1.1.1.1"])
        subnet_info_patch.assert_called_once_with("1.1.1.1", "Test")

    async def test_get_no_tenant(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = {"1.1.1.1": "Test"}
        subnet_info_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.get_subnet_info_for_ip"
        )
        subnet_info_patch.return_value = NetboxAsset(
            tenant=[], cidr=CIDR(_raw_exploded="1.1.1.1", exploded=ipaddress.ip_network("1.1.1.1/32")), description=""
        )
        assert (await test_activity_env.run(activities.get_netbox_network_info, ["1.1.1.1"])) == {
            "Departments": ["---"],
            "Networks": ["University"],
            "IP Mapping": ["IP: 1.1.1.1,\tNetwork: University,\tDepartment: ---"],
        }
        netbox_data_patch.assert_called_once_with(["1.1.1.1"])
        subnet_info_patch.assert_called_once_with("1.1.1.1", "Test")

    async def test_get_no_tenant_vpn_description(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = {"1.1.1.1": "Test"}
        subnet_info_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.get_subnet_info_for_ip"
        )
        subnet_info_patch.return_value = NetboxAsset(
            tenant=[],
            cidr=CIDR(_raw_exploded="1.1.1.1", exploded=ipaddress.ip_network("1.1.1.1/32")),
            description="vpn",
        )
        assert (await test_activity_env.run(activities.get_netbox_network_info, ["1.1.1.1"])) == {
            "Departments": ["---"],
            "Networks": ["vpn"],
            "IP Mapping": ["IP: 1.1.1.1,\tNetwork: vpn,\tDepartment: ---"],
        }
        netbox_data_patch.assert_called_once_with(["1.1.1.1"])
        subnet_info_patch.assert_called_once_with("1.1.1.1", "Test")

    async def test_get_no_tenant_eduroam_description(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = {"1.1.1.1": "Test"}
        subnet_info_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.get_subnet_info_for_ip"
        )
        subnet_info_patch.return_value = NetboxAsset(
            tenant=[],
            cidr=CIDR(_raw_exploded="1.1.1.1", exploded=ipaddress.ip_network("1.1.1.1/32")),
            description="eduroam",
        )
        assert (await test_activity_env.run(activities.get_netbox_network_info, ["1.1.1.1"])) == {
            "Departments": ["---"],
            "Networks": ["eduroam"],
            "IP Mapping": ["IP: 1.1.1.1,\tNetwork: eduroam,\tDepartment: ---"],
        }
        netbox_data_patch.assert_called_once_with(["1.1.1.1"])
        subnet_info_patch.assert_called_once_with("1.1.1.1", "Test")

    async def test_get_vpn_tenant(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = {"1.1.1.1": "Test"}
        subnet_info_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.get_subnet_info_for_ip"
        )
        subnet_info_patch.return_value = NetboxAsset(
            tenant=[Tenant("VPN")],
            cidr=CIDR(_raw_exploded="1.1.1.1", exploded=ipaddress.ip_network("1.1.1.1/32")),
            description="",
        )
        assert (await test_activity_env.run(activities.get_netbox_network_info, ["1.1.1.1"])) == {
            "Departments": ["VPN"],
            "Networks": ["vpn"],
            "IP Mapping": ["IP: 1.1.1.1,\tNetwork: vpn,\tDepartment: VPN"],
        }
        netbox_data_patch.assert_called_once_with(["1.1.1.1"])
        subnet_info_patch.assert_called_once_with("1.1.1.1", "Test")

    async def test_get_eduroam_tenant(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = {"1.1.1.1": "Test"}
        subnet_info_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.get_subnet_info_for_ip"
        )
        subnet_info_patch.return_value = NetboxAsset(
            tenant=[Tenant("Eduroam")],
            cidr=CIDR(_raw_exploded="1.1.1.1", exploded=ipaddress.ip_network("1.1.1.1/32")),
            description="",
        )
        assert (await test_activity_env.run(activities.get_netbox_network_info, ["1.1.1.1"])) == {
            "Departments": ["Eduroam"],
            "Networks": ["eduroam"],
            "IP Mapping": ["IP: 1.1.1.1,\tNetwork: eduroam,\tDepartment: Eduroam"],
        }
        netbox_data_patch.assert_called_once_with(["1.1.1.1"])
        subnet_info_patch.assert_called_once_with("1.1.1.1", "Test")

    async def test_get_random_tenant(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        activities = AlphaCommonActions(AlphaClient(worker_config.alpha))
        netbox_data_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.AlphaClient.get_ip_address_data"
        )
        netbox_data_patch.return_value = {"1.1.1.1": "Test"}
        subnet_info_patch = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.alpha_common_actions.get_subnet_info_for_ip"
        )
        subnet_info_patch.return_value = NetboxAsset(
            tenant=[Tenant("Random")],
            cidr=CIDR(_raw_exploded="1.1.1.1", exploded=ipaddress.ip_network("1.1.1.1/32")),
            description="",
        )
        assert (await test_activity_env.run(activities.get_netbox_network_info, ["1.1.1.1"])) == {
            "Departments": ["Random"],
            "Networks": ["University"],
            "IP Mapping": ["IP: 1.1.1.1,\tNetwork: University,\tDepartment: Random"],
        }
        netbox_data_patch.assert_called_once_with(["1.1.1.1"])
        subnet_info_patch.assert_called_once_with("1.1.1.1", "Test")
