"""
GraphEngine Manager for sending control commands via Redis channel.

This module provides a simplified interface for controlling workflow executions
using the new Redis command channel, without requiring user permission checks.
Callers must provide a Redis client dependency from outside the workflow package.
"""

import logging
from collections.abc import Sequence
from typing import final

from dify_graph.graph_engine.command_channels.redis_channel import RedisChannel, RedisClientProtocol
from dify_graph.graph_engine.entities.commands import (
    AbortCommand,
    GraphEngineCommand,
    PauseCommand,
    UpdateVariablesCommand,
    VariableUpdate,
)

logger = logging.getLogger(__name__)


@final
class GraphEngineManager:
    """
    Manager for sending control commands to GraphEngine instances.

    This class provides a simple interface for controlling workflow executions
    by sending commands through Redis channels, without user validation.
    """

    _redis_client: RedisClientProtocol

    def __init__(self, redis_client: RedisClientProtocol) -> None:
        self._redis_client = redis_client

    def send_stop_command(self, task_id: str, reason: str | None = None) -> None:
        """
        Send a stop command to a running workflow.

        Args:
            task_id: The task ID of the workflow to stop
            reason: Optional reason for stopping (defaults to "User requested stop")
        """
        abort_command = AbortCommand(reason=reason or "User requested stop")
        self._send_command(task_id, abort_command)

    def send_pause_command(self, task_id: str, reason: str | None = None) -> None:
        """Send a pause command to a running workflow."""

        pause_command = PauseCommand(reason=reason or "User requested pause")
        self._send_command(task_id, pause_command)

    def send_update_variables_command(self, task_id: str, updates: Sequence[VariableUpdate]) -> None:
        """Send a command to update variables in a running workflow."""

        if not updates:
            return

        update_command = UpdateVariablesCommand(updates=updates)
        self._send_command(task_id, update_command)

    def _send_command(self, task_id: str, command: GraphEngineCommand) -> None:
        """Send a command to the workflow-specific Redis channel."""

        if not task_id:
            return

        channel_key = f"workflow:{task_id}:commands"
        channel = RedisChannel(self._redis_client, channel_key)

        try:
            channel.send_command(command)
        except Exception:
            # Silently fail if Redis is unavailable
            # The legacy control mechanisms will still work
            logger.exception("Failed to send graph engine command %s for task %s", command.__class__.__name__, task_id)
