import re
from collections.abc import Awaitable, Callable, Sequence
from typing import Any

from temporalio import activity, workflow

from csirtmu.beta_temporal.commons.actions.temporal_common_actions import TemporalCommonActions
from csirtmu.beta_temporal.config import AppConfig
from csirtmu.beta_temporal.constants import WorkflowReference
from csirtmu.beta_temporal.external_services.mattermost.client import MattermostClient
from csirtmu.beta_temporal.external_services.rt import structs
from csirtmu.beta_temporal.external_services.rt.client import RTClient
from csirtmu.beta_temporal.workflows.logging import LoggedActivities, LoggedWorkflow


class MattermostNotificationOnCSIRTWebFormActivities(LoggedActivities):
    def __init__(self, rt_client: RTClient, rt_host: str, mattermost_client: MattermostClient) -> None:
        self.rt_client = rt_client
        self.rt_host = rt_host
        self.mattermost_client = mattermost_client

    def get_activities(self) -> Sequence[Callable[..., Any]]:
        return [self.is_message_from_csirt_web_form, self.send_mattermost_notification]

    @activity.defn
    async def is_message_from_csirt_web_form(self, transaction: structs.TransactionStruct) -> bool:
        self.log_activity()
        return (ticket_data := self.rt_client.get_ticket_data(transaction)) is not None and bool(
            re.search(r"Zprava z formulare webu csirt.muni.cz", ticket_data.attachments[0].subject, re.IGNORECASE)
        )

    @activity.defn
    async def send_mattermost_notification(self, transaction: structs.TransactionStruct, channel: str) -> None:
        self.log_activity()
        if transaction.ticket_obj is None or (ticket_data := self.rt_client.get_ticket_data(transaction)) is None:
            return
        content = ""
        for line in ticket_data.body.split("\n"):
            if not re.search(r"Na zpr.vu m..ete p..mo odpov.d.t", line, re.IGNORECASE):
                content += f"> {line}\n"
        text = f"New ticket in Info: {transaction.ticket_obj.subject}, link: {self.rt_host}Ticket/Display.html?id={transaction.ticket_obj.id}\n{content}"
        self.mattermost_client.send_message(text, channel=channel, username="rt_bot", icon_emoji="sauron")


class MattermostNotificationOnCSIRTWebForm(
    LoggedWorkflow, workflow_name=WorkflowReference.MATTERMOST_NOTIFICATION_ON_CSIRT_WEB_FORM
):
    @classmethod
    def get_activities(cls) -> Sequence[Callable[..., Awaitable[Any]]]:
        config = AppConfig.get()
        local_activities = MattermostNotificationOnCSIRTWebFormActivities(
            RTClient(config.rt), config.rt.base_url, MattermostClient(config.mattermost)
        )
        temporal = TemporalCommonActions(config.temporal)
        return [*local_activities.get_activities(), *temporal.get_activities()]

    @workflow.run
    async def run(self, transaction: structs.TransactionStruct, params: dict[str, str]) -> None:
        self.log_workflow()
        if not (channel := params.get("mm_channel")):
            raise ValueError("No channel given!")
        config = AppConfig.get()
        if await workflow.execute_activity(
            MattermostNotificationOnCSIRTWebFormActivities.is_message_from_csirt_web_form,
            args=(transaction,),
            retry_policy=config.temporal.retry_policy,
            start_to_close_timeout=config.temporal.activity_timeout,
        ):
            await workflow.execute_activity(
                MattermostNotificationOnCSIRTWebFormActivities.send_mattermost_notification,
                args=(transaction, channel),
                retry_policy=config.temporal.retry_policy,
                start_to_close_timeout=config.temporal.activity_timeout,
            )
        elif config.temporal.allow_internal_cancels:
            await workflow.execute_activity(
                TemporalCommonActions.cancel_workflow,
                args=(workflow.info().workflow_id, workflow.info().task_queue),
                retry_policy=config.temporal.retry_policy,
                start_to_close_timeout=config.temporal.activity_timeout,
            )
