"""
表单UI设计节点

根据数据库表结构自动生成表单UI配置
"""
import json
import logging
import re
import uuid
from typing import Any, Dict, List, Optional, Tuple

from ..base import BaseNode, NodeContext, NodeResult
from ..registry import NodeRegistry
from ..utils.config_utils import resolve_object_config

logger = logging.getLogger(__name__)


@NodeRegistry.register
class FormUIDesignNode(BaseNode):
    """
    表单UI设计节点

    根据数据库表结构自动生成表单UI配置，包括：
    - 字段到组件的映射
    - 验证规则推断
    - 组件属性配置
    - 字段分组
    - 布局配置
    """

    node_type = 'form_ui_design'
    node_name = '表单UI设计'
    node_category = 'form'
    node_icon = 'layout'
    node_description = '根据数据库表结构自动生成表单UI配置'

    # ========== 字段类型到组件的映射规则 ==========
    FIELD_TYPE_MAPPING = {
        # 字符串类型
        'varchar': {
            'default': 'input',
            'long_text_threshold': 200,  # 超过此长度使用 textarea
        },
        'char': {'default': 'input'},
        'text': {'default': 'textarea'},

        # 数字类型
        'int': {'default': 'input-number'},
        'integer': {'default': 'input-number'},
        'bigint': {'default': 'input-number'},
        'smallint': {'default': 'input-number'},

        # 小数类型
        'decimal': {'default': 'input-number'},
        'numeric': {'default': 'input-number'},
        'float': {'default': 'input-number'},
        'double': {'default': 'input-number'},

        # 日期时间类型
        'datetime': {'default': 'date', 'props': {'type': 'datetime', 'format': 'YYYY-MM-DD HH:mm:ss'}},
        'timestamp': {'default': 'date', 'props': {'type': 'datetime', 'format': 'YYYY-MM-DD HH:mm:ss'}},
        'date': {'default': 'date', 'props': {'type': 'date', 'format': 'YYYY-MM-DD'}},
        'time': {'default': 'time', 'props': {'format': 'HH:mm:ss'}},

        # 布尔类型
        'boolean': {'default': 'switch'},
        'bool': {'default': 'switch'},

        # JSON类型
        'json': {'default': 'textarea', 'props': {'rows': 6}},
        'jsonb': {'default': 'textarea', 'props': {'rows': 6}},
    }

    # ========== 字段名模式匹配规则 ==========
    FIELD_NAME_PATTERNS = [
        # 邮箱
        (r'(email|mail)', 'input', {'type': 'email'}),
        # 手机号
        (r'(phone|mobile|tel)', 'input', {'type': 'tel'}),
        # URL
        (r'(url|link|website)', 'input', {'type': 'url'}),
        # 密码
        (r'(password|pwd)', 'input', {'type': 'password', 'show-password': True}),
        # 颜色
        (r'(color|colour)$', 'color', {}),
        # 编码生成器
        (r'(code|no|number)$', 'code-generator', {}),
        # 长文本
        (r'(remark|note|memo)', 'textarea', {'rows': 4}),
        (r'(desc|description)', 'textarea', {'rows': 4}),
        (r'(content)', 'textarea', {'rows': 6}),
        (r'(address|addr)', 'textarea', {'rows': 3}),
        # 富文本
        (r'(html|rich_text|richtext)', 'rich-text', {}),
        # 用户选择器
        (r'(user|creator|modifier|operator)_id$', 'user-selector', {}),
        # 部门选择器
        (r'(dept|department)_id$', 'dept-selector', {}),
        # 角色选择器
        (r'(role)_id$', 'role-selector', {}),
        # 岗位选择器
        (r'(post|position)_id$', 'post-selector', {}),
        # 通用外键 - 下拉选择
        (r'_id$', 'select', {'filterable': True}),
        # 评分
        (r'(rate|rating|score)$', 'rate', {'max': 5}),
        # 百分比
        (r'(percent|percentage)$', 'slider', {'min': 0, 'max': 100}),
        # 排序
        (r'(sort|order|seq)$', 'input-number', {'min': 0, 'step': 1}),
        # 年龄
        (r'(age)$', 'input-number', {'min': 0, 'max': 150}),
        # 金额
        (r'(amount|price|money|fee|cost|salary|wage|budget)', 'money-input', {}),
        # 图片
        (r'(image|photo|picture|avatar|logo)', 'image-selector', {}),
        # 文件
        (r'(file|attachment|document)', 'file-selector', {}),
        # Cron表达式
        (r'(cron)', 'cron-selector', {}),
    ]

    # ========== 字段分组规则 ==========
    FIELD_GROUP_RULES = {
        'basic_info': {
            'label': '基本信息',
            'patterns': [r'^(name|title|code|no|type|category|status)'],
            'priority': 1,
            'collapsed': False,
        },
        'detail_info': {
            'label': '详细信息',
            'patterns': [r'(desc|description|remark|note|content|detail)'],
            'priority': 2,
            'collapsed': False,
        },
        'contact_info': {
            'label': '联系方式',
            'patterns': [r'(phone|mobile|tel|email|address|contact|wechat|qq)'],
            'priority': 3,
            'collapsed': False,
        },
        'financial_info': {
            'label': '金额信息',
            'patterns': [r'(amount|price|money|fee|cost|salary|wage|budget)'],
            'priority': 4,
            'collapsed': False,
        },
        'time_info': {
            'label': '时间信息',
            'patterns': [r'(date|time|datetime|start|end|begin|finish|deadline)'],
            'priority': 5,
            'collapsed': False,
        },
        'attachment_info': {
            'label': '附件信息',
            'patterns': [r'(file|image|photo|picture|attachment|document)'],
            'priority': 6,
            'collapsed': False,
        },
        'system_info': {
            'label': '系统信息',
            'patterns': [r'^sys_', r'^is_', r'(creator|modifier|create_time|update_time)'],
            'priority': 99,
            'collapsed': True,
        },
    }

    # 系统字段（默认隐藏）
    SYSTEM_FIELDS = [
        'id', 'sys_create_datetime', 'sys_update_datetime',
        'sys_creator_id', 'sys_modifier_id', 'sys_dept_id',
        'is_deleted', 'sort'
    ]

    inputs = [
        {
            'name': 'database_design',
            'type': 'object',
            'description': '数据库设计配置（来自数据库设计节点）',
            'required': True,
        },
        {
            'name': 'form_name',
            'type': 'string',
            'description': '表单名称',
            'required': False,
        },
        {
            'name': 'form_code',
            'type': 'string',
            'description': '表单编码',
            'required': False,
        },
    ]

    outputs = [
        {
            'name': 'form_ui_design',
            'type': 'object',
            'description': '表单UI设计配置',
        },
        {
            'name': 'form_code',
            'type': 'string',
            'description': '表单编码',
        },
        {
            'name': 'field_count',
            'type': 'number',
            'description': '字段数量',
        },
        {
            'name': 'group_count',
            'type': 'number',
            'description': '分组数量',
        },
    ]

    def execute(self, context: NodeContext) -> NodeResult:
        """执行节点"""
        try:
            # 检查是否有用户编辑的数据（从设计预览面板提交）
            user_input = context.variables.get('__user_input__')
            if user_input:
                edited_data = self._parse_user_edit(user_input)
                if edited_data:
                    logger.info(f'FormUIDesignNode - 使用用户编辑的数据')
                    context.variables.pop('__user_input__', None)
                    return self._build_result_from_edit(edited_data)

            # 获取配置
            database_design = resolve_object_config(
                context, self.config.get('database_design', '{}')
            )
            form_name = context.resolve_template(self.config.get('form_name', ''))
            form_code = context.resolve_template(self.config.get('form_code', ''))

            # 布局配置
            layout_mode = self.config.get('layout_mode', 'auto')
            label_width = self.config.get('label_width', 120)
            enable_grouping = self.config.get('enable_grouping', True)
            hide_system_fields = self.config.get('hide_system_fields', True)

            logger.info(f'FormUIDesignNode - 开始生成表单UI配置')

            # 解析数据库设计
            if not database_design:
                return NodeResult(
                    success=False,
                    error='数据库设计配置解析失败或为空',
                )

            # 获取表信息
            table_info = database_design.get('table', {})
            table_name = table_info.get('tableName', '')
            fields = table_info.get('fields', [])

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

            if not fields:
                return NodeResult(
                    success=False,
                    error='字段列表不能为空',
                )

            # 使用表名作为默认表单编码
            if not form_code:
                form_code = table_name
            if not form_name:
                form_name = table_info.get('alias', table_name)

            # 生成表单项
            form_items = []
            for field in fields:
                field_name = field.get('name', '')

                # 跳过系统字段
                if hide_system_fields and field_name in self.SYSTEM_FIELDS:
                    continue

                # 生成表单项配置
                form_item = self._generate_form_item(field)
                if form_item:
                    form_items.append(form_item)

            # 计算布局 - 默认使用双列布局
            col_span = self._calculate_col_span(len(form_items), layout_mode)
            for item in form_items:
                if 'colSpan' not in item or item.get('colSpan') == 12:
                    # 只更新默认值，保留特殊组件的全宽设置
                    if item.get('type') not in ['textarea', 'rich-text', 'sub-table']:
                        item['colSpan'] = col_span

            # 将所有字段包裹在栅格布局容器中（默认两列）
            grid_layout_item = {
                'id': str(uuid.uuid4()).replace('-', ''),
                'type': 'grid-layout',
                'label': '',
                'props': {
                    'columns': 2,  # 默认两列
                    'gap': 16,
                },
                'children': form_items,
                'colSpan': 24,  # 栅格容器占满整行
            }

            # 用栅格容器替换原有的扁平列表
            wrapped_items = [grid_layout_item]

            # 分组处理
            if enable_grouping:
                grouped_items = self._group_fields(form_items)
            else:
                grouped_items = [{
                    'title': '',
                    'collapsed': False,
                    'fields': form_items,
                }]

            # 构建表单UI配置
            form_ui_design = {
                'formCode': form_code,
                'formName': form_name,
                'tableName': table_name,
                'layout': {
                    'mode': layout_mode,
                    'labelWidth': label_width,
                    'labelPosition': 'right',
                    'size': 'default',
                    'colSpan': col_span,
                },
                'groups': grouped_items,
                'items': wrapped_items,  # 使用包裹了栅格布局的表单项
                'tableConfigs': [],  # 表单设计器需要的表配置
                'dbConfig': database_design.get('dbConfig', 'default'),
            }

            field_count = len(form_items)
            group_count = len([g for g in grouped_items if g.get('fields')])

            logger.info(f'FormUIDesignNode - 表单UI配置生成完成: {form_code}, 字段数: {field_count}, 分组数: {group_count}')

            # 构建 table_configs（供前端表单设计组件使用）
            table_configs = [{
                'id': 'main-table',
                'type': 'main',
                'tableName': table_name,
                'alias': table_info.get('alias', table_name),
                'fields': fields,
                'meta': {
                    'schema': table_info.get('schema', 'public'),
                    'database': table_info.get('database', ''),
                },
            }]

            # 检查是否需要确认（支持布尔值、字符串模式和变量引用）
            require_confirmation = self.resolve_require_confirmation(context, default=True)

            # 构建预览数据（包含 table_configs 供前端表单设计组件使用）
            preview_data = {
                'type': 'form_ui_design',
                'title': '表单UI设计',
                'data': form_ui_design,
                'table_configs': table_configs,
                'editable': True,
            } if require_confirmation else None

            return NodeResult(
                success=True,
                output=form_ui_design,
                output_variables={
                    'form_ui_design': form_ui_design,
                    'form_code': form_code,
                    'field_count': field_count,
                    'group_count': group_count,
                    'table_configs': table_configs,
                },
                preview=preview_data,
                waiting_for_input=require_confirmation,
                waiting_config={
                    'type': 'design_preview',
                    'preview_type': 'form_ui_design',
                    'title': '表单UI设计',
                    'message': '请确认或编辑表单UI设计',
                    'data': form_ui_design,
                    'table_configs': table_configs,
                } if require_confirmation else {},
            )

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

    async def execute_async(self, context: NodeContext) -> NodeResult:
        """异步执行节点（直接调用同步方法）"""
        return self.execute(context)

    def _parse_user_edit(self, user_input: Any) -> Optional[Dict[str, Any]]:
        """解析用户编辑的数据"""
        if isinstance(user_input, dict):
            if 'items' in user_input or 'groups' in user_input:
                return user_input
            return None

        if isinstance(user_input, str):
            try:
                data = json.loads(user_input)
                if isinstance(data, dict) and ('items' in data or 'groups' in data):
                    return data
            except (json.JSONDecodeError, TypeError):
                pass

        return None

    def _build_result_from_edit(self, edited_data: Dict[str, Any]) -> NodeResult:
        """从用户编辑的数据构建节点结果"""
        form_code = edited_data.get('formCode', '')
        items = edited_data.get('items', [])
        groups = edited_data.get('groups', [])

        return NodeResult(
            success=True,
            output=edited_data,
            output_variables={
                'form_ui_design': edited_data,
                'form_code': form_code,
                'field_count': len(items),
                'group_count': len([g for g in groups if g.get('fields')]),
            },
        )

    def _parse_database_design(self, design_str: Any) -> Optional[Dict]:
        """解析数据库设计配置"""
        if isinstance(design_str, dict):
            return design_str

        if isinstance(design_str, str):
            design_str = design_str.strip()
            if not design_str or design_str == '{}':
                return None

            try:
                return json.loads(design_str)
            except json.JSONDecodeError:
                import ast
                try:
                    return ast.literal_eval(design_str)
                except (ValueError, SyntaxError):
                    return None

        return None

    def _generate_form_item(self, field: Dict) -> Optional[Dict]:
        """生成单个表单项配置"""
        field_name = field.get('name', '')
        field_type = field.get('type', 'varchar').lower()
        comment = field.get('comment', field_name)
        nullable = field.get('nullable', True)
        max_length = field.get('maxLength')

        if not field_name:
            return None

        # 确定组件类型和属性
        component, props = self._infer_component(field_name, field_type, field)

        # 生成验证规则
        rules = self._infer_validation_rules(field, component)

        # 生成布局配置
        layout = self._infer_layout(field_name, component)

        # 构建表单项
        form_item = {
            'id': str(uuid.uuid4()).replace('-', ''),
            'type': component,
            'field': field_name,
            'label': comment,
            'props': props,
            'rules': rules,
            'colSpan': layout.get('colSpan', 12),
            'order': layout.get('order', 0),
        }

        # 添加选项配置（如果需要）
        if component in ['select', 'radio', 'checkbox']:
            form_item['options'] = []
            form_item['dataSource'] = self._infer_data_source(field_name)

        return form_item

    def _infer_component(self, field_name: str, field_type: str, field: Dict) -> Tuple[str, Dict]:
        """推断组件类型和属性"""
        props = {}
        component = 'input'  # 默认组件

        # 1. 先根据字段名模式匹配
        field_name_lower = field_name.lower()
        for pattern, comp, pattern_props in self.FIELD_NAME_PATTERNS:
            if re.search(pattern, field_name_lower):
                component = comp
                props.update(pattern_props)
                break
        else:
            # 2. 如果没有匹配到模式，根据字段类型映射
            type_config = self.FIELD_TYPE_MAPPING.get(field_type, {'default': 'input'})
            component = type_config.get('default', 'input')

            # 添加类型默认属性
            if 'props' in type_config:
                props.update(type_config['props'])

            # 特殊处理：varchar 长度判断
            if field_type == 'varchar':
                max_length = field.get('maxLength', 255)
                # 确保 max_length 是整数
                try:
                    max_length = int(max_length) if max_length else 255
                except (ValueError, TypeError):
                    max_length = 255
                threshold = type_config.get('long_text_threshold', 200)
                if max_length > threshold:
                    component = 'textarea'
                    props['rows'] = 4

        # 3. 添加通用属性
        props = self._add_common_props(props, field, component)

        return component, props

    def _add_common_props(self, props: Dict, field: Dict, component: str) -> Dict:
        """添加通用组件属性"""
        field_name = field.get('name', '')
        comment = field.get('comment', field_name)
        max_length = field.get('maxLength')
        # 确保 max_length 是整数
        if max_length:
            try:
                max_length = int(max_length)
            except (ValueError, TypeError):
                max_length = None

        # 占位符
        if component in ['input', 'textarea']:
            props.setdefault('placeholder', f'请输入{comment}')
        elif component in ['select', 'cascader', 'tree-select', 'user-selector', 'dept-selector', 'role-selector', 'post-selector']:
            props.setdefault('placeholder', f'请选择{comment}')
        elif component == 'date':
            props.setdefault('placeholder', f'请选择{comment}')

        # 可清空
        props.setdefault('clearable', True)

        # 字符串长度限制
        if max_length and component in ['input', 'textarea']:
            props['maxlength'] = max_length
            props['show-word-limit'] = True

        # textarea 行数
        if component == 'textarea':
            props.setdefault('rows', 4)

        # 数字输入框
        if component == 'input-number':
            props.setdefault('controls-position', 'right')
            # 小数精度
            if field.get('type') in ['decimal', 'numeric', 'float', 'double']:
                scale = field.get('scale', 2)
                props.setdefault('precision', scale)
                props.setdefault('step', 10 ** (-scale))
            else:
                props.setdefault('step', 1)

        # 下拉选择
        if component == 'select':
            props.setdefault('filterable', True)

        # 开关
        if component == 'switch':
            props.setdefault('active-text', '是')
            props.setdefault('inactive-text', '否')

        return props

    def _infer_validation_rules(self, field: Dict, component: str) -> List[Dict]:
        """推断验证规则"""
        rules = []
        field_name = field.get('name', '').lower()
        field_type = field.get('type', '')
        nullable = field.get('nullable', True)
        max_length = field.get('maxLength')
        # 确保 max_length 是整数
        if max_length:
            try:
                max_length = int(max_length)
            except (ValueError, TypeError):
                max_length = None
        comment = field.get('comment', field_name)

        # 必填规则
        if not nullable:
            rules.append({
                'required': True,
                'message': f'{comment}不能为空',
                'trigger': 'blur' if component in ['input', 'textarea'] else 'change',
            })

        # 长度规则
        if max_length and field_type in ['varchar', 'char']:
            rules.append({
                'max': max_length,
                'message': f'最多{max_length}个字符',
                'trigger': 'blur',
            })

        # 格式规则
        if 'email' in field_name or 'mail' in field_name:
            rules.append({
                'type': 'email',
                'message': '请输入正确的邮箱格式',
                'trigger': 'blur',
            })

        if 'phone' in field_name or 'mobile' in field_name:
            rules.append({
                'pattern': r'^1[3-9]\d{9}$',
                'message': '请输入正确的手机号码',
                'trigger': 'blur',
            })

        if 'url' in field_name or 'link' in field_name:
            rules.append({
                'type': 'url',
                'message': '请输入正确的URL格式',
                'trigger': 'blur',
            })

        return rules

    def _infer_layout(self, field_name: str, component: str) -> Dict:
        """推断布局配置"""
        layout = {
            'colSpan': 12,  # 默认占一半宽度
            'order': 0,
        }

        field_name_lower = field_name.lower()

        # 全宽组件
        if component in ['textarea', 'rich-text', 'sub-table', 'divider']:
            layout['colSpan'] = 24

        # 小组件
        elif component in ['switch', 'rate']:
            layout['colSpan'] = 8

        # 根据字段名调整
        if any(kw in field_name_lower for kw in ['remark', 'note', 'description', 'content', 'address']):
            layout['colSpan'] = 24

        return layout

    def _calculate_col_span(self, field_count: int, layout_mode: str) -> int:
        """
        根据字段数量计算列宽

        规则：
        - 字段数 <= 6: 单列布局 (colSpan=24)
        - 字段数 7-12: 双列布局 (colSpan=12)
        - 字段数 > 12: 三列布局 (colSpan=8)
        - 最多三列
        """
        if layout_mode == 'single':
            return 24
        elif layout_mode == 'double':
            return 12
        elif layout_mode == 'triple':
            return 8
        else:  # auto
            if field_count <= 6:
                return 24  # 单列
            elif field_count <= 12:
                return 12  # 双列
            else:
                return 8   # 三列（最多）

    def _infer_data_source(self, field_name: str) -> Optional[Dict]:
        """推断数据来源配置"""
        field_name_lower = field_name.lower()

        # 外键字段
        if field_name_lower.endswith('_id'):
            table_name = field_name_lower[:-3]

            # 特殊业务字段
            if 'user' in table_name:
                return {
                    'type': 'api',
                    'apiUrl': '/api/v1/system/users',
                    'labelField': 'name',
                    'valueField': 'id',
                }
            elif 'dept' in table_name or 'department' in table_name:
                return {
                    'type': 'api',
                    'apiUrl': '/api/v1/system/departments',
                    'labelField': 'name',
                    'valueField': 'id',
                }
            elif 'role' in table_name:
                return {
                    'type': 'api',
                    'apiUrl': '/api/v1/system/roles',
                    'labelField': 'name',
                    'valueField': 'id',
                }

        # 枚举类型字段
        if 'status' in field_name_lower or 'type' in field_name_lower or 'category' in field_name_lower:
            return {
                'type': 'dict',
                'dictCode': f'{field_name_lower}_dict',
            }

        return None

    def _group_fields(self, form_items: List[Dict]) -> List[Dict]:
        """将表单项分组"""
        groups = {}
        ungrouped = []

        for item in form_items:
            field_name = item.get('field', '').lower()
            group_key = self._match_group(field_name)

            if group_key:
                if group_key not in groups:
                    group_config = self.FIELD_GROUP_RULES.get(group_key, {})
                    groups[group_key] = {
                        'key': group_key,
                        'title': group_config.get('label', group_key),
                        'priority': group_config.get('priority', 50),
                        'collapsed': group_config.get('collapsed', False),
                        'fields': [],
                    }
                groups[group_key]['fields'].append(item)
            else:
                ungrouped.append(item)

        # 将未分组的字段放入"其他信息"组
        if ungrouped:
            groups['other_info'] = {
                'key': 'other_info',
                'title': '其他信息',
                'priority': 50,
                'collapsed': False,
                'fields': ungrouped,
            }

        # 按优先级排序
        sorted_groups = sorted(groups.values(), key=lambda g: g.get('priority', 50))

        # 移除空组
        return [g for g in sorted_groups if g.get('fields')]

    def _match_group(self, field_name: str) -> Optional[str]:
        """匹配字段所属分组"""
        for group_key, group_config in self.FIELD_GROUP_RULES.items():
            patterns = group_config.get('patterns', [])
            for pattern in patterns:
                if re.search(pattern, field_name):
                    return group_key
        return None

    @classmethod
    def get_config_schema(cls) -> Dict[str, Any]:
        """获取节点配置 Schema"""
        return {
            'type': 'object',
            'properties': {
                'database_design': {
                    'type': 'string',
                    'title': '数据库设计配置',
                    'description': '来自数据库设计节点的输出',
                    'x-component': 'SmartInput',
                },
                'form_name': {
                    'type': 'string',
                    'title': '表单名称',
                    'description': '表单显示名称，不填则使用表别名',
                    'x-component': 'SmartInput',
                },
                'form_code': {
                    'type': 'string',
                    'title': '表单编码',
                    'description': '表单唯一编码，不填则使用表名',
                    'x-component': 'SmartInput',
                },
                'layout_mode': {
                    'type': 'string',
                    'title': '布局模式',
                    'description': '表单布局模式',
                    'default': 'auto',
                    'enum': ['auto', 'single', 'double', 'triple'],
                    'enumNames': ['自动', '单列', '双列', '三列'],
                    'x-component': 'Select',
                },
                'label_width': {
                    'type': 'number',
                    'title': '标签宽度',
                    'description': '表单标签宽度（像素）',
                    'default': 120,
                    'x-component': 'InputNumber',
                },
                'enable_grouping': {
                    'type': 'boolean',
                    'title': '启用分组',
                    'description': '是否按字段类型自动分组',
                    'default': True,
                    'x-component': 'Switch',
                },
                'hide_system_fields': {
                    'type': 'boolean',
                    'title': '隐藏系统字段',
                    'description': '是否隐藏系统字段（id, sys_*等）',
                    'default': True,
                    'x-component': 'Switch',
                },
                'require_confirmation': {
                    'type': 'boolean',
                    'title': '需要确认',
                    'description': '设计完成后是否暂停等待用户确认或编辑',
                    'default': True,
                    'x-component': 'Switch',
                },
            },
            'required': ['database_design'],
        }
