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.commons.conditions import CommonConditions
from csirtmu.beta_temporal.config import AppConfig
from csirtmu.beta_temporal.constants import WorkflowReference
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.external_services.rt.utils import get_custom_field_value_from_transaction
from csirtmu.beta_temporal.workflows.logging import LoggedActivities, LoggedWorkflow


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

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

    @activity.defn
    async def set_category(self, transaction: TransactionStruct) -> None:
        self.log_activity()
        if (data := self.rt_client.get_ticket_data(transaction)) is None:
            return
        category = data.headers.get("X-RT-Category")
        subcategory = data.headers.get("X-RT-Subcategory")
        original_category = get_custom_field_value_from_transaction(data.transaction, "Category")

        if (not category and (not original_category or not original_category.values)) or (
            (original_category and original_category.values) and "Testing ticket" not in original_category.values
        ):
            return
        if not data.transaction.ticket_obj:
            raise ValueError("Ticket object is None.")

        self.rt_client.edit_custom_field(
            data.transaction.ticket_obj.id,
            "Category",
            "Testing ticket" if (not category or category == "") else category,
        )
        if subcategory and subcategory != "":
            self.rt_client.edit_custom_field(data.transaction.ticket_obj.id, "Subcategory", subcategory)


class SetCategoryForToolReport(LoggedWorkflow, workflow_name=WorkflowReference.SET_CATEGORY_FOR_TOOL_REPORT):
    @classmethod
    def get_activities(cls) -> Sequence[Callable[..., Awaitable[Any]]]:
        config = AppConfig.get()
        rt_client = RTClient(config.rt)
        common_conditions = CommonConditions(rt_client)
        local_activities = SetCategoryForToolReportActivities(rt_client)
        temporal_actions = TemporalCommonActions(config.temporal)
        return [
            *common_conditions.get_activities(),
            *local_activities.get_activities(),
            *temporal_actions.get_activities(),
        ]

    @workflow.run
    async def run(self, transaction: structs.TransactionStruct) -> None:
        self.log_workflow()
        config = AppConfig.get()
        if await workflow.execute_activity(
            CommonConditions.is_tool_report,
            args=(transaction,),
            retry_policy=config.temporal.retry_policy,
            start_to_close_timeout=config.temporal.activity_timeout,
        ):
            await workflow.execute_activity(
                SetCategoryForToolReportActivities.set_category,
                args=(transaction,),
                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,
            )
