import re

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_category_for_tool_report import SetCategoryForToolReportActivities


class TestSetCategory:
    async def test_set_category_ticket_data_is_none(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockFixture,
    ) -> None:
        activities = SetCategoryForToolReportActivities(RTClient(worker_config.rt))
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.get_ticket_data",
        )
        get_ticket_data_mock.return_value = None
        assert (await test_activity_env.run(activities.set_category, mock_transaction_obj)) is None
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_set_category_no_categories(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        mock_ticket_data: structs.TicketData,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockFixture,
    ) -> None:
        activities = SetCategoryForToolReportActivities(RTClient(worker_config.rt))
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.get_ticket_data",
        )
        get_ticket_data_mock.return_value = mock_ticket_data
        assert (await test_activity_env.run(activities.set_category, mock_transaction_obj)) is None
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_set_category_exiting_category(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        mock_ticket_data: structs.TicketData,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetCategoryForToolReportActivities(RTClient(worker_config.rt))
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.get_ticket_data",
        )
        mock_transaction_obj.ticket_obj.custom_fields = [
            structs.CustomFieldStruct(id="", type="", url="", name="Category", _values=["Random"]),
        ]
        mock_ticket_data.transaction = mock_transaction_obj
        get_ticket_data_mock.return_value = mock_ticket_data
        assert (await test_activity_env.run(activities.set_category, mock_transaction_obj)) is None
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)

    async def test_set_category_testing_ticket_exiting_category(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        mock_ticket_data: structs.TicketData,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetCategoryForToolReportActivities(RTClient(worker_config.rt))
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.get_ticket_data",
        )
        edit_custom_field_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.edit_custom_field",
        )
        mock_transaction_obj.ticket_obj.custom_fields = [
            structs.CustomFieldStruct(id="", type="", url="", name="Category", _values=["Testing ticket"]),
        ]
        mock_ticket_data.transaction = mock_transaction_obj
        get_ticket_data_mock.return_value = mock_ticket_data
        edit_custom_field_mock.return_value = None
        assert (await test_activity_env.run(activities.set_category, mock_transaction_obj)) is None
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)
        edit_custom_field_mock.assert_called_once_with(mock_transaction_obj.ticket_obj.id, "Category", "Testing ticket")

    async def test_set_category_ticket_obj_is_none(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        mock_ticket_data: structs.TicketData,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockFixture,
    ) -> None:
        activities = SetCategoryForToolReportActivities(RTClient(worker_config.rt))
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.get_ticket_data",
        )
        mock_transaction_obj.ticket_obj = None
        mock_ticket_data.transaction = mock_transaction_obj
        mock_ticket_data.headers.add_header("X-RT-Category", "Test")
        get_ticket_data_mock.return_value = mock_ticket_data
        with pytest.raises(ValueError, match=re.escape("Ticket object is None.")):
            await test_activity_env.run(activities.set_category, mock_transaction_obj)

    async def test_set_category_no_subcategory(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        mock_ticket_data: structs.TicketData,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetCategoryForToolReportActivities(RTClient(worker_config.rt))
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.get_ticket_data",
        )
        edit_custom_field_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.edit_custom_field",
        )
        mock_ticket_data.headers.add_header("X-RT-Category", "Test")
        mock_ticket_data.transaction = mock_transaction_obj
        get_ticket_data_mock.return_value = mock_ticket_data
        edit_custom_field_mock.return_value = None
        assert (await test_activity_env.run(activities.set_category, mock_transaction_obj)) is None
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)
        edit_custom_field_mock.assert_called_once_with(mock_transaction_obj.ticket_obj.id, "Category", "Test")

    async def test_set_category_with_subcategory(
        self,
        worker_config: WorkerConfig,
        mock_transaction_obj: structs.TransactionStruct,
        mock_ticket_data: structs.TicketData,
        test_activity_env: ActivityEnvironment,
        mocker: pytest_mock.MockFixture,
    ) -> None:
        assert mock_transaction_obj.ticket_obj is not None
        activities = SetCategoryForToolReportActivities(RTClient(worker_config.rt))
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.get_ticket_data",
        )
        edit_custom_field_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.set_category_for_tool_report.RTClient.edit_custom_field",
        )
        mock_ticket_data.headers.add_header("X-RT-Category", "Test")
        mock_ticket_data.headers.add_header("X-RT-Subcategory", "Test_subcategory")
        mock_ticket_data.transaction = mock_transaction_obj
        get_ticket_data_mock.return_value = mock_ticket_data
        edit_custom_field_mock.return_value = None
        assert (await test_activity_env.run(activities.set_category, mock_transaction_obj)) is None
        get_ticket_data_mock.assert_called_once_with(mock_transaction_obj)
        assert edit_custom_field_mock.call_args_list[0][0] == (mock_transaction_obj.ticket_obj.id, "Category", "Test")
        assert edit_custom_field_mock.call_args_list[1][0] == (
            mock_transaction_obj.ticket_obj.id,
            "Subcategory",
            "Test_subcategory",
        )
