"""
表单发布节点

将已创建的表单发布到菜单系统
"""
import logging
from typing import Any, Dict, Optional

from ..base import BaseNode, NodeContext, NodeResult
from ..registry import NodeRegistry

logger = logging.getLogger(__name__)


@NodeRegistry.register
class FormPublishNode(BaseNode):
    """
    表单发布节点

    将已创建的表单发布到菜单系统，生成菜单和权限
    """

    node_type = 'form_publish'
    node_name = '表单发布'
    node_category = 'form'
    node_icon = 'send'
    node_description = '将已创建的表单发布到菜单系统'

    inputs = [
        {
            'name': 'form_id',
            'type': 'string',
            'description': '表单ID（来自表单创建节点）',
            'required': True,
        },
        {
            'name': 'form_code',
            'type': 'string',
            'description': '表单编码（可选，用于生成路由）',
            'required': False,
        },
    ]

    outputs = [
        {
            'name': 'menu_id',
            'type': 'string',
            'description': '创建的菜单ID',
        },
        {
            'name': 'route_path',
            'type': 'string',
            'description': '表单访问路径',
        },
        {
            'name': 'publish_result',
            'type': 'object',
            'description': '发布结果详情',
        },
    ]

    def execute(self, context: NodeContext) -> NodeResult:
        """执行节点（同步方法，通过运行异步方法实现）"""
        import asyncio

        loop = asyncio.get_event_loop()
        if loop.is_running():
            import concurrent.futures
            with concurrent.futures.ThreadPoolExecutor() as executor:
                future = executor.submit(asyncio.run, self.execute_async(context))
                return future.result()
        else:
            return loop.run_until_complete(self.execute_async(context))

    async def execute_async(self, context: NodeContext) -> NodeResult:
        """异步执行节点"""
        try:
            # 获取输入参数
            form_id = context.resolve_template(self.config.get('form_id', ''))
            form_code = context.resolve_template(self.config.get('form_code', ''))
            require_confirmation = self.resolve_require_confirmation(context, default=True)

            logger.info(f'FormPublishNode - 开始发布表单: form_id={form_id}')

            # 验证必要参数
            if not form_id:
                return NodeResult(
                    success=False,
                    error='表单ID不能为空',
                )

            # 检查是否有用户编辑的数据（从设计预览面板提交）
            user_input = context.variables.get('__user_input__')
            if user_input:
                publish_config = self._parse_user_input(user_input)
                if publish_config:
                    logger.info(f'FormPublishNode - 使用用户编辑的数据: {publish_config}')
                    # 清除用户输入，防止重复处理
                    context.variables.pop('__user_input__', None)
                    return await self._do_publish(context, form_id, publish_config)

            # 如果需要确认，返回等待用户输入
            if require_confirmation:
                return await self._wait_for_confirmation(form_id)

            # 不需要确认，直接发布（使用默认配置）
            return await self._do_publish(context, form_id, {})

        except Exception as e:
            logger.exception(f'表单发布节点执行失败: {e}')
            return NodeResult(
                success=False,
                error=f'节点执行失败: {str(e)}',
            )

    def _parse_user_input(self, user_input: Any) -> Optional[Dict]:
        """解析用户输入"""
        import json

        if isinstance(user_input, dict):
            # 检查是否是 publishData 格式
            if 'publishData' in user_input:
                return user_input.get('publishData', {})
            return user_input

        if isinstance(user_input, str):
            try:
                data = json.loads(user_input)
                if isinstance(data, dict):
                    if 'publishData' in data:
                        return data.get('publishData', {})
                    return data
            except json.JSONDecodeError:
                pass

        return None

    async def _wait_for_confirmation(self, form_id: str) -> NodeResult:
        """等待用户确认"""
        from app.database import AsyncSessionLocal
        from online_dev.form_manager.service import FormService

        async with AsyncSessionLocal() as db:
            form = await FormService.get(db, form_id)
            if not form:
                return NodeResult(
                    success=False,
                    error=f'表单不存在: {form_id}',
                )

            # 构建预览数据
            preview_data = {
                'type': 'form_publish',
                'data': {
                    'publishData': {
                        'menu_name': form.name,
                        'menu_parent_id': None,
                        'menu_icon': 'lucide:file-text',
                        'menu_order': 1,
                    },
                },
            }

            # 返回等待用户输入的结果
            return NodeResult(
                success=True,
                waiting_for_input=True,
                waiting_config={
                    'type': 'design_preview',
                    'preview_type': 'form_publish',
                    'title': '发布表单',
                    'message': '请确认或编辑发布配置',
                    'data': {
                        'menu_name': form.name,
                        'menu_parent_id': None,
                        'menu_icon': 'lucide:file-text',
                        'menu_order': 1,
                    },
                },
                preview=preview_data,
            )

    async def _do_publish(self, context: NodeContext, form_id: str, publish_config: Dict) -> NodeResult:
        """执行发布"""
        from app.database import AsyncSessionLocal
        from online_dev.form_manager.service import FormService, FormServiceException

        async with AsyncSessionLocal() as db:
            try:
                # 获取表单
                form = await FormService.get(db, form_id)
                if not form:
                    return NodeResult(
                        success=False,
                        error=f'表单不存在: {form_id}',
                    )

                # 构建发布配置
                menu_name = publish_config.get('menu_name', form.name)
                menu_parent_id = publish_config.get('menu_parent_id')
                menu_icon = publish_config.get('menu_icon', 'lucide:file-text')
                menu_order = publish_config.get('menu_order', 1)

                publish_data = {
                    'menu_name': menu_name,
                    'menu_parent_id': menu_parent_id if menu_parent_id else None,
                    'menu_icon': menu_icon,
                    'menu_order': menu_order,
                    'allow_add': True,
                    'allow_edit': True,
                    'allow_delete': True,
                    'allow_export': True,
                    'allow_import': False,
                }

                # 构建路由路径
                route_path = f'/form-render/{form.code}'

                # 检查表单是否已发布
                if form.status == 'published':
                    # 表单已发布，更新菜单配置
                    logger.info(f'FormPublishNode - 表单已发布，更新菜单配置: form_id={form_id}')
                    await self._update_menu_config(db, form, publish_data)
                else:
                    # 发布表单
                    form = await FormService.publish(db, form_id, publish_data)

                # 构建输出
                publish_result = {
                    'form_id': form.id,
                    'form_code': form.code,
                    'form_name': form.name,
                    'status': form.status,
                    'menu_name': menu_name,
                    'menu_icon': menu_icon,
                    'route_path': route_path,
                }

                logger.info(f'FormPublishNode - 表单发布成功: form_id={form_id}, route_path={route_path}')

                return NodeResult(
                    success=True,
                    output=publish_result,
                    output_variables={
                        'menu_id': form.menu_id if hasattr(form, 'menu_id') else '',
                        'route_path': route_path,
                        'publish_result': publish_result,
                    },
                )

            except FormServiceException as e:
                logger.error(f'表单服务异常: {e}')
                return NodeResult(
                    success=False,
                    error=f'表单发布失败: {str(e)}',
                )
            except Exception as e:
                logger.exception(f'表单发布异常: {e}')
                return NodeResult(
                    success=False,
                    error=f'表单发布异常: {str(e)}',
                )

    async def _update_menu_config(self, db, form, publish_data: Dict):
        """更新已发布表单的菜单配置"""
        from sqlalchemy import select
        from core.menu.model import Menu

        # 查找表单对应的菜单
        menu_stmt = select(Menu).where(
            Menu.path == f"/form-render/{form.code}"
        )
        menu_result = await db.execute(menu_stmt)
        existing_menu = menu_result.scalar_one_or_none()

        if existing_menu:
            # 更新菜单配置
            existing_menu.name = publish_data.get('menu_name', form.name)
            existing_menu.title = publish_data.get('menu_name', form.name)
            existing_menu.parent_id = publish_data.get('menu_parent_id')
            existing_menu.icon = publish_data.get('menu_icon', 'lucide:file-text')
            existing_menu.order = publish_data.get('menu_order', 0)
            await db.commit()
            logger.info(f'更新表单菜单配置: {form.code}')

    @classmethod
    def get_config_schema(cls) -> Dict[str, Any]:
        """获取节点配置 Schema"""
        return {
            'type': 'object',
            'properties': {
                'form_id': {
                    'type': 'string',
                    'title': '表单ID',
                    'description': '来自表单创建节点的输出',
                    'x-component': 'SmartInput',
                },
                'form_code': {
                    'type': 'string',
                    'title': '表单编码',
                    'description': '用于生成访问路由（可选）',
                    'x-component': 'SmartInput',
                },
                'require_confirmation': {
                    'type': 'boolean',
                    'title': '需要确认',
                    'description': '发布前是否需要用户确认配置',
                    'default': True,
                    'x-component': 'Switch',
                },
            },
            'required': ['form_id'],
        }
