import threading
from time import sleep
from typing import Dict, Any, Optional
from typing import List, Tuple

from app.core.config import global_vars
from app.core.event import eventmanager, Event
from app.db.models import Workflow
from app.db.workflow_oper import WorkflowOper
from app.helper.module import ModuleHelper
from app.log import logger
from app.schemas import ActionContext, Action
from app.schemas.types import EventType
from app.utils.singleton import Singleton


class WorkFlowManager(metaclass=Singleton):
    """
    工作流管理器
    """

    def __init__(self):
        # 所有动作定义
        self._lock = threading.Lock()
        self._actions: Dict[str, Any] = {}
        self._event_workflows: Dict[str, List[int]] = {}
        self.init()

    def init(self):
        """
        初始化
        """

        def filter_func(obj: Any):
            """
            过滤函数，确保只加载新定义的类
            """
            if not isinstance(obj, type):
                return False
            if not hasattr(obj, 'execute') or not hasattr(obj, "name"):
                return False
            if obj.__name__ == "BaseAction":
                return False
            return obj.__module__.startswith("app.workflow.actions")

        # 加载所有动作
        self._actions = {}
        actions = ModuleHelper.load(
            "app.workflow.actions",
            filter_func=lambda _, obj: filter_func(obj)
        )
        for action in actions:
            logger.debug(f"加载动作: {action.__name__}")
            try:
                self._actions[action.__name__] = action
            except Exception as err:
                logger.error(f"加载动作失败: {action.__name__} - {err}")

        # 加载工作流事件触发器
        self.load_workflow_events()

    def stop(self):
        """
        停止
        """
        self._actions = {}
        self._event_workflows = {}

    def excute(self, workflow_id: int, action: Action,
               context: ActionContext = None) -> Tuple[bool, str, ActionContext]:
        """
        执行工作流动作
        """
        if not context:
            context = ActionContext()
        if action.type in self._actions:
            # 实例化之前，清理掉类对象的数据

            # 实例化
            action_obj = self._actions[action.type](action.id)
            # 执行
            logger.info(f"执行动作: {action.id} - {action.name}")
            try:
                result_context = action_obj.execute(workflow_id, action.data, context)
            except Exception as err:
                logger.error(f"{action.name} 执行失败: {err}")
                return False, f"{err}", context
            loop = action.data.get("loop")
            loop_interval = action.data.get("loop_interval")
            if loop and loop_interval:
                while not action_obj.done:
                    if global_vars.is_workflow_stopped(workflow_id):
                        break
                    # 等待
                    logger.info(f"{action.name} 等待 {loop_interval} 秒后继续执行 ...")
                    sleep(loop_interval)
                    # 执行
                    logger.info(f"继续执行动作: {action.id} - {action.name}")
                    result_context = action_obj.execute(workflow_id, action.data, result_context)
            if action_obj.success:
                logger.info(f"{action.name} 执行成功")
            else:
                logger.error(f"{action.name} 执行失败！")
            return action_obj.success, action_obj.message, result_context
        else:
            logger.error(f"未找到动作: {action.type} - {action.name}")
            return False, " ", context

    def list_actions(self) -> List[dict]:
        """
        获取所有动作
        """
        return [
            {
                "type": key,
                "name": action.name,
                "description": action.description,
                "data": {
                    "label": action.name,
                    **action.data
                }
            } for key, action in self._actions.items()
        ]

    def update_workflow_event(self, workflow: Workflow):
        """
        更新工作流事件触发器
        """
        # 确保先移除旧的事件监听器
        self.remove_workflow_event(workflow_id=workflow.id, event_type_str=workflow.event_type)
        # 如果工作流是事件触发类型且未被禁用
        if workflow.trigger_type == "event" and workflow.state != 'P':
            # 注册事件触发器
            self.register_workflow_event(workflow.id, workflow.event_type)

    def load_workflow_events(self, workflow_id: Optional[int] = None):
        """
        加载工作流触发事件
        """
        workflows = []
        if workflow_id:
            workflow = WorkflowOper().get(workflow_id)
            if workflow:
                workflows = [workflow]
        else:
            workflows = WorkflowOper().get_event_triggered_workflows()
        try:
            for workflow in workflows:
                self.update_workflow_event(workflow)
        except Exception as e:
            logger.error(f"加载事件触发工作流失败: {e}")

    def register_workflow_event(self, workflow_id: int, event_type_str: str):
        """
        注册工作流事件触发器
        """
        try:
            event_type = EventType(event_type_str)
        except ValueError:
            logger.error(f"无效的事件类型: {event_type_str}")
            return
        if event_type in EventType:
            # 确保先移除旧的事件监听器
            self.remove_workflow_event(workflow_id, event_type.value)
            with self._lock:
                # 添加新的事件监听器
                eventmanager.add_event_listener(event_type, self._handle_event)
                # 记录工作流事件触发器
                if event_type.value not in self._event_workflows:
                    self._event_workflows[event_type.value] = []
                self._event_workflows[event_type.value].append(workflow_id)
                logger.info(f"已注册工作流 {workflow_id} 事件触发器: {event_type.value}")

    def remove_workflow_event(self, workflow_id: int, event_type_str: str):
        """
        移除工作流事件触发器
        """
        try:
            event_type = EventType(event_type_str)
        except ValueError:
            logger.error(f"无效的事件类型: {event_type_str}")
            return
        if event_type in EventType:
            with self._lock:
                eventmanager.remove_event_listener(event_type, self._handle_event)
                if event_type.value in self._event_workflows:
                    if workflow_id in self._event_workflows[event_type.value]:
                        self._event_workflows[event_type.value].remove(workflow_id)
                        if not self._event_workflows[event_type.value]:
                            del self._event_workflows[event_type.value]
                logger.info(f"已移除工作流 {workflow_id} 事件触发器")

    def _handle_event(self, event: Event):
        """
        处理事件，触发相应的工作流
        """
        try:
            event_type_str = str(event.event_type.value)
            with self._lock:
                if event_type_str not in self._event_workflows:
                    return
                workflow_ids = self._event_workflows[event_type_str].copy()
            for workflow_id in workflow_ids:
                self._trigger_workflow(workflow_id, event)
        except Exception as e:
            logger.error(f"处理工作流事件失败: {e}")

    def _trigger_workflow(self, workflow_id: int, event: Event):
        """
        触发工作流执行
        """
        try:
            # 检查工作流是否存在且启用
            workflow = WorkflowOper().get(workflow_id)
            if not workflow or workflow.state == 'P':
                return

            # 检查事件条件
            if not self._check_event_conditions(workflow, event):
                logger.debug(f"工作流 {workflow.name} 事件条件不匹配，跳过执行")
                return

            # 检查工作流是否正在运行
            if workflow.state == 'R':
                logger.warning(f"工作流 {workflow.name} 正在运行中，跳过重复触发")
                return

            logger.info(f"事件 {event.event_type.value} 触发工作流: {workflow.name}")

            # 发送工作流执行事件以启动工作流
            eventmanager.send_event(EventType.WorkflowExecute, {
                "workflow_id": workflow_id,
            })

        except Exception as e:
            logger.error(f"触发工作流 {workflow_id} 失败: {e}")

    def _check_event_conditions(self, workflow, event: Event) -> bool:
        """
        检查事件是否满足工作流的触发条件
        """
        if not workflow.event_conditions:
            return True

        conditions = workflow.event_conditions
        event_data = event.event_data or {}

        # 检查字段匹配条件
        for field, expected_value in conditions.items():
            if field not in event_data:
                return False
            actual_value = event_data[field]
            # 支持多种条件匹配方式
            if isinstance(expected_value, dict):
                # 复杂条件匹配
                if not self._check_complex_condition(actual_value, expected_value):
                    return False
            else:
                # 简单值匹配
                if actual_value != expected_value:
                    return False
        return True

    @staticmethod
    def _check_complex_condition(actual_value: any, condition: dict) -> bool:
        """
        检查复杂条件匹配
        支持的操作符：equals, not_equals, contains, not_contains, in, not_in, regex
        """
        for operator, expected_value in condition.items():
            if operator == "equals":
                if actual_value != expected_value:
                    return False
            elif operator == "not_equals":
                if actual_value == expected_value:
                    return False
            elif operator == "contains":
                if expected_value not in str(actual_value):
                    return False
            elif operator == "not_contains":
                if expected_value in str(actual_value):
                    return False
            elif operator == "in":
                if actual_value not in expected_value:
                    return False
            elif operator == "not_in":
                if actual_value in expected_value:
                    return False
            elif operator == "regex":
                import re
                if not re.search(expected_value, str(actual_value)):
                    return False
        return True

    def get_event_workflows(self) -> dict:
        """
        获取所有事件触发的工作流
        """
        with self._lock:
            return self._event_workflows.copy()
