import pytest
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.set_status_act_on_automatic_correspond import (
    SetStatusActOnAutomaticCorrespondActivities,
)


class TestIsAutomaticCorrespond:
    async def test_is_automatic_correspond_transaction_type_not_correspond(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        activities = SetStatusActOnAutomaticCorrespondActivities(RTClient(worker_config.rt))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CREATE
        assert not await test_activity_env.run(activities.is_automatic_correspond, mock_transaction_obj)

    async def test_is_automatic_correspond_ticket_obj_is_none(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        activities = SetStatusActOnAutomaticCorrespondActivities(RTClient(worker_config.rt))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CORRESPOND
        mock_transaction_obj.ticket_obj = None
        assert not await test_activity_env.run(activities.is_automatic_correspond, mock_transaction_obj)

    async def test_is_automatic_correspond_ticket_status_is_invalid(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetStatusActOnAutomaticCorrespondActivities(RTClient(worker_config.rt))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CORRESPOND
        mock_transaction_obj.ticket_obj.status = "act"
        assert not await test_activity_env.run(activities.is_automatic_correspond, mock_transaction_obj)

    @pytest.mark.parametrize("status", ["resolved", "closed", "wait"])
    async def test_is_automatic_correspond_is_from_web(
        self,
        status: str,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetStatusActOnAutomaticCorrespondActivities(RTClient(worker_config.rt))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CORRESPOND
        mock_transaction_obj.ticket_obj.status = status
        mock_transaction_obj.interface = "web"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_status_act_on_automatic_correspond.RTClient.get_ticket_data",
        )
        assert not await test_activity_env.run(activities.is_automatic_correspond, mock_transaction_obj)
        get_ticket_data_mock.assert_not_called()

    @pytest.mark.parametrize("status", ["resolved", "closed", "wait"])
    async def test_is_automatic_correspond_ticket_data_is_none(
        self,
        status: str,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetStatusActOnAutomaticCorrespondActivities(RTClient(worker_config.rt))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CORRESPOND
        mock_transaction_obj.ticket_obj.status = status
        mock_transaction_obj.interface = "email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_status_act_on_automatic_correspond.RTClient.get_ticket_data",
        )
        get_ticket_data_mock.return_value = None
        assert not await test_activity_env.run(activities.is_automatic_correspond, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    @pytest.mark.parametrize("status", ["resolved", "closed", "wait"])
    async def test_is_automatic_correspond_from_tool_gateway(
        self,
        status: str,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetStatusActOnAutomaticCorrespondActivities(RTClient(worker_config.rt))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CORRESPOND
        mock_transaction_obj.ticket_obj.status = status
        mock_transaction_obj.interface = "email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_status_act_on_automatic_correspond.RTClient.get_ticket_data",
        )
        mock_ticket_data.headers.add_header("From", "ToolGateway")
        get_ticket_data_mock.return_value = mock_ticket_data
        assert await test_activity_env.run(activities.is_automatic_correspond, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    @pytest.mark.parametrize("status", ["resolved", "closed", "wait"])
    @pytest.mark.parametrize("sender", SetStatusActOnAutomaticCorrespondActivities.EXCEPTIONS.keys())
    async def test_is_automatic_correspond_is_exception(
        self,
        status: str,
        sender: str,
        worker_config: WorkerConfig,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        test_activity_env: ActivityEnvironment,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetStatusActOnAutomaticCorrespondActivities(RTClient(worker_config.rt))
        mock_transaction_obj.type = structs.TransactionTypeEnum.CORRESPOND
        mock_transaction_obj.ticket_obj.status = status
        mock_transaction_obj.interface = "email"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_status_act_on_automatic_correspond.RTClient.get_ticket_data",
        )
        mock_ticket_data.headers.add_header("From", sender)
        mock_ticket_data.body = (
            SetStatusActOnAutomaticCorrespondActivities.EXCEPTIONS[sender][0]
            .replace("\\s", "")
            .replace("*", "")
            .replace("^", "")
            .replace("?", "")
            .replace("(", "")
            .replace(")", "")
        )
        get_ticket_data_mock.return_value = mock_ticket_data
        assert not await test_activity_env.run(activities.is_automatic_correspond, mock_transaction_obj)
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)
