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

from temporalio import activity

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.structs import TransactionStruct
from csirtmu.beta_temporal.workflows.logging import LoggedActivities


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

    def get_activities(self) -> Sequence[Callable[..., Any]]:
        return [
            self.set_custom_field,
            self.set_ticket_priority,
            self.set_ticket_status,
            self.close_ticket,
            self.set_ip_related_custom_fields,
        ]

    @activity.defn
    async def set_custom_field(self, name: str, value: str, transaction: TransactionStruct) -> None:
        self.log_activity()
        if transaction.ticket_obj is None:
            raise ValueError(f"TicketObj in transaction: {transaction} is None.")
        self.rt_client.edit_custom_field(transaction.ticket_obj.id, name, value)

    @activity.defn
    async def set_ticket_status(
        self, status: str, transaction: TransactionStruct, verify_status_integrity: bool = False
    ) -> None:
        self.log_activity()
        if transaction.ticket_obj:
            if verify_status_integrity:
                ticket = self.rt_client.get_ticket(transaction.ticket_obj.id)
                if ticket.status.lower() != transaction.ticket_obj.status.lower():
                    return
            self.rt_client.edit_ticket(transaction.ticket_obj.id, Status=status)

    @activity.defn
    async def set_ticket_priority(self, priority: int, transaction: TransactionStruct) -> None:
        self.log_activity()
        if transaction.ticket_obj is None:
            raise ValueError(f"TicketObj in transaction: {transaction} is None.")
        self.rt_client.edit_ticket(transaction.ticket_obj.id, Priority=priority)

    @activity.defn
    async def close_ticket(self, ticket_id: int | str) -> None:
        self.log_activity()
        self.rt_client.edit_ticket(ticket_id, Status="Resolved")

    def filter_changed_cf_values(
        self, transaction: structs.TransactionStruct, custom_fields: dict[str, list[str]]
    ) -> dict[str, list[str]]:
        if transaction.ticket_obj is None:
            raise RuntimeError("No ticket object found!")
        for cf in transaction.ticket_obj.custom_fields:
            if cf.name in custom_fields:
                existing = set(cf.values)
                new_values = set(custom_fields[cf.name]) | existing
                if existing == new_values:
                    custom_fields.pop(cf.name)
        return custom_fields

    @activity.defn
    async def set_ip_related_custom_fields(
        self, transaction: structs.TransactionStruct, custom_fields: dict[str, Any]
    ) -> None:
        if transaction.ticket_obj is not None:
            if transaction.type == structs.TransactionTypeEnum.CREATE:
                self.rt_client.edit_ticket(
                    transaction.ticket_obj.id,
                    CustomFields=custom_fields,
                )
            elif (filtered := self.filter_changed_cf_values(transaction, custom_fields)) != {}:
                self.rt_client.edit_ticket(
                    transaction.ticket_obj.id,
                    CustomFields=filtered,
                )
