/*
 * @Author: ZhaoYing 
 * @Date: 2026-02-03 15:39:59 
 * @Last Modified by: ZhaoYing
 * @Last Modified time: 2026-03-16 16:11:28
 */
import { type FC, useEffect, useState, useMemo } from "react";
import clsx from 'clsx'
import { useTranslation } from 'react-i18next'
import { Graph, Node } from '@antv/x6';
import { Form, Input, Select, InputNumber, Switch, Divider, Space, Button } from 'antd'
import { CaretDownOutlined, CaretRightOutlined } from '@ant-design/icons';

import type { NodeConfig, NodeProperties, ChatVariable } from '../../types'
import Empty from '@/components/Empty';
import emptyIcon from '@/assets/images/workflow/empty.png'
import CustomSelect from "@/components/CustomSelect";
import MessageEditor from './MessageEditor'
import Knowledge from './Knowledge/Knowledge';
import type { Suggestion } from '../Editor/plugin/AutocompletePlugin'
import VariableSelect from './VariableSelect';
import ParamsList from './ParamsList';
import GroupVariableList from './GroupVariableList'
import CaseList from './CaseList'
import HttpRequest from './HttpRequest';
import CategoryList from './CategoryList'
import ConditionList from './ConditionList'
import CycleVarsList from './CycleVarsList'
import AssignmentList from './AssignmentList'
import ToolConfig from './ToolConfig'
import MemoryConfig from './MemoryConfig'
import VariableList from './VariableList'
import { useVariableList, getCurrentNodeVariables, getChildNodeVariables } from './hooks/useVariableList'
import styles from './properties.module.css'
import Editor, { type LexicalEditorProps } from "../Editor";
import RbSlider from './RbSlider'
import JinjaRender from './JinjaRender'
import CodeExecution from './CodeExecution'
import { nodeLibrary } from '../../constant';

/**
 * Props for Properties component
 */
interface PropertiesProps {
  /** Currently selected node */
  selectedNode?: Node | null; 
  /** Function to update selected node */
  setSelectedNode: (node: Node | null) => void;
  /** Reference to graph instance */
  graphRef: React.MutableRefObject<Graph | undefined>;
  /** Handler for blank canvas click */
  blankClick: () => void;
  /** Handler for delete event */
  deleteEvent: () => void;
  /** Handler for copy event */
  copyEvent: () => void;
  /** Handler for paste event */
  parseEvent: () => void;
  /** Workflow configuration */
  config?: any;
  /** Chat variables */
  chatVariables: ChatVariable[];
}

/**
 * Properties panel component
 * Displays and manages configuration for selected workflow node
 * @param props - Component props
 */
