"""
全局执行状态管理器
用于支持任务的暂停、恢复和停止功能
使用轮询检查机制，确保线程安全
支持多用户/多执行ID并行管理
"""

import threading
import asyncio
from typing import Optional, Dict
from enum import Enum


class ExecutionStatus(Enum):
    """执行状态枚举"""
    RUNNING = "running"      # 正在运行
    PAUSED = "paused"        # 已暂停
    STOPPED = "stopped"      # 已停止
    IDLE = "idle"            # 空闲


class ExecutionStateManager:
    """
    全局执行状态管理器

    功能：
    - 管理多用户/多执行ID的并行状态（使用字典存储）
    - 管理任务执行状态（运行/暂停/停止）
    - 使用轮询检查机制，避免异步事件的线程问题
    - 提供线程安全的状态查询和修改接口

    设计说明：
    - 保持单例模式（Manager本身）
    - 但内部状态按 execution_id 隔离存储
    - 解决了多用户并发问题
    """

    _instance: Optional['ExecutionStateManager'] = None
    _lock = threading.Lock()

    def __new__(cls):
        """单例模式"""
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super().__new__(cls)
                    cls._instance._initialized = False
        return cls._instance

    def __init__(self):
        """初始化状态管理器"""
        if self._initialized:
            return

        self._initialized = True

        # 状态存储：execution_id -> 状态字典
        # 结构：{
        #   'status': ExecutionStatus,
        #   'goal': str,
        #   'should_pause': bool,
        #   'should_stop': bool
        # }
        self._states: Dict[str, Dict] = {}

        # 每个 execution_id 的锁（更细粒度的锁）
        self._locks: Dict[str, threading.Lock] = {}

        # 全局锁（用于管理 _states 和 _locks 本身的线程安全）
        self._manager_lock = threading.Lock()

    def _get_lock(self, execution_id: str) -> threading.Lock:
        """获取指定 execution_id 的锁，如果不存在则创建"""
        with self._manager_lock:
            if execution_id not in self._locks:
                self._locks[execution_id] = threading.Lock()
            return self._locks[execution_id]

    def _ensure_state(self, execution_id: str) -> Dict:
        """确保指定 execution_id 的状态存在"""
        with self._manager_lock:
            if execution_id not in self._states:
                self._states[execution_id] = {
                    'status': ExecutionStatus.IDLE,
                    'goal': None,
                    'should_pause': False,
                    'should_stop': False
                }
            return self._states[execution_id]

    def _get_state(self, execution_id: str) -> Optional[Dict]:
        """获取指定 execution_id 的状态，不存在则返回 None"""
        with self._manager_lock:
            return self._states.get(execution_id)

    def _cleanup_state(self, execution_id: str):
        """清理指定 execution_id 的状态"""
        with self._manager_lock:
            self._states.pop(execution_id, None)
            self._locks.pop(execution_id, None)

    def get_status(self, execution_id: str) -> Optional[ExecutionStatus]:
        """获取当前执行状态"""
        state = self._get_state(execution_id)
        if state is None:
            return None
        with self._get_lock(execution_id):
            return state['status']

    def set_goal(self, execution_id: str, goal: str):
        """设置当前执行的任务目标"""
        state = self._ensure_state(execution_id)
        with self._get_lock(execution_id):
            state['goal'] = goal

    def get_goal(self, execution_id: str) -> Optional[str]:
        """获取当前执行的任务目标"""
        state = self._get_state(execution_id)
        if state is None:
            return None
        with self._get_lock(execution_id):
            return state['goal']

    def start_execution(self, execution_id: str, goal: str):
        """开始执行"""
        state = self._ensure_state(execution_id)
        with self._get_lock(execution_id):
            state['status'] = ExecutionStatus.RUNNING
            state['goal'] = goal
            state['should_pause'] = False
            state['should_stop'] = False

    def pause_execution(self, execution_id: str) -> bool:
        """
        暂停执行

        Args:
            execution_id: 执行ID

        Returns:
            bool: 是否成功暂停
        """
        state = self._get_state(execution_id)
        if state is None:
            return False

        with self._get_lock(execution_id):
            if state['status'] != ExecutionStatus.RUNNING:
                return False
            state['status'] = ExecutionStatus.PAUSED
            state['should_pause'] = True
            return True

    def resume_execution(self, execution_id: str) -> bool:
        """
        恢复执行

        Args:
            execution_id: 执行ID

        Returns:
            bool: 是否成功恢复
        """
        state = self._get_state(execution_id)
        if state is None:
            return False

        with self._get_lock(execution_id):
            if state['status'] != ExecutionStatus.PAUSED:
                return False
            state['status'] = ExecutionStatus.RUNNING
            state['should_pause'] = False
            return True

    def stop_execution(self, execution_id: str) -> bool:
        """
        停止执行

        Args:
            execution_id: 执行ID

        Returns:
            bool: 是否成功停止
        """
        state = self._get_state(execution_id)
        if state is None:
            return False

        with self._get_lock(execution_id):
            if state['status'] in [ExecutionStatus.IDLE, ExecutionStatus.STOPPED]:
                return False
            state['status'] = ExecutionStatus.STOPPED
            state['should_stop'] = True
            state['should_pause'] = False
            return True

    def reset(self, execution_id: str):
        """重置指定 execution_id 的状态为空闲"""
        state = self._ensure_state(execution_id)
        with self._get_lock(execution_id):
            state['status'] = ExecutionStatus.IDLE
            state['goal'] = None
            state['should_pause'] = False
            state['should_stop'] = False

    def cleanup(self, execution_id: str):
        """清理指定 execution_id 的所有状态"""
        self._cleanup_state(execution_id)

    async def async_check_pause(self, execution_id: str):
        """
        异步检查是否需要暂停（轮询方式）

        如果处于暂停状态，会阻塞当前协程直到恢复或停止
        应该在执行循环的关键点调用此方法

        Args:
            execution_id: 执行ID

        Returns:
            bool: 如果返回True表示应该继续执行，False表示应该停止
        """
        state = self._get_state(execution_id)
        if state is None:
            # 状态不存在，默认继续执行
            return True

        # 使用轮询检查，避免异步事件问题
        while True:
            with self._get_lock(execution_id):
                should_stop = state['should_stop']
                should_pause = state['should_pause']

            # 检查停止标志
            if should_stop:
                return False

            # 检查暂停状态
            if should_pause:
                # 处于暂停状态，等待恢复
                await asyncio.sleep(0.1)  # 短暂睡眠，避免占用CPU

                # 重新获取状态
                with self._get_lock(execution_id):
                    should_pause = state['should_pause']
                    should_stop = state['should_stop']

                if not should_pause:
                    continue
                if should_stop:
                    return False
                # 继续等待
                continue

            # 既没有停止也没有暂停，可以继续执行
            return True

    def is_paused(self, execution_id: str) -> bool:
        """检查是否处于暂停状态"""
        state = self._get_state(execution_id)
        if state is None:
            return False
        with self._get_lock(execution_id):
            return state['status'] == ExecutionStatus.PAUSED

    def is_running(self, execution_id: str) -> bool:
        """检查是否正在运行"""
        state = self._get_state(execution_id)
        if state is None:
            return False
        with self._get_lock(execution_id):
            return state['status'] == ExecutionStatus.RUNNING

    def is_stopped(self, execution_id: str) -> bool:
        """检查是否已停止"""
        state = self._get_state(execution_id)
        if state is None:
            return True
        with self._get_lock(execution_id):
            return state['status'] == ExecutionStatus.STOPPED

    def is_active(self, execution_id: str) -> bool:
        """检查是否处于活动状态（运行中或暂停中）"""
        state = self._get_state(execution_id)
        if state is None:
            return False
        with self._get_lock(execution_id):
            return state['status'] in [ExecutionStatus.RUNNING, ExecutionStatus.PAUSED]


# 全局单例实例
execution_state_manager = ExecutionStateManager()
