import datetime
import unittest.mock
from pyexpat import ExpatError

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.alpha.client import AlphaClient
from csirtmu.beta_temporal.external_services.alpha.structs import AccountingRecord
from csirtmu.beta_temporal.external_services.rt import structs
from csirtmu.beta_temporal.external_services.rt.client import RTClient
from csirtmu.beta_temporal.external_services.rt.utils import create_copyright_notice_ticket
from csirtmu.beta_temporal.workflows.handle_copyright_infringement import CopyrightHandlingActivities


class TestActionsOnCopyrightNotice:
    USER_SEARCH_ERROR: str = "Nepodarilo se dohledat uzivatele, zaviram. Duvod: chyba."
    UNKNOWN_USER: str = "Nenalezen zadny uzivatel, zaviram."
    COPYRIGHT_REPLY: str = """<p>Dear Sir or Madam,<br/>

thank you for reporting the issue. We look forward to solving your problem promptly.
<br/><br/>

Best regards,<br/>
CSIRT-MU, Masaryk University Cybersecurity team<br/>
<a href=https://csirt.muni.cz/?lang=en>https://csirt.muni.cz</a></p>
"""
    COPYRIGHT_TICKET_2_SUBJECT: str = (
        "Porušování autorských práv z účtu {mail} / Copyright infringement from the account {mail}"
    )

    def prepare_all_mocks(self, mocker: pytest_mock.MockerFixture) -> dict[str, pytest_mock.MockType]:
        return {
            "get_ticket_data_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.get_ticket_data",
            ),
            "edit_custom_field_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.edit_custom_field",
            ),
            "create_engine_mock": mocker.patch(
                "csirtmu.beta_temporal.external_services.data_platform.client.create_engine"
            ),
            "translate_ip_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.TrinoClient.get_nat_translation",
            ),
            "comment_ticket_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.comment"
            ),
            "create_ticket_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.create_ticket"
            ),
            "edit_link_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.edit_link"
            ),
            "reply_mock": mocker.patch("csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.reply"),
            "edit_ticket_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.edit_ticket"
            ),
            "get_culprit_by_ip_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.get_culprit_based_on_ip"
            ),
            "translate_dns_mock": mocker.patch(
                "csirtmu.beta_temporal.workflows.handle_copyright_infringement.try_translate_ip_address_to_domain"
            ),
        }

    async def test_actions_on_copyright_notice_ticket_data_none(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.get_ticket_data",
        )
        get_ticket_data_mock.return_value = None

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        get_details_from_xml_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_copyright_infringement.get_details_from_xml"
        )
        await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)
        get_details_from_xml_mock.assert_not_called()

    async def test_actions_on_copyright_notice_ticket_object_none(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.get_ticket_data",
        )
        get_ticket_data_mock.return_value = mock_ticket_data
        mock_transaction_obj.ticket_obj = None
        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        get_details_from_xml_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_copyright_infringement.get_details_from_xml"
        )
        await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)
        get_details_from_xml_mock.assert_not_called()

    async def test_actions_on_copyright_notice_empty_xml_in_body(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_ticket_data.body = "Start ACNS XML\nEnd ACNS XML"
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.get_ticket_data",
        )
        get_ticket_data_mock.return_value = mock_ticket_data

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        with pytest.raises(
            ExpatError,
        ):
            await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

    async def test_actions_on_copyright_notice_empty_attachment_and_xml_in_attachment_content_type(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_ticket_data.attachments[0].content_type = "xml"
        mock_ticket_data.attachments[0].content = ""
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.get_ticket_data",
        )
        get_ticket_data_mock.return_value = mock_ticket_data

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        with pytest.raises(
            ExpatError,
        ):
            await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

    async def test_actions_on_copyright_notice_empty_attachment_and_xml_in_attachment_filename(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
    ) -> None:
        mock_ticket_data.attachments[0].filename = "xml"
        mock_ticket_data.attachments[0].content = ""
        get_ticket_data_mock = mocker.patch(
            "csirtmu.beta_temporal.workflows.handle_copyright_infringement.RTClient.get_ticket_data",
        )
        get_ticket_data_mock.return_value = mock_ticket_data

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        with pytest.raises(
            ExpatError,
        ):
            await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

    async def test_actions_on_copyright_notice_xml_in_body_unable_to_translate_ip(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        xml_body: str,
    ) -> None:
        mock_ticket_data.body = xml_body
        mocks = self.prepare_all_mocks(mocker)
        mocks["get_ticket_data_mock"].return_value = mock_ticket_data
        mocks["create_engine_mock"].return_value = None
        mocks["translate_ip_mock"].return_value = []
        mocks["create_ticket_mock"].return_value = 1

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

        ticket_id = -1 if mock_transaction_obj.ticket_obj is None else mock_transaction_obj.ticket_obj.id
        assert mocks["edit_custom_field_mock"].call_count == 4
        assert mocks["edit_custom_field_mock"].call_args_list[0].args == (
            ticket_id,
            "Category",
            "Automatic - Copyright notice",
        )
        assert mocks["edit_custom_field_mock"].call_args_list[1].args == (ticket_id, "IP", "147.251.163.172")
        assert mocks["edit_custom_field_mock"].call_args_list[2].args == (ticket_id, "Summary", "2020-11-11T12:14:20Z")
        assert mocks["edit_custom_field_mock"].call_args_list[3].args == (ticket_id, "Duplicity", "True")

        time = datetime.datetime.fromisoformat("2020-11-11T12:14:20Z")
        mocks["translate_ip_mock"].assert_called_once_with(
            "147.251.163.172", "54662", time - datetime.timedelta(minutes=2), time + datetime.timedelta(minutes=2)
        )
        mocks["comment_ticket_mock"].assert_called_once_with(
            ticket_id, "Unable to translate public IP: 147.251.163.172", "text/plain"
        )
        mocks["create_ticket_mock"].assert_called_once_with(
            mock_transaction_obj.queue,
            "text/html",
            self.COPYRIGHT_TICKET_2_SUBJECT.format(mail="<email_placeholder>"),
            create_copyright_notice_ticket(
                "<email_placeholder>",
                "<translated_ip_placeholder>",
                "2020-11-11T12:14:20Z",
                "<translated_domain_placeholder>",
                "The Naked Gun: From the Files of Police Squad!",
            ),
            CustomFields={"Category": "Automatic - Copyright notice"},
            Status="act",
        )
        mocks["edit_link_mock"].assert_called_once_with(1, "Parent", ticket_id)
        mocks["reply_mock"].assert_called_once_with(ticket_id, self.COPYRIGHT_REPLY, "text/html")
        mocks["edit_ticket_mock"].assert_called_once_with(ticket_id, Status="Resolved")

    async def test_actions_on_copyright_notice_xml_in_attachment_unable_to_translate_ip(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        xml_attachment: str,
    ) -> None:
        mock_ticket_data.attachments[0].content_type = "xml"
        mock_ticket_data.attachments[0].content = xml_attachment
        mocks = self.prepare_all_mocks(mocker)
        mocks["get_ticket_data_mock"].return_value = mock_ticket_data
        mocks["create_engine_mock"].return_value = None
        mocks["translate_ip_mock"].return_value = []
        mocks["create_ticket_mock"].return_value = 1

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

        ticket_id = -1 if mock_transaction_obj.ticket_obj is None else mock_transaction_obj.ticket_obj.id
        assert mocks["edit_custom_field_mock"].call_count == 4
        assert mocks["edit_custom_field_mock"].call_args_list[0].args == (
            ticket_id,
            "Category",
            "Automatic - Copyright notice",
        )
        assert mocks["edit_custom_field_mock"].call_args_list[1].args == (ticket_id, "IP", "147.251.163.172")
        assert mocks["edit_custom_field_mock"].call_args_list[2].args == (ticket_id, "Summary", "2020-11-11T12:14:20Z")
        assert mocks["edit_custom_field_mock"].call_args_list[3].args == (ticket_id, "Duplicity", "True")

        time = datetime.datetime.fromisoformat("2020-11-11T12:14:20Z")
        mocks["translate_ip_mock"].assert_called_once_with(
            "147.251.163.172", "54662", time - datetime.timedelta(minutes=2), time + datetime.timedelta(minutes=2)
        )
        mocks["comment_ticket_mock"].assert_called_once_with(
            ticket_id, "Unable to translate public IP: 147.251.163.172", "text/plain"
        )
        mocks["create_ticket_mock"].assert_called_once_with(
            mock_transaction_obj.queue,
            "text/html",
            self.COPYRIGHT_TICKET_2_SUBJECT.format(mail="<email_placeholder>"),
            create_copyright_notice_ticket(
                "<email_placeholder>",
                "<translated_ip_placeholder>",
                "2020-11-11T12:14:20Z",
                "<translated_domain_placeholder>",
                "The Naked Gun: From the Files of Police Squad!",
            ),
            CustomFields={"Category": "Automatic - Copyright notice"},
            Status="act",
        )
        mocks["edit_link_mock"].assert_called_once_with(1, "Parent", ticket_id)
        mocks["reply_mock"].assert_called_once_with(ticket_id, self.COPYRIGHT_REPLY, "text/html")
        mocks["edit_ticket_mock"].assert_called_once_with(ticket_id, Status="Resolved")

    async def test_actions_on_copyright_notice_xml_in_attachment_multiple_ips_translated(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        xml_attachment: str,
    ) -> None:
        mock_ticket_data.attachments[0].content_type = "xml"
        mock_ticket_data.attachments[0].content = xml_attachment
        mocks = self.prepare_all_mocks(mocker)
        mocks["get_ticket_data_mock"].return_value = mock_ticket_data
        mocks["create_engine_mock"].return_value = None
        mocks["translate_ip_mock"].return_value = ["10.16.163.172", "10.16.163.180"]
        mocks["create_ticket_mock"].return_value = 1

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

        ticket_id = -1 if mock_transaction_obj.ticket_obj is None else mock_transaction_obj.ticket_obj.id
        assert mocks["edit_custom_field_mock"].call_count == 4
        assert mocks["edit_custom_field_mock"].call_args_list[0].args == (
            ticket_id,
            "Category",
            "Automatic - Copyright notice",
        )
        assert mocks["edit_custom_field_mock"].call_args_list[1].args == (ticket_id, "IP", "147.251.163.172")
        assert mocks["edit_custom_field_mock"].call_args_list[2].args == (ticket_id, "Summary", "2020-11-11T12:14:20Z")
        assert mocks["edit_custom_field_mock"].call_args_list[3].args == (ticket_id, "Duplicity", "True")

        time = datetime.datetime.fromisoformat("2020-11-11T12:14:20Z")
        mocks["translate_ip_mock"].assert_called_once_with(
            "147.251.163.172", "54662", time - datetime.timedelta(minutes=2), time + datetime.timedelta(minutes=2)
        )
        mocks["comment_ticket_mock"].assert_called_once_with(
            ticket_id,
            "Public IP: 147.251.163.172 translated to multiple addresses: ['10.16.163.172', '10.16.163.180']",
            "text/plain",
        )
        mocks["create_ticket_mock"].assert_called_once_with(
            mock_transaction_obj.queue,
            "text/html",
            self.COPYRIGHT_TICKET_2_SUBJECT.format(mail="<email_placeholder>"),
            create_copyright_notice_ticket(
                "<email_placeholder>",
                "<translated_ip_placeholder>",
                "2020-11-11T12:14:20Z",
                "<translated_domain_placeholder>",
                "The Naked Gun: From the Files of Police Squad!",
            ),
            CustomFields={"Category": "Automatic - Copyright notice"},
            Status="act",
        )
        mocks["edit_link_mock"].assert_called_once_with(1, "Parent", ticket_id)
        mocks["reply_mock"].assert_called_once_with(ticket_id, self.COPYRIGHT_REPLY, "text/html")
        mocks["edit_ticket_mock"].assert_called_once_with(ticket_id, Status="Resolved")

    async def test_actions_on_copyright_notice_xml_in_attachment_one_ip_translated_user_not_found(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        xml_attachment: str,
    ) -> None:
        mock_ticket_data.attachments[0].content_type = "xml"
        mock_ticket_data.attachments[0].content = xml_attachment
        mocks = self.prepare_all_mocks(mocker)
        mocks["get_ticket_data_mock"].return_value = mock_ticket_data
        mocks["create_engine_mock"].return_value = None
        mocks["translate_ip_mock"].return_value = ["10.16.163.172"]
        mocks["create_ticket_mock"].return_value = 1
        mocks["get_culprit_by_ip_mock"].return_value = None

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

        ticket_id = -1 if mock_transaction_obj.ticket_obj is None else mock_transaction_obj.ticket_obj.id
        assert mocks["edit_custom_field_mock"].call_count == 4
        assert mocks["edit_custom_field_mock"].call_args_list[0].args == (
            ticket_id,
            "Category",
            "Automatic - Copyright notice",
        )
        assert mocks["edit_custom_field_mock"].call_args_list[1].args == (ticket_id, "IP", "147.251.163.172")
        assert mocks["edit_custom_field_mock"].call_args_list[2].args == (ticket_id, "Summary", "2020-11-11T12:14:20Z")
        assert mocks["edit_custom_field_mock"].call_args_list[3].args == (ticket_id, "Duplicity", "True")

        time = datetime.datetime.fromisoformat("2020-11-11T12:14:20Z")
        mocks["translate_ip_mock"].assert_called_once_with(
            "147.251.163.172", "54662", time - datetime.timedelta(minutes=2), time + datetime.timedelta(minutes=2)
        )
        mocks["get_culprit_by_ip_mock"].assert_called_once_with(
            "10.16.163.172",
            "2020-11-11T12:14:20Z",
            unittest.mock.ANY,
        )
        assert mocks["comment_ticket_mock"].call_count == 2
        assert mocks["comment_ticket_mock"].call_args_list[0].args == (
            ticket_id,
            "Public IP: 147.251.163.172 translated to address: 10.16.163.172",
            "text/plain",
        )
        assert mocks["comment_ticket_mock"].call_args_list[1].args == (ticket_id, self.UNKNOWN_USER, "text/plain")
        mocks["create_ticket_mock"].assert_called_once_with(
            mock_transaction_obj.queue,
            "text/html",
            self.COPYRIGHT_TICKET_2_SUBJECT.format(mail="<email_placeholder>"),
            create_copyright_notice_ticket(
                "<email_placeholder>",
                "10.16.163.172",
                "2020-11-11T12:14:20Z",
                "<translated_domain_placeholder>",
                "The Naked Gun: From the Files of Police Squad!",
            ),
            CustomFields={"Category": "Automatic - Copyright notice"},
            Status="act",
        )
        mocks["edit_link_mock"].assert_called_once_with(1, "Parent", ticket_id)
        mocks["reply_mock"].assert_called_once_with(ticket_id, self.COPYRIGHT_REPLY, "text/html")
        mocks["edit_ticket_mock"].assert_called_once_with(ticket_id, Status="Resolved")

    async def test_actions_on_copyright_notice_xml_in_attachment_one_ip_translated_uco_user_found(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        xml_attachment: str,
        uco_culprit: AccountingRecord,
    ) -> None:
        mock_ticket_data.attachments[0].content_type = "xml"
        mock_ticket_data.attachments[0].content = xml_attachment
        mocks = self.prepare_all_mocks(mocker)
        mocks["get_ticket_data_mock"].return_value = mock_ticket_data
        mocks["create_engine_mock"].return_value = None
        mocks["translate_ip_mock"].return_value = ["10.16.163.172"]
        mocks["create_ticket_mock"].return_value = 1
        mocks["get_culprit_by_ip_mock"].return_value = uco_culprit
        mocks["translate_dns_mock"].return_value = None

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

        ticket_id = -1 if mock_transaction_obj.ticket_obj is None else mock_transaction_obj.ticket_obj.id
        assert mocks["edit_custom_field_mock"].call_count == 5
        assert mocks["edit_custom_field_mock"].call_args_list[0].args == (
            ticket_id,
            "Category",
            "Automatic - Copyright notice",
        )
        assert mocks["edit_custom_field_mock"].call_args_list[1].args == (ticket_id, "IP", "147.251.163.172")
        assert mocks["edit_custom_field_mock"].call_args_list[2].args == (ticket_id, "Summary", "2020-11-11T12:14:20Z")
        assert mocks["edit_custom_field_mock"].call_args_list[3].args == (ticket_id, "UCO", "123456")
        assert mocks["edit_custom_field_mock"].call_args_list[4].args == (ticket_id, "Duplicity", "True")

        time = datetime.datetime.fromisoformat("2020-11-11T12:14:20Z")
        mocks["translate_ip_mock"].assert_called_once_with(
            "147.251.163.172", "54662", time - datetime.timedelta(minutes=2), time + datetime.timedelta(minutes=2)
        )
        mocks["get_culprit_by_ip_mock"].assert_called_once_with(
            "10.16.163.172",
            "2020-11-11T12:14:20Z",
            unittest.mock.ANY,
        )
        mocks["comment_ticket_mock"].assert_called_once_with(
            ticket_id, "Public IP: 147.251.163.172 translated to address: 10.16.163.172", "text/plain"
        )
        mocks["create_ticket_mock"].assert_called_once_with(
            mock_transaction_obj.queue,
            "text/html",
            self.COPYRIGHT_TICKET_2_SUBJECT.format(mail="123456@mail.muni.cz"),
            create_copyright_notice_ticket(
                "123456@mail.muni.cz",
                "10.16.163.172",
                "2020-11-11T12:14:20Z",
                "---",
                "The Naked Gun: From the Files of Police Squad!",
            ),
            CustomFields={"Category": "Automatic - Copyright notice", "UCO": "123456"},
            Status="Resolved",
            Requestor=["123456@mail.muni.cz"],
        )
        mocks["edit_link_mock"].assert_called_once_with(1, "Parent", ticket_id)
        mocks["reply_mock"].assert_called_once_with(ticket_id, self.COPYRIGHT_REPLY, "text/html")
        mocks["edit_ticket_mock"].assert_called_once_with(ticket_id, Status="Resolved")

    async def test_actions_on_copyright_notice_xml_in_attachment_one_ip_translated_mail_user_found(
        self,
        worker_config: WorkerConfig,
        test_activity_env: ActivityEnvironment,
        mock_ticket_data: structs.TicketData,
        mock_transaction_obj: structs.TransactionStruct,
        mocker: pytest_mock.MockerFixture,
        xml_attachment: str,
        mail_culprit: AccountingRecord,
    ) -> None:
        mock_ticket_data.attachments[0].content_type = "xml"
        mock_ticket_data.attachments[0].content = xml_attachment
        mocks = self.prepare_all_mocks(mocker)
        mocks["get_ticket_data_mock"].return_value = mock_ticket_data
        mocks["create_engine_mock"].return_value = None
        mocks["translate_ip_mock"].return_value = ["10.16.163.172"]
        mocks["create_ticket_mock"].return_value = 1
        mocks["get_culprit_by_ip_mock"].return_value = mail_culprit
        mocks["translate_dns_mock"].return_value = None

        activities = CopyrightHandlingActivities("", RTClient(worker_config.rt), AlphaClient(worker_config.alpha))
        await test_activity_env.run(activities.actions_on_copyright_notice, mock_transaction_obj)

        ticket_id = -1 if mock_transaction_obj.ticket_obj is None else mock_transaction_obj.ticket_obj.id
        assert mocks["edit_custom_field_mock"].call_count == 5
        assert mocks["edit_custom_field_mock"].call_args_list[0].args == (
            ticket_id,
            "Category",
            "Automatic - Copyright notice",
        )
        assert mocks["edit_custom_field_mock"].call_args_list[1].args == (ticket_id, "IP", "147.251.163.172")
        assert mocks["edit_custom_field_mock"].call_args_list[2].args == (ticket_id, "Summary", "2020-11-11T12:14:20Z")
        assert mocks["edit_custom_field_mock"].call_args_list[3].args == (ticket_id, "UCO", "mail@test.com")
        assert mocks["edit_custom_field_mock"].call_args_list[4].args == (ticket_id, "Duplicity", "True")

        time = datetime.datetime.fromisoformat("2020-11-11T12:14:20Z")
        mocks["translate_ip_mock"].assert_called_once_with(
            "147.251.163.172", "54662", time - datetime.timedelta(minutes=2), time + datetime.timedelta(minutes=2)
        )
        mocks["get_culprit_by_ip_mock"].assert_called_once_with(
            "10.16.163.172",
            "2020-11-11T12:14:20Z",
            unittest.mock.ANY,
        )
        mocks["comment_ticket_mock"].assert_called_once_with(
            ticket_id, "Public IP: 147.251.163.172 translated to address: 10.16.163.172", "text/plain"
        )
        mocks["create_ticket_mock"].assert_called_once_with(
            mock_transaction_obj.queue,
            "text/html",
            self.COPYRIGHT_TICKET_2_SUBJECT.format(mail="mail@test.com"),
            create_copyright_notice_ticket(
                "mail@test.com",
                "10.16.163.172",
                "2020-11-11T12:14:20Z",
                "---",
                "The Naked Gun: From the Files of Police Squad!",
            ),
            CustomFields={"Category": "Automatic - Copyright notice", "UCO": "mail@test.com"},
            Status="Resolved",
            Requestor=["mail@test.com"],
        )
        mocks["edit_link_mock"].assert_called_once_with(1, "Parent", ticket_id)
        mocks["reply_mock"].assert_called_once_with(ticket_id, self.COPYRIGHT_REPLY, "text/html")
        mocks["edit_ticket_mock"].assert_called_once_with(ticket_id, Status="Resolved")
