"""
Dramatiq Worker Starter Worker
===============================

Worker 启动器，提供简化的启动接口
"""

import logging
import signal
import time

import dramatiq

logger = logging.getLogger(__name__)


class Worker:
    """
    Worker 启动器

    提供简化的 Worker 启动接口，支持自定义队列监听
    """

    def __init__(
        self,
        broker_instance: dramatiq.Broker,
        queues: list[str] | None = None,
        worker_timeout: int = 3600000,
        shutdown_timeout: int = 60000,
    ):
        """
        初始化 Worker

        :param broker_instance: Dramatiq Broker 实例
        :type broker_instance: dramatiq.Broker
        :param queues: 要监听的队列列表，如果为 None 则自动声明所有 Actor 队列
        :type queues: list[str] | None
        :param worker_timeout: Worker 超时时间（毫秒）
        :type worker_timeout: int
        :param shutdown_timeout: 关闭超时时间（毫秒）
        :type shutdown_timeout: int
        """
        self.broker = broker_instance
        self.queues = queues
        self.worker_timeout = worker_timeout
        self.shutdown_timeout = shutdown_timeout
        self._worker: dramatiq.Worker | None = None
        self._running = False

    def start(self) -> None:
        """
        启动 Worker（阻塞运行，直到收到终止信号）
        """
        # 声明队列
        if self.queues is None:
            # 自动声明所有 Actor 队列（去重）
            queues_to_listen = set()
            for _actor_name, actor in self.broker.actors.items():
                queue_name = actor.queue_name
                self.broker.declare_queue(queue_name)
                queues_to_listen.add(queue_name)
            queues_to_listen = list(queues_to_listen)
            logger.info(f"Auto-declared {len(queues_to_listen)} queues: {queues_to_listen}")
        else:
            # 声明指定的队列
            for queue in self.queues:
                self.broker.declare_queue(queue)
            queues_to_listen = self.queues

        if not queues_to_listen:
            logger.warning("No queues to listen. Exiting.")
            return

        # 设置信号处理器
        signal.signal(signal.SIGINT, self._signal_handler)
        signal.signal(signal.SIGTERM, self._signal_handler)

        # 创建并启动 Worker
        self._worker = dramatiq.Worker(
            self.broker,
            queues=queues_to_listen,
            worker_timeout=self.worker_timeout,
        )

        logger.info(f"Starting worker on queues: {queues_to_listen}")
        logger.info(f"Registered actors: {list(self.broker.actors.keys())}")

        self._worker.start()
        self._running = True

        # 等待信号（使用 dramatiq CLI 的方式）
        while self._running:
            time.sleep(1)

        # 停止 Worker
        logger.info("Stopping worker...")
        self._worker.stop(timeout=self.shutdown_timeout)
        self._worker.join()
        logger.info("Worker stopped")

    def stop(self) -> None:
        """
        停止 Worker
        """
        self._running = False

    def _signal_handler(self, signum: int, _frame) -> None:
        """
        信号处理器

        :param signum: 信号编号
        :param _frame: 栈帧
        """
        if self._running:
            logger.info(f"Received signal {signum}, shutting down...")
            self._running = False
        else:
            logger.warning("Already shutting down, ignoring signal...")


def run_worker(
    broker_instance: dramatiq.Broker,
    queues: list[str] | None = None,
    worker_timeout: int = 3600000,
    shutdown_timeout: int = 60000,
) -> None:
    """
    快捷启动 Worker 函数

    :param broker_instance: Dramatiq Broker 实例
    :type broker_instance: dramatiq.Broker
    :param queues: 要监听的队列列表，如果为 None 则自动声明所有 Actor 队列
    :type queues: list[str] | None
    :param worker_timeout: Worker 超时时间（毫秒）
    :type worker_timeout: int
    :param shutdown_timeout: 关闭超时时间（毫秒）
    :type shutdown_timeout: int
    """
    worker = Worker(
        broker_instance=broker_instance,
        queues=queues,
        worker_timeout=worker_timeout,
        shutdown_timeout=shutdown_timeout,
    )
    worker.start()
