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

from temporalio import activity

from csirtmu.beta_temporal.external_services.rt.client import RTClient
from csirtmu.beta_temporal.external_services.rt.structs import TransactionStruct, TransactionTypeEnum
from csirtmu.beta_temporal.workflows.logging import LoggedActivities


class CommonConditions(LoggedActivities):
    def __init__(self, rt_client: RTClient) -> None:
        self.rt_client = rt_client

    def get_activities(self) -> Sequence[Callable[..., Any]]:
        return [
            self.has_keyword_in_subject,
            self.is_from_interface,
            self.is_tool_report,
            self.custom_field_value_set,
            self.custom_field_changed_or_set,
            self.is_certificate_notification,
            self.is_status_change,
        ]

    @activity.defn
    async def has_keyword_in_subject(self, keyword: str, transaction: TransactionStruct) -> bool:
        self.log_activity()
        return transaction.ticket_obj is not None and keyword in transaction.ticket_obj.subject

    @activity.defn
    async def is_from_interface(self, interface: str, transaction: TransactionStruct) -> bool:
        self.log_activity()
        return transaction.interface is not None and transaction.interface.lower() == interface.lower()

    @activity.defn
    async def custom_field_value_set(self, name: str, value: str, transaction: TransactionStruct) -> bool:
        self.log_activity()
        return transaction.ticket_obj is not None and any(
            custom_field.name == name and value in custom_field.values
            for custom_field in transaction.ticket_obj.custom_fields
        )

    @activity.defn
    async def custom_field_changed_or_set(self, name: str, transaction: TransactionStruct) -> bool:
        self.log_activity()
        if transaction.ticket_obj is None:
            return False
        if transaction.type == TransactionTypeEnum.CUSTOM_FIELD:
            for cf in transaction.ticket_obj.custom_fields:
                if transaction.new_value in cf.values or cf.values == []:
                    return cf.name == name
            return False
        return any(cf.name == name and cf.values != [] for cf in transaction.ticket_obj.custom_fields)

    @activity.defn
    async def is_tool_report(self, transaction: TransactionStruct) -> bool:
        self.log_activity()
        if (ticket_data := self.rt_client.get_ticket_data(transaction)) is None or len(ticket_data.attachments) == 0:
            return False
        return ticket_data.headers.get("X-RT-Tool-Name") is not None

    @activity.defn
    async def is_certificate_notification(self, transaction: TransactionStruct) -> bool:
        self.log_activity()
        return (
            transaction.interface == "Email"
            and (ticket_data := self.rt_client.get_ticket_data(transaction)) is not None
            and bool(re.search(r"ca@cesnet\.cz|tcs-ra@cesnet\.cz", ticket_data.headers.get("From", "")))
        )

    @activity.defn
    async def is_status_change(self, status: str, transaction: TransactionStruct) -> bool:
        self.log_activity()
        if transaction.ticket_obj is None:
            return False
        return (
            transaction.type == TransactionTypeEnum.STATUS and transaction.new_value == status
        ) or transaction.ticket_obj.status == status