const Properties: FC<PropertiesProps> = ({
  selectedNode,
  graphRef,
  chatVariables,
  blankClick
}) => {
  const { t } = useTranslation()
  const [form] = Form.useForm<NodeConfig>();
  const [configs, setConfigs] = useState<Record<string,NodeConfig>>({} as Record<string,NodeConfig>)
  const values = Form.useWatch([], form);
  const variableList = useVariableList(selectedNode, graphRef, chatVariables)

  useEffect(() => {
    if (selectedNode?.getData()?.id) {
      setOutputCollapsed(true)
    }
    form.resetFields()
  }, [selectedNode?.getData()?.id])

  useEffect(() => {
    if (selectedNode && form) {
      const { type = 'default', name = '', config, id } = selectedNode.getData() || {}
      const initialValue: Record<string, any> = {}
      Object.keys(config || {}).forEach(key => {
        if (config && config[key] && 'defaultValue' in config[key]) {
          initialValue[key] = config[key].defaultValue
        }
      })

      form.setFieldsValue({
        type,
        id,
        name,
        ...initialValue,
      })
      setConfigs(config || {})
    } else {
      form.resetFields()
    }
  }, [selectedNode, form])

  /**
   * Update node label in graph
   * @param newLabel - New label text
   */
  const updateNodeLabel = (newLabel: string) => {
    if (selectedNode && form) {
      const nodeData = selectedNode.getData() as NodeProperties;
      selectedNode.setAttrByPath('text/text', `${nodeData.icon} ${newLabel}`);
      selectedNode.setData({ ...selectedNode.getData(), name: newLabel });
    }
  };

  useEffect(() => {
    if (values && selectedNode) {
      const { id, knowledge_retrieval, group, group_variables, ...rest } = values
      const { knowledge_bases = [], name: _name, description: _description, ...restKnowledgeConfig } = (knowledge_retrieval as any) || {}

      let allRest = {
        ...rest,
        ...restKnowledgeConfig,
      }
      if (knowledge_bases?.length) {
        allRest.knowledge_bases = knowledge_bases?.map((vo: any) => ({
          id: vo.id,
          ...vo.config
        }))
      }

      const nodeData = selectedNode.getData()

      Object.keys(values).forEach(key => {
        if (nodeData?.config?.[key]) {
          // Create a deep copy to avoid reference sharing between nodes
          if (!nodeData.config[key]) {
            nodeData.config[key] = {};
          }
          nodeData.config[key] = {
            ...nodeData.config[key],
            defaultValue: values[key]
          };
        }
      })

      selectedNode?.setData({
        ...nodeData,
        ...allRest,
      })
    }
  }, [values, selectedNode, form])



  /**
   * Get filtered variable list based on node type and config key
   * @param nodeType - Type of the node
   * @param key - Configuration key
   * @returns Filtered variable list
   */
  const getFilteredVariableList = (nodeType?: string, key?: string) => {
    // Check if current node is a child of iteration node
    const parentIterationNode = selectedNode ? (() => {
      const nodes = graphRef.current?.getNodes() || [];
      const nodeData = selectedNode.getData();
      const cycle = nodeData?.cycle;
      
      if (cycle) {
        const parentNode = nodes.find(n => n.getData().id === cycle);
        if (parentNode) {
          const parentData = parentNode.getData();
          if (parentData?.type === 'iteration') {
            return parentNode;
          }
        }
      }
      return null;
    })() : null;

    // Helper function to add parent iteration variables
    const addParentIterationVars = (filteredList: any[]) => {
      if (parentIterationNode) {
        const parentData = parentIterationNode.getData();
        const parentNodeId = parentData.id;
        
        if (parentData.config?.input?.defaultValue) {
          const itemKey = `${parentNodeId}_item`;
          const indexKey = `${parentNodeId}_index`;
          
          const existingItemVar = filteredList.find(v => v.key === itemKey);
          const existingIndexVar = filteredList.find(v => v.key === indexKey);
          
          if (!existingItemVar) {
            // Determine item dataType from input variable
            let itemDataType = 'object';
            const inputVariable = variableList.find(v => `{{${v.value}}}` === parentData.config.input.defaultValue);
            if (inputVariable && inputVariable.dataType.startsWith('array[')) {
              itemDataType = inputVariable.dataType.replace(/^array\[(.+)\]$/, '$1');
            }
            
            filteredList.push({
              key: itemKey,
              label: 'item',
              type: 'variable',
              dataType: itemDataType,
              value: `${parentNodeId}.item`,
              nodeData: parentData,
            });
          }
          
          if (!existingIndexVar) {
            filteredList.push({
              key: indexKey,
              label: 'index',
              type: 'variable',
              dataType: 'number',
              value: `${parentNodeId}.index`,
              nodeData: parentData,
            });
          }
        }
      }
      return filteredList;
    };

    if (nodeType === 'llm') {
      // For LLM nodes that are children of iteration or loop nodes, include parent variables
      const parentLoopNode = selectedNode ? (() => {
        const nodes = graphRef.current?.getNodes() || [];
        const nodeData = selectedNode.getData();
        const cycle = nodeData?.cycle;
        
        if (cycle) {
          const parentNode = nodes.find(n => n.getData().id === cycle);
          if (parentNode) {
            const parentData = parentNode.getData();
            if (parentData?.type === 'loop' || parentData?.type === 'iteration') {
              return parentNode;
            }
          }
        }
        return null;
      })() : null;
      
      let filteredList = variableList.filter(variable => variable.dataType !== 'boolean');
      
      // If this LLM node is a child of iteration/loop, ensure parent variables are included
      if (parentLoopNode) {
        const parentData = parentLoopNode.getData();
        const parentNodeId = parentData.id;
        
        // Ensure parent loop/iteration variables are included
        if (parentData.type === 'loop') {
          const cycleVars = parentData.cycle_vars || [];
          cycleVars.forEach((cycleVar: any) => {
            const key = `${parentNodeId}_cycle_${cycleVar.name}`;
            const existingVar = filteredList.find(v => v.key === key);
            if (!existingVar && cycleVar.name && cycleVar.type !== 'boolean') {
              filteredList.push({
                key,
                label: cycleVar.name,
                type: 'variable',
                dataType: cycleVar.type || 'String',
                value: `${parentNodeId}.${cycleVar.name}`,
                nodeData: parentData,
              });
            }
          });
        } else if (parentData.type === 'iteration') {
          // Add item and index variables for iteration parent
          if (parentData.config?.input?.defaultValue) {
            const itemKey = `${parentNodeId}_item`;
            const indexKey = `${parentNodeId}_index`;
            
            const existingItemVar = filteredList.find(v => v.key === itemKey);
            const existingIndexVar = filteredList.find(v => v.key === indexKey);
            
            if (!existingItemVar) {
              // Determine item dataType from input variable
              let itemDataType = 'object';
              const inputVariable = variableList.find(v => `{{${v.value}}}` === parentData.config.input.defaultValue);
              if (inputVariable && inputVariable.dataType.startsWith('array[')) {
                itemDataType = inputVariable.dataType.replace(/^array\[(.+)\]$/, '$1');
              }
              
              filteredList.push({
                key: itemKey,
                label: 'item',
                type: 'variable',
                dataType: itemDataType,
                value: `${parentNodeId}.item`,
                nodeData: parentData,
              });
            }
            
            if (!existingIndexVar) {
              filteredList.push({
                key: indexKey,
                label: 'index',
                type: 'variable',
                dataType: 'Number',
                value: `${parentNodeId}.index`,
                nodeData: parentData,
              });
            }
          }
        }
      }
      
      return filteredList;
    }
    if (nodeType === 'knowledge-retrieval' || nodeType === 'parameter-extractor' && key !== 'prompt' || nodeType === 'memory-read' || nodeType === 'memory-write' || nodeType === 'question-classifier') {
      let filteredList = addParentIterationVars(variableList).filter(variable => variable.dataType === 'string');
      return filteredList;
    }
    if (nodeType === 'parameter-extractor' && key === 'prompt') {
      let filteredList = addParentIterationVars(variableList).filter(variable => variable.dataType === 'string' || variable.dataType === 'number');
      return filteredList;
    }
    if (nodeType === 'iteration' && key === 'output' || nodeType === 'loop' && key === 'condition') {
      if (!selectedNode) return [];
      let filteredList = nodeType === 'iteration' 
        ? variableList.filter(variable => variable.value.includes('sys.')) 
        : addParentIterationVars(variableList).filter(variable => variable.nodeData.type !== 'loop');
      
      const childVariables = getChildNodeVariables(selectedNode, graphRef);
      const existingKeys = new Set(filteredList.map(v => v.key));
      childVariables.forEach(v => {
        if (!existingKeys.has(v.key)) {
          filteredList.push(v);
          existingKeys.add(v.key);
        }
      });
      
      return filteredList;
    }
    if (nodeType === 'iteration') {
      return variableList.filter(variable => variable.dataType.includes('array'));
    }
    
    // For all other node types, add parent iteration variables if applicable
    let baseList = variableList;
    return addParentIterationVars(baseList);
  };

  // const defaultVariableList = calculateVariableList(selectedNode as Node, graphRef, workflowConfig )

  console.log('values', values)

  /**
   * Get current node output variables
   */
  const currentNodeVariables = useMemo(() => {
    if (!selectedNode) return []
    return getCurrentNodeVariables(selectedNode?.getData(), values)
  }, [selectedNode?.getData(), values])

  const [outputCollapsed, setOutputCollapsed] = useState(true)
  /**
   * Toggle output section collapsed state
   */
  const handleToggle = () => {
    setOutputCollapsed((prev: boolean) => !prev)
  }

  /**
   * Handle variable list change and update output type for iteration nodes
   * @param _value - Selected value
   * @param option - Selected option
   * @param key - Configuration key
   */
  const handleChangeVariableList = (_value: string, option: any, key: string) => {
    if (selectedNode?.data?.type === 'iteration' && key === 'output') {
      form.setFieldValue('output_type', option?.dataType)
    }
  }
  console.log('variableList', variableList, currentNodeVariables)
  const handleSureReplace = () => {
    const { replaceNode } = values;
    const nodeLibraryConfig = [...nodeLibrary]
          .flatMap(category => category.nodes)
          .find(n => n.type === replaceNode)

    if (replaceNode && nodeLibraryConfig) {
      // Preserve existing config values when switching node types
      const currentData = selectedNode?.data || {};
      const currentConfig = currentData.config || {};
      const newConfig = nodeLibraryConfig.config || {};
      
      // Merge configs: keep existing values for matching keys, add new keys from template
      const mergedConfig: Record<string, any> = {};
      Object.keys(newConfig).forEach(key => {
        if (currentConfig[key] && currentConfig[key].defaultValue !== undefined) {
          // Preserve existing value if it exists
          mergedConfig[key] = {
            ...newConfig[key],
            defaultValue: currentConfig[key].defaultValue
          };
        } else {
          // Use new config template
          mergedConfig[key] = { ...newConfig[key] };
        }
      });

      selectedNode?.setData({
        ...currentData,
        ...nodeLibraryConfig,
        config: mergedConfig
      })
      blankClick()
    }
  }

  return (
    <div className={clsx("rb:w-75 rb:fixed rb:right-0 rb:top-16 rb:bottom-0 rb:p-3 rb:pb-6", styles.properties)}>
      <div className="rb:font-medium rb:leading-5 rb:pb-3 rb:mb-3 rb:border-b rb:border-b-[#DFE4ED]">{t('workflow.nodeProperties')}</div>
      {!selectedNode
        ? <Empty url={emptyIcon} size={140} className="rb:h-full rb:mx-15" title={t('workflow.empty')} />
        : <div className="rb:h-[calc(100%-20px)] rb:overflow-x-hidden rb:overflow-y-auto">
        <Form form={form} size="small" layout="vertical">
          <Form.Item name="name" label={t('workflow.nodeName')}>
            <Input
              placeholder={t('common.pleaseEnter')}
              onChange={(e) => {
                updateNodeLabel(e.target.value);
              }}
            />
          </Form.Item>
          <Form.Item name="id" label="ID">
            <Input disabled />
          </Form.Item>
          {selectedNode?.data?.type === 'unknown'
            ? <>
              <Form.Item name="replaceNode" label={t('workflow.config.unknown.replaceNodeType')}>
                <Select
                  options={nodeLibrary.map(category => ({
                    label: t(`workflow.${category.category}`),
                    options: category.nodes.filter(item => !['cycle-start', 'break'].includes(item.type)).map(node => ({
                      label: <div className="rb:flex rb:items-center rb:gap-2 rb:flex-1">
                        <img src={node.icon} className="rb:size-3.5" />
                        <div className="rb:wrap-break-word rb:line-clamp-1">{t(`workflow.${node.type}`)}</div>
                      </div>,
                      value: node.type
                    }))
                  }))}
                  placeholder={t('common.pleaseSelect')}
                  allowClear
                />
              </Form.Item>
              <Button type="primary" size="small" className="rb:text-[12px]!" onClick={handleSureReplace}>{t('workflow.sureReplace')}</Button>
            </>
            : selectedNode?.data?.type === 'http-request'
            ? <HttpRequest 
                options={variableList} 
                selectedNode={selectedNode}
                graphRef={graphRef}
              />
            : selectedNode?.data?.type === 'tool'
            ? <ToolConfig options={variableList} />
            : selectedNode?.data?.type === 'jinja-render'
            ? <JinjaRender
              selectedNode={selectedNode}
              options={getFilteredVariableList(selectedNode?.data?.type, 'mapping')}
              templateOptions={getFilteredVariableList(selectedNode?.data?.type, 'template')}
            />
            : selectedNode?.data?.type === 'code'
            ? <CodeExecution
              selectedNode={selectedNode}
              options={getFilteredVariableList(selectedNode?.data?.type, 'mapping')}
            />
            : configs && Object.keys(configs).length > 0 && Object.keys(configs).map((key) => {
              const config = configs[key] || {}

              if (config.dependsOn && (values as any)?.[config.dependsOn as string] !== config.dependsOnValue) {
                return null
              }

              if (selectedNode?.data?.type === 'start' && key === 'variables' && config.type === 'define') {
                return (
                  <Form.Item key={key} name={key}>
                    <VariableList
                      parentName={key}
                      selectedNode={selectedNode}
                      config={config}
                    />
                  </Form.Item>
                )
              }

              if (selectedNode?.data?.type === 'llm' && key === 'messages' && config.type === 'define') {
                // 为llm节点且isArray=true时添加context变量支持
                let contextVariableList = [...getFilteredVariableList('llm')];
                const isArrayMode = config.isArray !== false; // 默认为true
                
                if (isArrayMode) {
                  const contextKey = `${selectedNode.id}_context`;
                  const hasContextVariable = contextVariableList.some(v => v.key === contextKey);
                  
                  if (!hasContextVariable) {
                    contextVariableList.unshift({
                      key: contextKey,
                      label: 'context',
                      type: 'variable',
                      dataType: 'String',
                      value: `context`,
                      nodeData: selectedNode.getData(),
                      isContext: true,
                    });
                  }
                }
                return (
                  <Form.Item key={key} name={key}>
                    <MessageEditor
                      key={key}
                      options={contextVariableList.filter(variable => variable.nodeData?.type !== 'knowledge-retrieval')} 
                      parentName={key}
                      placeholder={t(config.placeholder || 'common.pleaseSelect')}
                      size="small"
                    />
                  </Form.Item>
                )
              }
              if (selectedNode?.data?.type === 'iteration' && key === 'output_type') {
                return (<Form.Item key={key} name={key} hidden />)
              }
              if (config.type === 'define') {
                return null
              }

              if (config.type === 'knowledge') {
                return (
                  <Form.Item
                    key={key}
                    name={key}
                  >
                    <Knowledge />
                  </Form.Item>
                )
              }

              if (config.type === 'messageEditor') {
                return (
                  <Form.Item key={key} name={key} label={selectedNode?.data?.type === 'memory-write' ? t(`workflow.config.${selectedNode?.data?.type}.${key}`) : undefined }>
                    <MessageEditor 
                      title={t(`workflow.config.${selectedNode?.data?.type}.${key}`)}
                      isArray={!!config.isArray} 
                      parentName={key}
                      language={config.language as LexicalEditorProps['language']}
                      options={getFilteredVariableList(selectedNode?.data?.type, key)}
                      titleVariant={config.titleVariant}
                      size="small"
                    />
                  </Form.Item>
                )
              }

              if (config.type === 'paramList') {
                return (
                  <Form.Item key={key} name={key}>
                    <ParamsList
                      label={t(`workflow.config.${selectedNode?.data?.type}.${key}`)}
                    />
                  </Form.Item>
                
                )
              }
              if (config.type === 'groupVariableList') {
                return (
                  <Form.Item key={key} name={key}>
                    <GroupVariableList
                      name={key}
                      options={getFilteredVariableList(selectedNode?.data?.type, key)}
                      isCanAdd={!!(values as any)?.group}
                      size="small"
                    />
                  </Form.Item>
                )
              }
              if (config.type === 'caseList') {
                return (
                  <Form.Item key={key} name={key}>
                    <CaseList
                      name={key}
                      options={getFilteredVariableList(selectedNode?.data?.type, key)}
                      selectedNode={selectedNode}
                      graphRef={graphRef}
                    />
                  </Form.Item>
                )
              }
              if (config.type === 'cycleVarsList') {
                return (
                  <Form.Item key={key} name={key}>
                    <CycleVarsList
                      size="small"
                      parentName={key}
                      options={getFilteredVariableList(selectedNode?.data?.type, key)}
                    />
                  </Form.Item>
                )
              }
              if (config.type === 'assignmentList') {
                return (
                  <Form.Item key={key} name={key}>
                    <AssignmentList
                      parentName={key}
                      options={(() => {
                        if (config.filterLoopIterationVars) {
                          const loopIterationVars: Suggestion[] = [];
                          
                          return [...getFilteredVariableList(selectedNode?.data?.type, key), ...loopIterationVars];
                        }
                        return getFilteredVariableList(selectedNode?.data?.type, key);
                      })()
                    }
                  />
                  </Form.Item>
                )
              }
              if (config.type === 'memoryConfig') {
                return (
                  <Form.Item
                    key={key}
                    name={key}
                    noStyle
                  >
                    <MemoryConfig
                      parentName={key}
                      options={getFilteredVariableList('llm')}
                    />
                  </Form.Item>
                )
              }
              if (config.type === 'conditionList') {
                return (
                  <Form.Item
                    key={key}
                    name={key}
                    noStyle
                  >
                    <ConditionList
                      parentName={key}
                      options={(() => {
                        const cycleVars = values?.cycle_vars || [];
                        const cycleVarSuggestions: Suggestion[] = cycleVars.filter(vo => vo.name && vo.name.trim() !== '').map((cycleVar: any) => ({
                          key: `${selectedNode.id}_cycle_${cycleVar.name}`,
                          label: cycleVar.name,
                          type: 'variable',
                          dataType: cycleVar.type || 'String',
                          value: `${selectedNode.getData().id}.${cycleVar.name}`,
                          nodeData: selectedNode.getData(),
                        }));

                        return [...getFilteredVariableList(selectedNode?.data?.type, key), ...cycleVarSuggestions];
                      })()}
                      selectedNode={selectedNode}
                      graphRef={graphRef}
                      addBtnText={t('workflow.config.addCase')}
                    />
                  </Form.Item>
                )
              }

              if (key === 'vision_input' && !values?.vision) {
                return null
              }

              return (
                <Form.Item 
                  key={key} 
                  name={key}
                  label={key === 'vision_input'
                    ? undefined : key === 'parallel_count'
                    ? <span className="rb:text-[10px] rb:text-[#5B6167] rb:leading-3.5 rb:-mb-1!">{t(`workflow.config.${selectedNode?.data?.type}.${key}`)}</span>
                    : t(`workflow.config.${selectedNode?.data?.type}.${key}`)
                  }
                  layout={config.type === 'switch' ? 'horizontal' : 'vertical'}
                  className={key === 'parallel_count' ? 'rb:-mt-3! rb:leading-3.5!' : ''}
                  hidden={Boolean(config.hidden)}
                >
                  {config.type === 'input'
                    ? <Input placeholder={t('common.pleaseEnter')} />
                    : config.type === 'textarea'
                    ? <Input.TextArea placeholder={t('common.pleaseEnter')} />
                    : config.type === 'select'
                    ? <Select
                      options={config.needTranslation ? (config.options || []).map(vo => ({ ...vo, label: t(vo.label) })) : config.options}
                      placeholder={t('common.pleaseSelect')}
                    />
                    : config.type === 'inputNumber'
                    ? <InputNumber
                        placeholder={t('common.pleaseEnter')}
                        className="rb:w-full!"
                        onChange={(value) => form.setFieldValue(key, value)}
                      />
                    : config.type === 'slider'
                    ? <RbSlider min={config.min} max={config.max} step={config.step} />
                    : config.type === 'customSelect'
                    ? <CustomSelect
                      placeholder={t('common.pleaseSelect')}
                      url={config.url as string}
                      params={config.params}
                      hasAll={false}
                      valueKey={config.valueKey}
                      labelKey={config.labelKey}
                      size="small"
                    />
                    : config.type === 'variableList'
                    ? <VariableSelect
                      placeholder={t(config.placeholder || 'common.pleaseSelect')}
                      options={(() => {
                        const baseVariableList = getFilteredVariableList(selectedNode?.data?.type, key);
                        // Apply filtering if specified in config
                        if (config.filterNodeTypes || config.filterVariableNames) {
                          return baseVariableList.filter(variable => {
                            const nodeTypeMatch = !config.filterNodeTypes ||
                              (Array.isArray(config.filterNodeTypes) && config.filterNodeTypes.includes(variable.nodeData?.type));
                            const variableNameMatch = !config.filterVariableNames ||
                              (Array.isArray(config.filterVariableNames) && config.filterVariableNames.includes(variable.label));
                            return nodeTypeMatch || variableNameMatch;
                          });
                        }
                        if (config.onFilterVariableNames) {
                          return baseVariableList.filter(variable => Array.isArray(config.onFilterVariableNames) && config.onFilterVariableNames.includes(variable.label));
                        }
                        // Filter child nodes for iteration output
                        if (config.filterChildNodes && selectedNode) {
                          const graph = graphRef.current;
                          if (!graph) return [];
                          
                          const nodes = graph.getNodes();
                          
                          // Find child nodes whose cycle field equals parent node's ID
                          const childNodes = nodes.filter(node => {
                            const nodeData = node.getData();
                            return nodeData?.cycle === selectedNode.id;
                          });
                          
                          return baseVariableList.filter(variable => 
                            childNodes.some(node => node.id === variable.nodeData?.id) || selectedNode?.data?.type === 'iteration' && key === 'output' && variable.value.includes('sys.')
                          );
                        }
                        return baseVariableList;
                      })()}
                      onChange={(value, option) => handleChangeVariableList(value, option, key)}
                      size="small"
                    />
                    : config.type === 'switch'
                    ? <Switch onChange={
                        key === 'group'
                        ? () => { form.setFieldValue('group_variables', []) }
                        : key === 'vision'
                        ? () => { form.setFieldValue('vision_input', undefined) }
                        : undefined
                      } />
                    : config.type === 'categoryList'
                    ? <CategoryList 
                      parentName={key} 
                      selectedNode={selectedNode}
                      graphRef={graphRef}
                      options={getFilteredVariableList(selectedNode?.data?.type, key)}
                    />
                    : config.type === 'editor'
                    ? <Editor options={variableList} variant="outlined" size="small" />
                    : null
                  }
                </Form.Item>
              )
            })
          }
        </Form>

        {currentNodeVariables.length > 0 && !(!values?.group && selectedNode.getData().type === 'var-aggregator') &&
          <div className="rb:pb-3">
            <Divider />
            <Space size={8} direction="vertical" className="rb:max-w-full!">
              <div className="rb:font-medium rb:text-[12px] rb:leading-4.5 rb:cursor-pointer rb:ml-4" onClick={handleToggle}>
                {t('workflow.config.output')}
                {outputCollapsed ? <CaretRightOutlined /> : <CaretDownOutlined />}
              </div>
              {!outputCollapsed && currentNodeVariables.map(vo => (
                <div key={vo.value} className="rb:ml-4 rb:text-[12px] rb:flex rb:gap-2">
                  <span className="rb:font-medium">{vo.label}</span>
                  <span className="rb:text-[#5B6167]">{vo.dataType}</span>
                </div>
              ))}
            </Space>
          </div>
        }
      </div>}
    </div>
  );
};
export default Properties;