# Copyright (c) 2025 Patrick Motsch
# Input/Human node executor - creates tasks and pauses execution.

import logging
from typing import Dict, Any

logger = logging.getLogger(__name__)


class PauseForHumanTaskError(Exception):
    """Raised when execution must pause for a human task. Contains runId, taskId."""

    def __init__(self, runId: str, taskId: str, nodeId: str):
        self.runId = runId
        self.taskId = taskId
        self.nodeId = nodeId
        super().__init__(f"Pause for human task {taskId} (run {runId}, node {nodeId})")


class PauseForEmailWaitError(Exception):
    """Raised when execution must pause waiting for a new email. Background poller will resume."""

    def __init__(self, runId: str, nodeId: str, waitConfig: Dict[str, Any]):
        self.runId = runId
        self.nodeId = nodeId
        self.waitConfig = waitConfig
        super().__init__(f"Pause for email wait (run {runId}, node {nodeId})")


class InputExecutor:
    """
    Execute input/human nodes. Creates a HumanTask, pauses the run, and raises
    PauseForHumanTaskError so the engine returns { paused: true, taskId, runId }.
    """

    def __init__(self, automation2_interface: Any):
        self.automation2 = automation2_interface

    async def execute(
        self,
        node: Dict[str, Any],
        context: Dict[str, Any],
    ) -> Any:
        nodeType = node.get("type", "")
        nodeId = node.get("id", "")
        runId = context.get("_runId")
        workflowId = context.get("workflowId")
        instanceId = context.get("instanceId")
        userId = context.get("userId")

        if not runId or not workflowId:
            logger.error("InputExecutor: runId/workflowId missing in context - cannot create task")
            return {"error": "Missing run context", "success": False}

        config = dict(node.get("parameters") or {})
        logger.info("InputExecutor node %s type=%s creating task", nodeId, nodeType)

        task = self.automation2.createTask(
            runId=runId,
            workflowId=workflowId,
            nodeId=nodeId,
            nodeType=nodeType,
            config=config,
            assigneeId=userId,
        )
        taskId = task.get("id")

        self.automation2.updateRun(
            runId,
            status="paused",
            nodeOutputs=context.get("nodeOutputs"),
            currentNodeId=nodeId,
            context={
                "connectionMap": context.get("connectionMap"),
                "inputSources": context.get("inputSources"),
                "orderedNodeIds": [n.get("id") for n in context.get("_orderedNodes", []) if n.get("id")],
            },
        )
        logger.info("InputExecutor node %s: created task %s, run %s paused", nodeId, taskId, runId)
        raise PauseForHumanTaskError(runId=runId, taskId=taskId, nodeId=nodeId)
