import re

import pytest
import pytest_mock
from temporalio.testing import ActivityEnvironment

from csirtmu.beta_temporal.commons.actions import MattermostActions
from csirtmu.beta_temporal.config import Config as WorkerConfig
from csirtmu.beta_temporal.external_services.mattermost.client import MattermostClient
from csirtmu.beta_temporal.external_services.rt import structs


class TestMattermostCommonActions:
    async def test_notify_mattermost_on_priority_ticket_ticket_obj_is_none(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
    ) -> None:
        mock_transaction_obj.ticket_obj = None
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        assert (
            await test_activity_env.run(activities.notify_mattermost_on_priority_ticket, mock_transaction_obj, "idk")
        ) is None

    async def test_notify_mattermost_on_priority_ticket_create_transaction(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        send_message_mock = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.mattermost_actions.MattermostClient.send_message"
        )
        send_message_mock.return_value = None
        mock_transaction_obj.type = structs.TransactionTypeEnum.CREATE
        mock_transaction_obj.ticket_obj.subject = "test"
        mock_transaction_obj.ticket_obj.id = 1
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        await test_activity_env.run(activities.notify_mattermost_on_priority_ticket, mock_transaction_obj, "idk")
        send_message_mock.assert_called_once_with(
            f"@channel: New priority ticket: {mock_transaction_obj.ticket_obj.subject}, link: "
            f"{worker_config.rt.base_url}Ticket/Display.html?id={mock_transaction_obj.ticket_obj.id}",
            channel="idk",
            username="rt_bot",
            icon_emoji="sauron",
        )

    async def test_notify_mattermost_on_priority_ticket_correspond_transaction(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        send_message_mock = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.mattermost_actions.MattermostClient.send_message"
        )
        send_message_mock.return_value = None
        mock_transaction_obj.type = structs.TransactionTypeEnum.CORRESPOND
        mock_transaction_obj.ticket_obj.subject = "test"
        mock_transaction_obj.ticket_obj.id = 1
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        await test_activity_env.run(activities.notify_mattermost_on_priority_ticket, mock_transaction_obj, "idk")
        send_message_mock.assert_called_once_with(
            f"@channel: Priority ticket update: {mock_transaction_obj.ticket_obj.subject}, link: "
            f"{worker_config.rt.base_url}Ticket/Display.html?id={mock_transaction_obj.ticket_obj.id}",
            channel="idk",
            username="rt_bot",
            icon_emoji="sauron",
        )

    async def test_notify_mattermost_on_analytics_category_ticket_obj_is_none(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
    ) -> None:
        mock_transaction_obj.ticket_obj = None
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        with pytest.raises(ValueError, match=re.escape(f"TicketObj in transaction: {mock_transaction_obj} is None.")):
            await test_activity_env.run(activities.notify_mattermost_on_analytics_category, mock_transaction_obj, "idk")

    async def test_notify_mattermost_on_analytics_category_success(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        send_message_mock = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.mattermost_actions.MattermostClient.send_message"
        )
        send_message_mock.return_value = None
        mock_transaction_obj.ticket_obj.subject = "test"
        mock_transaction_obj.ticket_obj.id = 1
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        await test_activity_env.run(activities.notify_mattermost_on_analytics_category, mock_transaction_obj, "idk")
        send_message_mock.assert_called_once_with(
            f"@all: Ticket for analytics: {mock_transaction_obj.ticket_obj.subject}, link: "
            f"{worker_config.rt.base_url}Ticket/Display.html?id={mock_transaction_obj.ticket_obj.id}",
            channel="idk",
            username="rt_bot",
            icon_emoji="sauron",
        )

    async def test_notify_mattermost_on_certificate_category_ticket_obj_is_none(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
    ) -> None:
        mock_transaction_obj.ticket_obj = None
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        assert (
            await test_activity_env.run(activities.notify_mattermost_on_certificate_ticket, mock_transaction_obj, "idk")
        ) is None

    async def test_notify_mattermost_on_certificate_category_success(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        send_message_mock = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.mattermost_actions.MattermostClient.send_message"
        )
        send_message_mock.return_value = None
        mock_transaction_obj.ticket_obj.subject = "test"
        mock_transaction_obj.ticket_obj.id = 1
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        await test_activity_env.run(activities.notify_mattermost_on_certificate_ticket, mock_transaction_obj, "idk")
        send_message_mock.assert_called_once_with(
            f"@channel: New priority ticket: {mock_transaction_obj.ticket_obj.subject}, link: "
            f"{worker_config.rt.base_url}Ticket/Display.html?id={mock_transaction_obj.ticket_obj.id}",
            channel="idk",
            username="rt_bot",
        )

    async def test_notify_mattermost_on_pentest_ticket_ticket_obj_is_none(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
    ) -> None:
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        mock_transaction_obj.ticket_obj = None
        assert (
            await test_activity_env.run(activities.notify_mattermost_on_pentest_ticket, mock_transaction_obj, "idk")
        ) is None

    async def test_notify_mattermost_on_pentest_ticket_new_ticket(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CREATE
        mock_transaction_obj.ticket_obj.subject = "test"
        send_message_mock = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.mattermost_actions.MattermostClient.send_message",
        )
        send_message_mock.return_value = None
        await test_activity_env.run(activities.notify_mattermost_on_pentest_ticket, mock_transaction_obj, "idk")
        send_message_mock.assert_called_once_with(
            f"New ticket: test, link: "
            f"{worker_config.rt.base_url}Ticket/Display.html?id={mock_transaction_obj.ticket_obj.id}",
            channel="idk",
            username="rt_bot",
            icon_emoji="sauron",
        )

    async def test_notify_mattermost_on_pentest_ticket_new_correspondence(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = MattermostActions(worker_config.rt.base_url, MattermostClient(worker_config.mattermost))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CORRESPOND
        mock_transaction_obj.ticket_obj.subject = "test"
        send_message_mock = mocker.patch(
            "csirtmu.beta_temporal.commons.actions.mattermost_actions.MattermostClient.send_message",
        )
        send_message_mock.return_value = None
        await test_activity_env.run(activities.notify_mattermost_on_pentest_ticket, mock_transaction_obj, "idk")
        send_message_mock.assert_called_once_with(
            f"New correspondence in ticket: test, link: "
            f"{worker_config.rt.base_url}Ticket/Display.html?id={mock_transaction_obj.ticket_obj.id}",
            channel="idk",
            username="rt_bot",
            icon_emoji="sauron",
        )
