import pytest_mock
from temporalio.testing import ActivityEnvironment

from csirtmu.beta_temporal.config import Config as WorkerConfig
from csirtmu.beta_temporal.external_services.rt import structs
from csirtmu.beta_temporal.external_services.rt.client import RTClient
from csirtmu.beta_temporal.workflows.handle_prominent_contact import HandleProminentContactActivities


class TestIsProminentContact:
    async def test_is_prominent_contact_interface_none(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        mock_transaction_obj.interface = None
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert not await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)

    async def test_is_prominent_contact_interface_not_email(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        mock_transaction_obj.interface = "Web"
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert not await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)

    async def test_is_prominent_contact_ticket_data_none(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_transaction_obj.interface = "Email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_prominent_contact.RTClient.get_ticket_data"
        )
        get_ticket_data_mock.return_value = None
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert not await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_is_prominent_contact_no_requesters(
        self,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_transaction_obj.interface = "Email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_prominent_contact.RTClient.get_ticket_data"
        )
        get_ticket_data_mock.return_value = mock_ticket_data
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert not await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_is_prominent_contact_random_requestor(
        self,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_transaction_obj.interface = "Email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_prominent_contact.RTClient.get_ticket_data"
        )
        mock_ticket_data.headers.add_header("From", "idk")
        get_ticket_data_mock.return_value = mock_ticket_data
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert not await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_is_prominent_contact_prominent_requestor(
        self,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_transaction_obj.interface = "Email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_prominent_contact.RTClient.get_ticket_data"
        )
        mock_ticket_data.headers.add_header("From", "rektor@muni.cz")
        get_ticket_data_mock.return_value = mock_ticket_data
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_is_prominent_contact_prominent_cc(
        self,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_transaction_obj.interface = "Email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_prominent_contact.RTClient.get_ticket_data"
        )
        mock_ticket_data.headers.add_header("From", "idk")
        mock_ticket_data.headers.add_header("CC", "rektor@muni.cz")
        get_ticket_data_mock.return_value = mock_ticket_data
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_is_prominent_contact_prominent_reply_to(
        self,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_transaction_obj.interface = "Email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_prominent_contact.RTClient.get_ticket_data"
        )
        mock_ticket_data.headers.add_header("From", "idk")
        mock_ticket_data.headers.add_header("Reply-To", "rektor@muni.cz")
        get_ticket_data_mock.return_value = mock_ticket_data
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_is_prominent_contact_substring(
        self,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_transaction_obj.interface = "Email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_prominent_contact.RTClient.get_ticket_data"
        )
        mock_ticket_data.headers.add_header("From", "skas@fi.muni.cz")
        get_ticket_data_mock.return_value = mock_ticket_data
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert not await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_is_prominent_contact_with_name_prefix(
        self,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_transaction_obj.interface = "Email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_prominent_contact.RTClient.get_ticket_data"
        )
        mock_ticket_data.headers.add_header("From", '"Jan Mysliveček" <myslivecek@ics.muni.cz>')
        get_ticket_data_mock.return_value = mock_ticket_data
        activities = HandleProminentContactActivities(RTClient(worker_config.rt))
        assert await test_activity_env.run(activities.is_prominent_contact, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)
