"""
表单创建节点

将表单配置保存到数据库，创建完整的表单元数据
"""
import ast
import json
import logging
from typing import Any, Dict, List, Optional

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

logger = logging.getLogger(__name__)


@NodeRegistry.register
class FormCreateNode(BaseNode):
    """
    表单创建节点

    将表单基础信息、表单UI设计、列表设计等配置保存到数据库
    """

    node_type = 'form_create'
    node_name = '表单创建'
    node_category = 'form'
    node_icon = 'file-plus'
    node_description = '将表单配置保存到数据库，创建完整的表单元数据'

    inputs = [
        {
            'name': 'form_basic_info',
            'type': 'object',
            'description': '表单基础信息（来自表单基础信息节点）',
            'required': True,
        },
        {
            'name': 'database_design',
            'type': 'object',
            'description': '数据库设计配置（来自数据库设计节点）',
            'required': True,
        },
        {
            'name': 'form_ui_design',
            'type': 'object',
            'description': '表单UI设计配置（来自表单UI设计节点）',
            'required': True,
        },
        {
            'name': 'list_config',
            'type': 'object',
            'description': '列表配置（来自列表UI设计节点）',
            'required': True,
        },
        {
            'name': 'application_id',
            'type': 'string',
            'description': '所属应用ID（可选）',
            'required': False,
        },
    ]

    outputs = [
        {
            'name': 'form_id',
            'type': 'string',
            'description': '创建的表单ID',
        },
        {
            'name': 'form_code',
            'type': 'string',
            'description': '表单编码',
        },
        {
            'name': 'form_meta',
            '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_basic_info_raw = self.config.get('form_basic_info', '{}')
            database_design_raw = self.config.get('database_design', '{}')
            form_ui_design_raw = self.config.get('form_ui_design', '{}')
            list_config_raw = self.config.get('list_config', '{}')

            # 解析变量引用，保持原始类型
            form_basic_info = self._resolve_variable_value(context, form_basic_info_raw)
            database_design = self._resolve_variable_value(context, database_design_raw)
            form_ui_design = self._resolve_variable_value(context, form_ui_design_raw)
            list_config = self._resolve_variable_value(context, list_config_raw)
            application_id = context.resolve_template(self.config.get('application_id', ''))

            logger.info(f'FormCreateNode - 解析结果: form_basic_info={bool(form_basic_info)}, database_design={bool(database_design)}, form_ui_design={bool(form_ui_design)}, list_config={bool(list_config)}')

            # 配置选项
            update_if_exists = self.config.get('update_if_exists', True)

            logger.info(f'FormCreateNode - 开始创建表单')

            # 验证必要配置
            if not form_basic_info:
                return NodeResult(
                    success=False,
                    error='表单基础信息配置不能为空',
                )

            if not database_design:
                return NodeResult(
                    success=False,
                    error='数据库设计配置不能为空',
                )

            if not form_ui_design:
                return NodeResult(
                    success=False,
                    error='表单UI设计配置不能为空',
                )

            if not list_config:
                return NodeResult(
                    success=False,
                    error='列表配置不能为空',
                )

            # 提取基础信息
            form_name = form_basic_info.get('name', '')
            form_code_base = form_basic_info.get('code', '')
            form_type = form_basic_info.get('form_type', 'normal')
            description = form_basic_info.get('description', '')
            sort = form_basic_info.get('sort', 0)

            if not form_name or not form_code_base:
                return NodeResult(
                    success=False,
                    error='表单名称和编码不能为空',
                )

            # 提取数据库配置
            table_info = database_design.get('table', {})
            db_config = database_design.get('dbConfig', 'default')
            meta = table_info.get('meta', {})

            main_table = table_info.get('tableName', '')
            # 优先使用原始 schema 配置（可能包含变量），如果不存在则使用解析后的值
            main_table_schema = meta.get('schemaRaw', meta.get('schema', ''))
            main_table_database = meta.get('database', '')

            if not main_table:
                return NodeResult(
                    success=False,
                    error='主表名不能为空',
                )

            # 构建表配置（用于 form_config.tableConfigs）
            table_configs = self._build_table_configs(database_design)

            # 构建 form_config
            form_config = {
                'items': form_ui_design.get('items', []),
                'labelWidth': form_ui_design.get('labelWidth', 100),
                'labelPosition': form_ui_design.get('labelPosition', 'right'),
                'size': form_ui_design.get('size', 'default'),
                'tableConfigs': table_configs,
            }

            # 调用 FormService 创建表单
            from app.database import AsyncSessionLocal
            from online_dev.form_manager.service import FormService, FormServiceException

            async with AsyncSessionLocal() as db:
                try:
                    # 生成唯一的 code（如果已存在则自动添加后缀）
                    form_code = await self._get_unique_code(db, form_code_base, FormService)
                    logger.info(f'FormCreateNode - 使用 code: {form_code} (原始: {form_code_base})')

                    # 构建表单数据
                    form_data = {
                        'application_id': application_id if application_id else None,
                        'name': form_name,
                        'code': form_code,
                        'form_type': form_type,
                        'description': description,
                        'sort': sort,
                        'db_config': db_config,
                        'main_table': main_table,
                        'main_table_schema': main_table_schema,
                        'main_table_database': main_table_database,
                        'form_config': form_config,
                        'list_config': list_config,
                        'sub_tables': [],  # 暂不支持子表
                    }

                    logger.info(f'FormCreateNode - 表单数据: name={form_name}, code={form_code}, main_table={main_table}')

                    # 由于 _get_unique_code 已确保 code 唯一，直接创建表单
                    # 如果仍然出现重复（极端并发情况），捕获异常并处理
                    try:
                        form = await FormService.create(db, form_data)
                        logger.info(f'表单创建成功: {form_code}')
                    except FormServiceException as e:
                        # 如果是编码重复错误且允许更新，尝试更新
                        if '已存在' in str(e) and update_if_exists:
                            logger.warning(f'表单编码冲突，尝试更新: {form_code}')
                            try:
                                existing_form = await FormService.get_by_code(db, form_code)
                                form = await FormService.update(db, existing_form.id, form_data)
                                logger.info(f'表单更新成功: {form_code}')
                            except Exception as update_error:
                                return NodeResult(
                                    success=False,
                                    error=f'表单创建和更新均失败: {str(update_error)}',
                                )
                        else:
                            return NodeResult(
                                success=False,
                                error=f'表单创建失败: {str(e)}',
                            )

                    # 构建输出
                    form_meta = {
                        'id': form.id,
                        'name': form.name,
                        'code': form.code,
                        'form_type': form.form_type,
                        'description': form.description,
                        'status': form.status,
                        'version': form.version,
                        'db_config': form.db_config,
                        'main_table': form.main_table,
                        'main_table_schema': form.main_table_schema,
                        'main_table_database': form.main_table_database,
                    }

                    logger.info(f'FormCreateNode - 表单创建成功: id={form.id}, code={form.code}')

                    return NodeResult(
                        success=True,
                        output=form_meta,
                        output_variables={
                            'form_id': form.id,
                            'form_code': form.code,
                            'form_meta': form_meta,
                        },
                    )

                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)}',
                    )

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

    def _resolve_variable_value(self, context: NodeContext, raw_value: Any) -> Optional[Dict]:
        """
        解析变量引用，保持原始类型

        支持格式：
        - {{node_id.variable_name}} - 节点变量引用
        - 直接的字典值
        - JSON 字符串
        """
        import re

        # 如果已经是字典，直接返回
        if isinstance(raw_value, dict):
            return raw_value if raw_value else None

        # 如果不是字符串，尝试解析
        if not isinstance(raw_value, str):
            return None

        raw_value = raw_value.strip()
        if not raw_value or raw_value == '{}':
            return None

        # 检查是否是单个变量引用 {{node_id.variable_name}}
        single_var_pattern = r'^\{\{([^}]+)\}\}$'
        match = re.match(single_var_pattern, raw_value)

        if match:
            var_ref = match.group(1).strip()

            # 解析 node_id.variable_name 格式
            if '.' in var_ref:
                parts = var_ref.split('.', 1)
                node_id = parts[0]
                key = parts[1]

                # 从节点输出命名空间获取
                node_outputs = context.variables.get(f'_node_{node_id}')
                if isinstance(node_outputs, dict) and key in node_outputs:
                    value = node_outputs[key]
                    if isinstance(value, dict):
                        return value if value else None
                    return self._parse_config(value)

                # 变量未找到
                logger.warning(f'变量引用未找到: {var_ref}')
            else:
                # 直接变量引用
                if var_ref in context.variables:
                    value = context.variables[var_ref]
                    if isinstance(value, dict):
                        return value if value else None
                    return self._parse_config(value)

                logger.warning(f'变量引用未找到: {var_ref}')

        # 不是变量引用，尝试解析为 JSON 或 Python dict
        return self._parse_config(raw_value)

    def _parse_config(self, config_str: Any) -> Optional[Dict]:
        """解析配置"""
        # 如果已经是字典，直接返回
        if isinstance(config_str, dict):
            return config_str if config_str else None

        # 如果是列表，返回 None（不是有效的配置）
        if isinstance(config_str, list):
            return None

        # 如果是字符串，尝试解析
        if isinstance(config_str, str):
            config_str = config_str.strip()
            if not config_str or config_str == '{}' or config_str == 'None':
                return None

            # 检查是否是未解析的模板变量（仍然包含 {{ }}）
            if '{{' in config_str and '}}' in config_str:
                logger.warning(f'配置值仍包含未解析的模板变量: {config_str[:100]}')
                return None

            # 尝试 JSON 解析
            try:
                result = json.loads(config_str)
                if isinstance(result, dict):
                    return result if result else None
                return None
            except json.JSONDecodeError:
                pass

            # 尝试 Python literal_eval（处理单引号格式）
            try:
                result = ast.literal_eval(config_str)
                if isinstance(result, dict):
                    return result if result else None
                return None
            except (ValueError, SyntaxError) as e:
                logger.warning(f'配置解析失败: {e}, 值: {config_str[:200]}')
                return None

        return None

    async def _get_unique_code(self, db, base_code: str, service) -> str:
        """
        生成唯一的 code，如果已存在则自动添加数字后缀

        Args:
            db: 数据库会话
            base_code: 基础 code
            service: 服务类（需要有 get_by_code 方法）

        Returns:
            唯一的 code
        """
        from sqlalchemy import select
        from online_dev.form_manager.model import FormMeta

        code = base_code
        counter = 1

        while True:
            # 直接查询数据库，避免 get_by_code 的异常处理问题
            stmt = select(FormMeta).where(
                FormMeta.code == code,
                FormMeta.is_deleted == False
            )
            result = await db.execute(stmt)
            existing = result.scalar_one_or_none()

            if not existing:
                # code 不存在，可以使用
                break

            # code 已存在，添加后缀
            code = f"{base_code}_{counter}"
            counter += 1

            # 防止无限循环
            if counter > 100:
                logger.warning(f'生成唯一 code 失败，已尝试 {counter} 次')
                break

        return code

    def _build_table_configs(self, database_design: Dict) -> List[Dict]:
        """构建表配置列表"""
        table_configs = []

        table_info = database_design.get('table', {})
        if not table_info:
            return table_configs

        meta = table_info.get('meta', {}).copy() if table_info.get('meta') else {}

        # 确保 meta 中包含 dbName（从 database_design.dbConfig 获取，如果 meta 中没有的话）
        if not meta.get('dbName') and database_design.get('dbConfig'):
            meta['dbName'] = database_design.get('dbConfig')

        # 主表配置
        main_config = {
            'type': 'main',
            'tableName': table_info.get('tableName', ''),
            'alias': table_info.get('alias', table_info.get('tableName', '')),
            'fields': table_info.get('fields', []),
            'meta': meta,
        }
        table_configs.append(main_config)

        return table_configs

    @classmethod
    def get_config_schema(cls) -> Dict[str, Any]:
        """获取节点配置 Schema"""
        return {
            'type': 'object',
            'properties': {
                'form_basic_info': {
                    'type': 'string',
                    'title': '表单基础信息',
                    'description': '来自表单基础信息节点的输出',
                    'x-component': 'SmartInput',
                },
                'database_design': {
                    'type': 'string',
                    'title': '数据库设计配置',
                    'description': '来自数据库设计节点的输出',
                    'x-component': 'SmartInput',
                },
                'form_ui_design': {
                    'type': 'string',
                    'title': '表单UI设计配置',
                    'description': '来自表单UI设计节点的输出',
                    'x-component': 'SmartInput',
                },
                'list_config': {
                    'type': 'string',
                    'title': '列表配置',
                    'description': '来自列表UI设计节点的输出',
                    'x-component': 'SmartInput',
                },
                'application_id': {
                    'type': 'string',
                    'title': '所属应用ID',
                    'description': '表单所属的应用ID（子应用模式下自动获取）',
                    'default': '{{application_id}}',
                    'x-component': 'SmartInput',
                },
                'update_if_exists': {
                    'type': 'boolean',
                    'title': '存在时更新',
                    'description': '表单编码已存在时是否更新',
                    'default': True,
                    'x-component': 'Switch',
                },
            },
            'required': ['form_basic_info', 'database_design', 'form_ui_design', 'list_config'],
        }
