import hashlib
from base64 import b64decode
from collections.abc import Awaitable, Callable, Sequence
from typing import Any

from temporalio import activity, workflow

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.utils import get_custom_field_value_from_transaction
from csirtmu.beta_temporal.workflows.logging import LoggedActivities, LoggedWorkflow


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

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

    @activity.defn
    async def hash_attachments(self, transaction: structs.TransactionStruct) -> None:
        self.log_activity()
        if transaction.ticket_obj is None:
            return
        if (ticket_data := self.rt_client.get_ticket_data(transaction)) is None:
            return
        cf_hashes = get_custom_field_value_from_transaction(transaction, "Attachment hashes")
        attachment_hashes: list[str] = cf_hashes.values if cf_hashes else []
        for attachment in ticket_data.attachments:
            if (
                attachment.filename is None
                or attachment.filename == ""
                or attachment.content_type == "pkc7-signature"
                or attachment.content is None
            ):
                continue
            attachment_hash = hashlib.sha256(b64decode(attachment.content)).hexdigest() + "\t" + attachment.filename
            if attachment_hash in attachment_hashes:
                continue
            attachment_hashes.append(attachment_hash)
        self.rt_client.edit_ticket(transaction.ticket_obj.id, CustomFields={"Attachment hashes": attachment_hashes})


class HashDiscoveredAttachments(LoggedWorkflow, workflow_name=WorkflowReference.HASH_DISCOVERED_ATTACHMENTS):
    @classmethod
    def get_activities(cls) -> Sequence[Callable[..., Awaitable[Any]]]:
        config = AppConfig.get()
        return HashDiscoveredAttachmentsActivities(RTClient(config.rt)).get_activities()

    @workflow.run
    async def run(self, transaction: structs.TransactionStruct) -> None:
        self.log_workflow()
        config = AppConfig.get()
        await workflow.execute_activity(
            HashDiscoveredAttachmentsActivities.hash_attachments,
            args=(transaction,),
            retry_policy=config.temporal.retry_policy,
            start_to_close_timeout=config.temporal.activity_timeout,
        )
