<template>
  <div class="workflow-designer">
    <!-- 顶部工具栏 -->
    <div class="toolbar">
      <div class="toolbar-left">
        <el-button icon="el-icon-back" size="small" @click="goBack">返回</el-button>
        <el-divider direction="vertical" />
        <el-input v-model="form.workflowName" placeholder="工作流名称" size="small" style="width: 200px" />
        <el-select v-model="form.workflowType" placeholder="类型" size="small" style="width: 120px; margin-left: 10px">
          <el-option
            v-for="dict in workflowTypeOptions"
            :key="dict.dictValue"
            :label="dict.dictLabel"
            :value="dict.dictValue"
          />
        </el-select>
      </div>
      <div class="toolbar-right">
        <el-input
          v-model="form.workflowDesc"
          placeholder="工作流描述"
          size="small"
          style="width: 200px; margin-right: 10px"
        />
        <el-divider direction="vertical" />
        <el-button icon="el-icon-zoom-in" size="small" @click="zoomIn">放大</el-button>
        <el-button icon="el-icon-zoom-out" size="small" @click="zoomOut">缩小</el-button>
        <el-button icon="el-icon-rank" size="small" @click="fitView">适应</el-button>
        <el-divider direction="vertical" />
          <el-button
              v-if="!readonlyMode"
              type="primary"
              icon="el-icon-check"
              size="small"
              @click="handleSave"
          >保存</el-button>
          <el-tag v-if="readonlyMode" type="info">历史版本预览</el-tag>
      </div>
    </div>

    <div class="main-content">
      <!-- 左侧节点面板 -->
      <div class="node-panel" v-if="!readonlyMode">
        <div class="panel-title">节点类型</div>
        <div class="node-category" v-for="category in nodeCategories" :key="category.key">
          <div class="category-title">{{ category.name }}</div>
          <div class="node-list">
            <div
              class="node-item"
              v-for="nodeType in category.types"
              :key="nodeType.typeCode"
              draggable="true"
              @dragstart="onDragStart($event, nodeType)"
              :style="{ borderColor: nodeType.typeColor, '--node-color': nodeType.typeColor }"
            >
              <i :class="nodeType.typeIcon" :style="{ color: nodeType.typeColor }"></i>
              <span>{{ nodeType.typeName }}</span>
            </div>
          </div>
        </div>
      </div>

      <!-- 中间画布区域 -->
      <div
        class="canvas-container"
        ref="canvasContainer"
        tabindex="0"
        @drop="onDrop"
        @dragover.prevent
        @click="onCanvasClick"
        @mousedown="onCanvasMouseDown"
        @keydown.delete="handleDelete"
        @keydown.backspace="handleDelete"
        @keydown.ctrl.c="copyNode"
        @keydown.meta.c="copyNode"
        @keydown.ctrl.v="pasteNode"
        @keydown.meta.v="pasteNode"
        @contextmenu.prevent="showContextMenu"
      >
        <svg class="canvas-svg" ref="canvasSvg" :width="canvasSize.width" :height="canvasSize.height"
          :class="{ 'dragging-canvas': isDraggingCanvas }">
          <!-- 网格背景 -->
          <defs>
            <pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
              <path d="M 20 0 L 0 0 0 20" fill="none" stroke="#e0e0e0" stroke-width="0.5"/>
            </pattern>
            <!-- 箭头标记 -->
            <marker
              id="arrowhead"
              markerWidth="10"
              markerHeight="10"
              refX="9"
              refY="5"
              orient="auto"
              markerUnits="userSpaceOnUse"
            >
              <path d="M0,1 L0,9 L9,5 z" fill="#999" />
            </marker>
            <!-- 选中状态的箭头 -->
            <marker
              id="arrowhead-selected"
              markerWidth="10"
              markerHeight="10"
              refX="9"
              refY="5"
              orient="auto"
              markerUnits="userSpaceOnUse"
            >
              <path d="M0,1 L0,9 L9,5 z" fill="#666" />
            </marker>
          </defs>
          <rect :width="canvasSize.width" :height="canvasSize.height" fill="url(#grid)" />

          <!-- 连线 -->
          <g class="edges-layer" :transform="`translate(${canvasOffset.x}, ${canvasOffset.y}) scale(${scale})`">
            <g
              v-for="edge in edges"
              :key="edge.edgeKey"
              class="edge-group"
              :class="{ selected: selectedEdge === edge }"
              @click.stop="selectEdge(edge)"
            >
              <!-- 不可见的交互路径，用于扩大点击区域 -->
              <path
                :d="getEdgePath(edge)"
                stroke="transparent"
                stroke-width="16"
                fill="none"
                class="edge-interaction"
                style="cursor: pointer"
              />
              <!-- 可见的连线路径 -->
              <path
                :d="getEdgePath(edge)"
                :stroke="edge.edgeColor || '#999'"
                stroke-width="2"
                fill="none"
                :marker-end="selectedEdge === edge ? 'url(#arrowhead-selected)' : 'url(#arrowhead)'"
                class="edge-path"
                :class="{ selected: selectedEdge === edge }"
              />
              <text
                v-if="edge.edgeLabel"
                :x="getEdgeLabelPos(edge).x"
                :y="getEdgeLabelPos(edge).y"
                text-anchor="middle"
                font-size="12"
                fill="#666"
              >{{ edge.edgeLabel }}</text>
            </g>
          </g>

          <!-- 临时连线 -->
          <g :transform="`translate(${canvasOffset.x}, ${canvasOffset.y}) scale(${scale})`">
            <path
              v-if="tempEdge"
              :d="tempEdge.path"
              stroke="#1890ff"
              stroke-width="2"
              fill="none"
              stroke-dasharray="5,5"
              marker-end="url(#arrowhead-selected)"
            />
          </g>

          <!-- 节点 -->
          <g class="nodes-layer" :transform="`translate(${canvasOffset.x}, ${canvasOffset.y}) scale(${scale})`">
            <g
              v-for="node in nodes"
              :key="node.nodeKey"
              class="node-group"
              :class="{ selected: selectedNode === node }"
              :transform="`translate(${node.posX}, ${node.posY})`"
              @mousedown="onNodeMouseDown($event, node)"
              @click.stop="selectNode(node)"
            >
              <rect
                :width="nodeWidth"
                :height="node.height || 36"
                rx="6"
                ry="6"
                :fill="getNodeBgColor(node)"
                :stroke="node.nodeColor || '#1890ff'"
                stroke-width="2"
                :class="{ selected: selectedNode === node }"
              />
              <foreignObject :width="nodeWidth" :height="node.height || 36">
                <div class="node-content" xmlns="http://www.w3.org/1999/xhtml" :title="node.nodeName">
                  <i :class="node.nodeIcon" :style="{ color: node.nodeColor }"></i>
                  <span class="node-name">{{ node.nodeName }}</span>
                </div>
              </foreignObject>
              <!-- 连接点 -->
              <circle :cx="nodeWidth / 2" cy="0" r="5" fill="#fff" stroke="#1890ff" stroke-width="2"
                class="anchor top" data-type="top" @mousedown.stop="startConnect($event, node, 'top')" />
              <circle :cx="nodeWidth / 2" :cy="node.height || 36" r="5" fill="#fff" stroke="#1890ff" stroke-width="2"
                class="anchor bottom" data-type="bottom" @mousedown.stop="startConnect($event, node, 'bottom')" />
              <circle cx="0" :cy="(node.height || 36) / 2" r="5" fill="#fff" stroke="#1890ff" stroke-width="2"
                class="anchor left" data-type="left" @mousedown.stop="startConnect($event, node, 'left')" />
              <circle :cx="nodeWidth" :cy="(node.height || 36) / 2" r="5" fill="#fff" stroke="#1890ff" stroke-width="2"
                class="anchor right" data-type="right" @mousedown.stop="startConnect($event, node, 'right')" />
            </g>
          </g>
        </svg>

        <!-- 右键菜单 -->
        <div
          v-show="contextMenu.visible"
          class="context-menu"
          :style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }"
          @click.stop
        >
          <div
            v-if="contextMenu.node"
            class="menu-item"
            @click="copyNodeFromMenu"
          >
            <i class="el-icon-document-copy"></i>
            <span>复制节点</span>
            <span class="shortcut">Ctrl+C</span>
          </div>
          <div
            v-if="copiedNode"
            class="menu-item"
            @click="pasteNodeFromMenu"
          >
            <i class="el-icon-document-add"></i>
            <span>粘贴节点</span>
            <span class="shortcut">Ctrl+V</span>
          </div>
          <div class="menu-divider" v-if="contextMenu.node && copiedNode"></div>
          <div
            v-if="contextMenu.node"
            class="menu-item danger"
            @click="deleteNodeFromMenu"
          >
            <i class="el-icon-delete"></i>
            <span>删除节点</span>
            <span class="shortcut">Delete</span>
          </div>
          <div
            v-if="!contextMenu.node"
            class="menu-item disabled"
          >
            <i class="el-icon-info"></i>
            <span>请选中节点</span>
          </div>
        </div>
      </div>

      <!-- 右侧属性面板 -->
      <div class="property-panel" v-if="!readonlyMode && (selectedNode || selectedEdge)">
        <div class="panel-title">
          <span>
            <i :class="selectedNode ? 'el-icon-setting' : 'el-icon-share'"></i>
            {{ selectedNode ? '节点属性' : '连线属性' }}
          </span>
          <i class="el-icon-close" @click="clearSelection"></i>
        </div>

        <!-- 节点属性 -->
        <div v-if="selectedNode" class="property-content">
          <el-form label-width="90px" size="small" label-position="left">
            <!-- 基本信息 -->
            <div class="property-section">
              <div class="section-title">
                <i class="el-icon-document"></i>基本信息
              </div>
              <el-form-item label="节点内容">
                <el-input
                  v-model="selectedNode.nodeName"
                  type="textarea"
                  :autosize="{ minRows: 2, maxRows: 4 }"
                  placeholder="请输入节点内容"
                />
              </el-form-item>
              <el-form-item label="节点类型">
                <div class="node-type-badge">
                  <i :class="selectedNode.nodeIcon" :style="{ color: selectedNode.nodeColor }"></i>
                  <span>{{ getNodeTypeName(selectedNode.nodeType) }}</span>
                </div>
              </el-form-item>
            </div>
             <!-- AI加微配置 -->
            <div v-if="selectedNode.nodeType == 'AI_ADD_WX_TASK_NEW'" class="property-section">
              <div class="section-title">
                <i class="el-icon-chat-dot-round"></i>加微配置
              </div>
              <el-form-item label="加微话术">
                <!-- <el-select v-model="selectedNode.nodeConfig.robot" filterable placeholder="请选择加微话术">
                  <el-option v-for="item in robotList" :key="item.id" :label="item.name + '('+item.num+')'" :value="item.id"/>
                </el-select> -->
                 <el-select v-model="selectedNode.nodeConfig.dialogId" placeholder="请选择加微话术" filterable size="small">
                      <el-option v-for="dialog in wxDialogList" :key="dialog.id" :label="dialog.name" :value="dialog.id"/>
                    </el-select>
              </el-form-item>
            </div>

            <!-- 企微加个微配置 -->
            <div v-if="selectedNode.nodeType == 'AI_QW_ADD_WX_TASK'" class="property-section">
              <div class="section-title">
                <i class="el-icon-chat-dot-round"></i>加微方式
              </div>
              <el-form-item label="加微方式">
                <!-- <el-select v-model="selectedNode.nodeConfig.robot" filterable placeholder="请选择加微话术">
                  <el-option v-for="item in robotList" :key="item.id" :label="item.name + '('+item.num+')'" :value="item.id"/>
                </el-select> -->
                <el-select v-model="selectedNode.nodeConfig.qwWxAddWayId" placeholder="请选择加微方式" filterable size="small">
                  <el-option
                    v-for="dict in qwWxAddWayOptions"
                    :key="dict.dictValue"
                    :label="dict.dictLabel"
                    :value="dict.dictValue"
                  />
                </el-select>
              </el-form-item>
                <div class="section-title">
                    <i class="el-icon-phone"></i>短信配置
                </div>
                <el-form-item label="短信模版">
                    <el-select v-model="selectedNode.nodeConfig.smsTempId" filterable placeholder="请选择短信模版">
                        <el-option v-for="item in smsTempList" :key="item.tempId" :label="item.title " :value="item.tempId"/>
                    </el-select>
                </el-form-item>
            </div>


            <!-- AI外呼配置（旧版天天外呼，已停用） -->
            <!--
            <div v-if="selectedNode.nodeType == 'AI_CALL_TASK'" class="property-section">
              <div class="section-title">
                <i class="el-icon-phone"></i>外呼配置
              </div>
              <el-form-item label="机器人">
                <el-select v-model="selectedNode.nodeConfig.robot" filterable placeholder="请选择机器人">
                  <el-option v-for="item in robotList" :key="item.id" :label="item.name + '('+item.num+')'" :value="item.id"/>
                </el-select>
              </el-form-item>
              <el-form-item label="话术">
                <el-select v-model="selectedNode.nodeConfig.dialogId" filterable placeholder="请选择话术">
                  <el-option v-for="item in dialogList" :key="item.id" :label="item.name" :value="item.id"/>
                </el-select>
              </el-form-item>
              <el-form-item label="主叫分组">
                <el-select v-model="selectedNode.nodeConfig.cidGroupId" filterable placeholder="请选择主叫分组">
                  <el-option v-for="item in CIDGroupList" :key="item.id" :label="item.name" :value="item.id"/>
                </el-select>
              </el-form-item>
              <el-form-item label="模式">
                <el-select v-model="selectedNode.nodeConfig.mode" placeholder="请选择模式">
                  <el-option label="呼叫机器人后挂断" :value="7"/>
                </el-select>
              </el-form-item>
              <div class="form-row">
                <el-form-item label="呼叫倍率" class="half-width">
                  <el-select v-model="selectedNode.nodeConfig.multiplier" @change="handleConfigChange" placeholder="选择倍率">
                    <el-option label="1" :value="1"/>
                    <el-option label="2" :value="2"/>
                    <el-option label="3" :value="3"/>
                    <el-option label="4" :value="4"/>
                    <el-option label="5" :value="5"/>
                  </el-select>
                </el-form-item>
              </div>
              <el-form-item label="自动重呼">
                <el-radio-group v-model="selectedNode.nodeConfig.autoRecall" @change="handleConfigChange">
                  <el-radio :label="0">否</el-radio>
                  <el-radio :label="1">是</el-radio>
                </el-radio-group>
              </el-form-item>
              <el-form-item label="重呼次数" v-if="selectedNode.nodeConfig.autoRecall == 1">
                <el-select v-model="selectedNode.nodeConfig.recallTimes" @change="handleConfigChange" placeholder="选择重呼次数">
                  <el-option label="不自动重呼" :value="0"/>
                  <el-option label="1次" :value="1"/>
                  <el-option label="2次" :value="2"/>
                  <el-option label="3次" :value="3"/>
                  <el-option label="4次" :value="4"/>
                  <el-option label="5次" :value="5"/>
                </el-select>
              </el-form-item>
            </div>
            -->

            <!-- AI外呼配置（新版 EasyCallCenter365） -->
            <div v-if="selectedNode.nodeType == 'AI_CALL_TASK'" class="property-section">
              <div class="section-title">
                <i class="el-icon-phone"></i>外呼配置
              </div>
              <el-form-item label="外呼模式">
                <el-select
                  v-model="selectedNode.nodeConfig.callMode"
                  filterable
                  placeholder="请选择外呼模式"
                  @change="checkCallMode()"
                >
                  <el-option
                    v-for="item in callMode"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="转人工业务组">
                  <el-select
                      v-model="selectedNode.nodeConfig.busiGroupId"
                      filterable
                      placeholder="请选择技能组"
                      @change="handleConfigChange"
                  >
                      <el-option
                          v-for="item in easyCallBusiGroupList"
                          :key="item.groupId"
                          :label="item.bizGroupName"
                          :value="item.groupId"
                      />
                  </el-select>
              </el-form-item>
              <el-form-item label="外呼线路">
                <el-select
                  :disabled="editAiDisable"
                  v-model="selectedNode.nodeConfig.gatewayId"
                  filterable
                  placeholder="请选择外呼线路"
                  @change="handleConfigChange('handleGateway')"
                >
                  <el-option
                    v-for="item in easyCallGatewayList"
                    :key="item.id"
                    :label="item.gwDesc"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="大模型">
                <el-select
                  :disabled="editAiDisable"
                  v-model="selectedNode.nodeConfig.llmAccountId"
                  filterable
                  placeholder="请选择大模型"
                  @change="handleConfigChange"
                >
                  <el-option
                    v-for="item in easyCallLlmAccountList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="音色来源">
                <el-select
                    :disabled="editAiDisable"
                    v-model="selectedNode.nodeConfig.voiceSource"
                    placeholder="请选择音色来源"
                    @change="handleConfigChange('handleVoiceSource')"
                >
                    <el-option
                        v-for="item in voiceSourceOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                    />
                </el-select>
              </el-form-item>

              <el-form-item label="音色">
                <el-select
                  :disabled="editAiDisable"
                  v-model="selectedNode.nodeConfig.voiceCode"
                  filterable
                  placeholder="请选择音色"
                  @change="handleConfigChange('handleVoice')"
                >
                  <el-option
                    v-for="item in easyCallVoiceCodeList"
                    :key="item.voiceCode"
                    :label="item.voiceName"
                    :value="item.voiceCode"
                  />
                </el-select>
              </el-form-item>
              <!-- <el-form-item label="技能组">
                <el-select
                  v-model="selectedNode.nodeConfig.busiGroupId"
                  filterable
                  placeholder="请选择技能组"
                  @change="handleConfigChange"
                >
                  <el-option
                    v-for="item in easyCallBusiGroupList"
                    :key="item.groupId"
                    :label="item.bizGroupName"
                    :value="item.groupId"
                  />
                </el-select>
              </el-form-item> -->
            </div>

            <!-- AI短信配置 -->
            <div v-if="selectedNode.nodeType == 'AI_SEND_MSG_TASK'" class="property-section">
              <div class="section-title">
                <i class="el-icon-phone"></i>短信配置
              </div>
              <el-form-item label="短信模版">
                <el-select v-model="selectedNode.nodeConfig.smsTempId" filterable placeholder="请选择短信模版">
                  <el-option v-for="item in smsTempList" :key="item.tempId" :label="item.title " :value="item.tempId"/>
                </el-select>
              </el-form-item>
            </div>

            <!-- 样式设置 -->
            <div class="property-section">
              <div class="section-title">
                <i class="el-icon-brush"></i>样式设置
              </div>
              <el-form-item label="节点颜色">
                <el-color-picker v-model="selectedNode.nodeColor" show-alpha />
              </el-form-item>
              <!-- <div class="form-row">
                <el-form-item label="X坐标" class="half-width">
                  <el-input-number v-model="selectedNode.posX" :min="0" controls-position="right" />
                </el-form-item>
                <el-form-item label="Y坐标" class="half-width">
                  <el-input-number v-model="selectedNode.posY" :min="0" controls-position="right" />
                </el-form-item>
              </div> -->
            </div>

            <!-- 操作按钮 -->
            <div class="property-actions">
              <el-button type="primary" size="small" icon="el-icon-document-copy" @click="copyNode">复制节点</el-button>
              <el-button type="danger" size="small" icon="el-icon-delete" @click="deleteNode">删除节点</el-button>
            </div>
          </el-form>
        </div>

        <!-- 连线属性 -->
        <div v-if="selectedEdge" class="property-content">
          <el-form label-width="90px" size="small" label-position="left">
            <!-- 基本信息 -->
            <div class="property-section">
              <div class="section-title">
                <i class="el-icon-share"></i>连线信息
              </div>
              <el-form-item label="备注">
                <el-input v-model="selectedEdge.edgeLabel" placeholder="请输入备注" />
              </el-form-item>
              <el-form-item label="连线颜色">
                <el-color-picker v-model="selectedEdge.edgeColor" show-alpha />
              </el-form-item>
            </div>

            <!-- 条件判断 -->
            <div v-if="edgeSourceNode.nodeType == 'AI_CALL_TASK' || edgeSourceNode.nodeType == 'AI_SEND_MSG_TASK' || edgeSourceNode.nodeType == 'AI_ADD_WX_TASK_NEW' || edgeSourceNode.nodeType == 'AI_QW_ADD_WX_TASK'"  class="property-section">
              <div class="section-title">
                <i class="el-icon-set-up"></i>条件判断
                <el-button type="success" size="mini" icon="el-icon-plus" @click="addCondition" class="add-condition-btn">新增条件</el-button>
              </div>

              <!-- AI外呼任务条件 -->
              <div v-if="edgeSourceNode.nodeType == 'AI_CALL_TASK'" class="conditions-container">
                <div v-for="(item, index) in selectedEdge.conditionExprObj" :key="index" class="condition-item">
                  <div class="condition-header">
                    <span class="condition-number">条件 {{ index + 1 }}</span>
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle @click="removeCondition(index)"></el-button>
                  </div>
                  <div class="condition-content">
                    <el-form-item label="是否拨通">
                      <el-select v-model="item.callConnected" placeholder="请选择">
                        <el-option :value="false" label="否" />
                        <el-option :value="true" label="是" />
                      </el-select>
                    </el-form-item>
                    <el-form-item label="延迟时间" v-if="item.callConnected == false">
                      <el-input v-model="item.callTime" placeholder="请输入时间">
                        <template slot="append">分钟</template>
                      </el-input>
                    </el-form-item>
                    <el-form-item label="意向度" v-if="!!item.callConnected">
                      <el-select v-model="item.intention" placeholder="请选择意向等级" filterable clearable>
                        <el-option v-for="level in levelList" :key="level.dictValue" :label="level.dictLabel" :value="level.dictValue"/>
                      </el-select>
                    </el-form-item>
                  </div>
                </div>
                <div v-if="selectedEdge.conditionExprObj.length === 0" class="empty-condition">
                  <i class="el-icon-info"></i>
                  <span>暂无条件，请点击上方按钮添加</span>
                </div>
              </div>

              <!-- 加微信任务条件 -->
              <div v-if="edgeSourceNode.nodeType == 'AI_ADD_WX_TASK_NEW' || edgeSourceNode.nodeType == 'AI_QW_ADD_WX_TASK'" class="conditions-container">
                <div v-for="(item, index) in selectedEdge.conditionExprObj" :key="index" class="condition-item">
                  <div class="condition-header">
                    <span class="condition-number">条件 {{ index + 1 }}</span>
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle @click="removeCondition(index)"></el-button>
                  </div>
                  <div class="condition-content">
                    <el-form-item label="添加状态">
                      <el-select v-model="item.isAdd" placeholder="请选择">
                        <el-option :value="false" label="未同意" />
                        <el-option :value="true" label="已同意" />
                      </el-select>
                    </el-form-item>
                    <el-form-item label="超时时间" v-if="item.isAdd == false">
                      <el-input v-model="item.addTime" placeholder="请输入时间">
                        <template slot="append">分钟</template>
                      </el-input>
                    </el-form-item>
                  </div>
                </div>
                <div v-if="selectedEdge.conditionExprObj.length === 0" class="empty-condition">
                  <i class="el-icon-info"></i>
                  <span>暂无条件，请点击上方按钮添加</span>
                </div>
              </div>

              <!-- 发短信任务条件 -->
              <div v-if="edgeSourceNode.nodeType == 'AI_SEND_MSG_TASK'" class="conditions-container">
                <div v-for="(item, index) in selectedEdge.conditionExprObj" :key="index" class="condition-item">
                  <div class="condition-header">
                    <span class="condition-number">条件 {{ index + 1 }}</span>
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle @click="removeCondition(index)"></el-button>
                  </div>
                  <div class="condition-content">
<!--                    <el-form-item label="发送状态">-->
<!--                      <el-select v-model="item.sendStatus" placeholder="请选择">-->
<!--                        <el-option :value="true" label="发送成功" />-->
<!--                        <el-option :value="false" label="发送失败" />-->
<!--                      </el-select>-->
<!--                    </el-form-item>-->
                    <el-form-item label="等待时间">
                      <el-input v-model="item.waitTime" placeholder="请输入时间">
                        <template slot="append">分钟</template>
                      </el-input>
                    </el-form-item>
                  </div>
                </div>
                <div v-if="selectedEdge.conditionExprObj.length === 0" class="empty-condition">
                  <i class="el-icon-info"></i>
                  <span>暂无条件，请点击上方按钮添加</span>
                </div>
              </div>
            </div>

            <!-- 操作按钮 -->
            <div class="property-actions">
              <el-button type="danger" size="small" icon="el-icon-delete" @click="deleteEdge">删除连线</el-button>
            </div>
          </el-form>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import {
  getSmsTempList,
} from "@/api/company/companyVoiceRobotic";
import { getWorkflow, addWorkflow, updateWorkflow, getNodeTypes, getWorkflowVersionDetail } from '@/api/company/companyWorkflow'
import {getDicts} from "@/api/system/dict/data";
import { getGatewayList, getLlmAccountList, getVoiceCodeList, getBusiGroupList } from '@/api/company/easyCall'
import { listAll } from '@/api/company/wxDialog';
export default {
  name: 'WorkflowDesign',
  data() {
    return {
      callMode:[{
        id:1,
        name:"人工外呼"
      },{
        id:2,
        name:"ai自动外呼"
      }],
      editAiDisable:true,
      wxDialogList: [],
      qwWxAddWayOptions: [],
      // 工作流ID
      workflowId: null,
      // 历史版本ID
      versionId: null,
      // 是否只读预览
      readonlyMode: false,
      // 表单数据
      form: {
        workflowName: '新建工作流',
        workflowDesc: '',
        workflowType: '1',
        canvasData: ''
      },
      // 节点列表
      nodes: [],
      // 连线列表
      edges: [],
      // 节点类型列表
      nodeTypes: [],
      levelList: [],
      // 节点分类
      nodeCategories: [],
      // 选中的节点
      selectedNode: null,
      // 选中的连线
      selectedEdge: null,
      edgeSourceNode: null,
      // 缩放比例
      scale: 1,
      // 画布偏移
      canvasOffset: { x: 0, y: 0 },
      // 拖拽中的节点
      draggingNode: null,
      // 拖拽偏移
      dragOffset: { x: 0, y: 0 },
      // 是否正在连线
      connecting: false,
      // 连线起点
      connectStart: null,
      // 临时连线
      tempEdge: null,
      // 画布尺寸
      canvasSize: { width: 2000, height: 2000 },
      // 节点固定宽度
      nodeWidth: 120,
      // 是否正在拖动画布
      isDraggingCanvas: false,
      // 画布拖动起始点
      canvasDragStart: { x: 0, y: 0 },
      // 复制的节点
      copiedNode: null,
      // 右键菜单
      contextMenu: {
        visible: false,
        x: 0,
        y: 0,
        node: null
      },
      // 工作流类型字典
      workflowTypeOptions: [
        { dictValue: '1', dictLabel: '对话流程' },
        { dictValue: '2', dictLabel: '任务流程' },
        { dictValue: '3', dictLabel: '审批流程' }
      ],
      conditionExprTemp:{
        callConnected: false,
        callTime: '',
        intention: '',
        isAdd: false,
        addTime: '',
        sendStatus: false,
        waitTime: ''
      },
      CIDGroupList:[],
      robotList: [],
      smsTempList: [],
      dialogList: [],
      // EasyCallCenter365 外呼配置相关列表
      easyCallGatewayList: [],     // 外呼线路（网关）列表
      easyCallLlmAccountList: [],  // 大模型底座列表
      easyCallVoiceCodeList: [],   // 音色列表
      allEasyCallVoiceCodeList: [],   // 接口原始数据
      easyCallBusiGroupList: [],   // tts厂商（技能组）列表
      voiceSourceOptions: [
        { label: '阿里云TTS', value: 'aliyun_tts' },
        { label: '豆包语音', value: 'doubao_vcl_tts' },
        { label: '电信语音', value: 'chinatelecom_tts' }
      ],
    }
  },
  created() {
    this.workflowId = this.$route.params.id
    this.versionId = this.$route.params.versionId

    // 如果有 versionId，说明是历史版本预览模式
    if (this.versionId) {
      this.readonlyMode = true
    }

    this.loadNodeTypes()
    if (this.versionId) {
      this.loadVersionWorkflow()
    } else if (this.workflowId) {
      this.loadWorkflow()
    }
    // listAll().then(e => {
    //   this.wxDialogList = e.data;
    //   console.log("------")
    //   console.log(this.wxDialogList)
    // })
    listAll().then(e => {
      this.wxDialogList = e.data;
      console.log("------")
      console.log(this.wxDialogList)
    })

    this.getDicts("sys_qw_qw_wx_add_way").then(response => {
      this.qwWxAddWayOptions = response.data;
    });

    // listAll().then(e => {
    //   this.wxDialogList = e.data;
    // })
  },
  mounted() {
    // 确保容器可获取焦点
    this.$nextTick(() => {
      this.$refs.canvasContainer.focus()  // 这里应该是 canvasContainer 不是 container
    })

    // 添加全局键盘事件监听
    // window.addEventListener('keydown', this.handleGlobalKeydown)
    document.addEventListener('mousemove', this.onMouseMove)
    document.addEventListener('mouseup', this.onMouseUp)
    // 点击任意地方隐藏右键菜单
    document.addEventListener('click', this.hideContextMenu)
  },
  beforeDestroy() {
    // window.removeEventListener('keydown', this.handleGlobalKeydown)
    document.removeEventListener('mousemove', this.onMouseMove)
    document.removeEventListener('mouseup', this.onMouseUp)
    document.removeEventListener('click', this.hideContextMenu)
  },
  methods: {
    // 聚焦画布容器
    focusCanvasContainer() {
      this.$refs.canvasContainer.focus()
    },

    // 处理配置变化，强制更新视图
    handleConfigChange(v) {
      if( !!v && v === "handleVoiceSource" ){
        let voiceSource = this.selectedNode.nodeConfig.voiceSource;

        this.easyCallVoiceCodeList = this.allEasyCallVoiceCodeList.filter(e => e.voiceSource == voiceSource);

        this.selectedNode.nodeConfig.voiceCode = null;
        this.selectedNode.nodeConfig.ttsModels = null;
      }
      if( !!v && v === "handleVoice" ){
       let voice =  this.easyCallVoiceCodeList.filter(e=>e.voiceCode == this.selectedNode.nodeConfig.voiceCode);
       this.selectedNode.nodeConfig.voiceSource = voice[0].voiceSource;
       this.selectedNode.nodeConfig.ttsModels =  voice[0].ttsModels;
      }
      else if( !!v && v === "handleGateway" ){
       let gateway =  this.easyCallGatewayList.filter(e=>e.id == this.selectedNode.nodeConfig.gatewayId);
       this.selectedNode.nodeConfig.maxConcurrency = gateway[0].maxConcurrency;
      }
      // 强制触发Vue响应式更新
      this.$forceUpdate()
    },
    //选择外呼模式
    checkCallMode(){
      // callMode: 1=人工外呼, 2=AI自动外呼
      // 人工外呼时禁用AI相关配置，AI外呼时启用
      this.editAiDisable = this.selectedNode.nodeConfig.callMode !== 2;
    },

    // 点击画布时聚焦
    onCanvasClick() {
      this.clearSelection()
      this.focusCanvasContainer()
    },

    // 点击节点时聚焦
    selectNode(node) {
      this.selectedNode = node
      // 将nodeConfig从字符串解析为对象
      if (typeof this.selectedNode.nodeConfig === 'string') {
        try {
          this.selectedNode.nodeConfig = JSON.parse(this.selectedNode.nodeConfig)
        } catch (e) {
          this.selectedNode.nodeConfig = {}
        }
      }
      // 确保nodeConfig是对象
      if (!this.selectedNode.nodeConfig || typeof this.selectedNode.nodeConfig !== 'object') {
        this.selectedNode.nodeConfig = {}
      }

      this.selectedEdge = null
      this.edgeSourceNode = null
      if(this.selectedNode.nodeType == "AI_CALL_TASK"){
        // 使用$set初始化默认值，确保响应式
        if (!this.selectedNode.nodeConfig.mode) {
          this.$set(this.selectedNode.nodeConfig, 'mode', 7)
        }
        if (!this.selectedNode.nodeConfig.multiplier) {
          this.$set(this.selectedNode.nodeConfig, 'multiplier', 1)
        }
        if (this.selectedNode.nodeConfig.autoRecall === undefined) {
          this.$set(this.selectedNode.nodeConfig, 'autoRecall', 0)
        }
        if (!this.selectedNode.nodeConfig.recallTimes && this.selectedNode.nodeConfig.recallTimes !== 0) {
          this.$set(this.selectedNode.nodeConfig, 'recallTimes', 0)
        }
          if (this.selectedNode.nodeConfig.busiGroupId === undefined) {
              this.$set(this.selectedNode.nodeConfig, 'busiGroupId', null)
          }
        // 初始化外呼模式，默认为人工外呼(1)
        if (!this.selectedNode.nodeConfig.callMode) {
          this.$set(this.selectedNode.nodeConfig, 'callMode', 1)
        }
        // 根据当前外呼模式设置AI配置的禁用状态
        this.editAiDisable = this.selectedNode.nodeConfig.callMode !== 2;

        // getTypes().then(e => {
        //   this.robotList = e.robot;
        //   this.dialogList = e.dialog;
        // })
        // getCIDGroupList().then(res=>{
        //   this.CIDGroupList = res.data;
        // }).catch(res=>{
        //   console.log(res);
        // });
        // 加载 EasyCallCenter365 四项基础数据
        getGatewayList().then(res => {
          this.easyCallGatewayList = res.data || []
        })
        getLlmAccountList().then(res => {
          this.easyCallLlmAccountList = res.data || []
        })
        getVoiceCodeList().then(res => {
          this.allEasyCallVoiceCodeList = res.data || []
          this.easyCallVoiceCodeList = res.data || []
        })
        getBusiGroupList().then(res => {
          this.easyCallBusiGroupList = res.data || []
        })
      }
      if (this.selectedNode.nodeType === 'AI_SEND_MSG_TASK' || this.selectedNode.nodeType === 'AI_QW_ADD_WX_TASK') {
        getSmsTempList().then(res => {
          this.smsTempList = res.data || []
        })
        console.log('smsTempList:', this.smsTempList)
      }
      this.focusCanvasContainer()
    },

    // 点击连线时聚焦
    selectEdge(edge) {
      this.selectedEdge = edge
      // 确保 conditionExprObj 存在
      if (!this.selectedEdge.conditionExprObj) {
        this.$set(this.selectedEdge, 'conditionExprObj', [])
      }
      this.edgeSourceNode = this.nodes.filter(e => e.nodeKey == this.selectedEdge.sourceNodeKey)[0]
      if(this.edgeSourceNode.nodeType == "AI_CALL_TASK"){
        if(this.levelList.length == 0) {
          getDicts("customer_intention_level").then(e => {
            this.levelList = e.data;
          })
        }
      }
      this.selectedNode = null
      this.focusCanvasContainer()
    },

    // 局部键盘事件
    handleDelete(event) {
          if (this.readonlyMode) return
          event.preventDefault()
          this.deleteSelected()
    },

    // 全局键盘事件
    // handleGlobalKeydown(event) {
    //   // 检查是否按下了退格键或删除键
    //   if ((event.key === 'Backspace' || event.key === 'Delete') && !this.isInputFocused()) {
    //     event.preventDefault()
    //     this.deleteSelected()
    //   }
    // },

    // 删除选中项的逻辑
    deleteSelected() {
      if (this.selectedNode) {
        this.deleteSelectedNode()
      } else if (this.selectedEdge) {
        this.deleteSelectedEdge()
      }
    },

    // 删除选中节点
    deleteSelectedNode() {
      if (!this.selectedNode) return
      // 确认对话框
      this.$confirm('是否确认删除该节点?', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const key = this.selectedNode.nodeKey
        this.nodes = this.nodes.filter(n => n.nodeKey !== key)
        // 同时删除与该节点相关的连线
        this.edges = this.edges.filter(e =>
          e.sourceNodeKey !== key && e.targetNodeKey !== key)
        this.selectedNode = null
      }).catch(() => {})
    },

    // 删除选中连线
    deleteSelectedEdge() {
      if (!this.selectedEdge) return

      this.$confirm('是否确认删除该连线?', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.edges = this.edges.filter(e => e.edgeKey !== this.selectedEdge.edgeKey)
        this.selectedEdge = null
      }).catch(() => {})
    },

    // 检查是否有输入框获得焦点
    isInputFocused() {
      const activeElement = document.activeElement
      // 注意：节点名称输入框也需要排除
      const isEditable = ['INPUT', 'TEXTAREA', 'SELECT'].includes(activeElement.tagName)
      // 额外检查是否是节点名称输入框
      const isNodeInput = activeElement.classList && activeElement.classList.contains('node-name-input')
      return isEditable || isNodeInput
    },

    /** 加载节点类型 */
    loadNodeTypes() {
      getNodeTypes().then(res => {
        this.nodeTypes = res.data || []
        this.groupNodeTypes()
      }).catch(() => {
        // 如果接口未实现，使用默认节点类型
        this.nodeTypes = [
          { typeCode: 'start', typeName: '开始', typeCategory: 'basic', typeIcon: 'el-icon-video-play', typeColor: '#52c41a' },
          { typeCode: 'end', typeName: '结束', typeCategory: 'basic', typeIcon: 'el-icon-video-pause', typeColor: '#ff4d4f' },
          { typeCode: 'condition', typeName: '条件判断', typeCategory: 'logic', typeIcon: 'el-icon-question', typeColor: '#faad14' },
        ]
        this.groupNodeTypes()
      })
    },
    /** 节点类型分组 */
    groupNodeTypes() {
      // 默认颜色映射
      const defaultColors = {
        start: '#52c41a',
        end: '#ff4d4f',
        condition: '#faad14',
        AI_CALL_TASK: '#1890ff',
        AI_ADD_WX_TASK_NEW: '#722ed1',
        AI_SEND_MSG_TASK: '#eb2f96',
        DELAY_TASK: '#13c2c2'
      }

      const categoryMap = {
        basic: { key: 'basic', name: '基础节点', types: [] },
        // logic: { key: 'logic', name: '逻辑节点', types: [] },
        aiCell: { key: 'aiCell', name: '动作节点', types: [] },
      }
      this.nodeTypes.forEach(t => {
        // 如果节点类型没有颜色，使用默认颜色
        if (!t.typeColor) {
          t.typeColor = defaultColors[t.typeCode] || '#666'
        }
        const cat = categoryMap[t.typeCategory] || categoryMap.basic
        cat.types.push(t)
      })
      this.nodeCategories = Object.values(categoryMap).filter(c => c.types.length > 0)
    },
    /** 加载工作流 */
    loadWorkflow() {
      getWorkflow(this.workflowId).then(res => {
        const data = res.data
        this.form = {
          workflowName: data.workflowName,
          workflowDesc: data.workflowDesc,
          workflowType: String(data.workflowType),
          canvasData: data.canvasData
        }
        if(data.edges){
          data.edges.forEach(edge => {
            const con = edge.conditionExpr;
            if(con == null){
              edge.conditionExprObj = [];
            }else{
              edge.conditionExprObj = JSON.parse(edge.conditionExpr);
            }
            console.info(edge)
          })
        }
        // 处理nodes，将nodeConfig从字符串转为对象
        if(data.nodes){
          data.nodes.forEach(node => {
            if (typeof node.nodeConfig === 'string') {
              try {
                // 使用Object.assign创建新对象，确保响应式
                const parsedConfig = JSON.parse(node.nodeConfig)
                node.nodeConfig = Object.assign({}, parsedConfig)
              } catch (e) {
                node.nodeConfig = {}
              }
            }
            if (!node.nodeConfig || typeof node.nodeConfig !== 'object') {
              node.nodeConfig = {}
            }
          })
        }
        this.nodes = data.nodes || []
        this.edges = data.edges || []
      })
    },
    /** 加载历史版本详情（只读预览） */
    loadVersionWorkflow() {
      getWorkflowVersionDetail(this.versionId).then(res => {
          const data = res.data || {}
          const version = data.workflowVersion || {}

          this.form = {
              workflowName: version.workflowName || '',
              workflowDesc: version.workflowDesc || '',
              workflowType: String(version.workflowType || '1'),
              canvasData: version.canvasData || ''
          }

          let nodes = data.nodes || []
          let edges = data.edges || []

          // 处理连线条件
          if (edges && edges.length > 0) {
              edges.forEach(edge => {
                  const con = edge.conditionExpr
                  if (con == null || con === '') {
                      edge.conditionExprObj = []
                  } else {
                      try {
                          edge.conditionExprObj = JSON.parse(con)
                      } catch (e) {
                          edge.conditionExprObj = []
                      }
                  }
              })
          }

          // 处理节点配置
          if (nodes && nodes.length > 0) {
              nodes.forEach(node => {
                  if (typeof node.nodeConfig === 'string') {
                      try {
                          const parsedConfig = JSON.parse(node.nodeConfig)
                          node.nodeConfig = Object.assign({}, parsedConfig)
                      } catch (e) {
                          node.nodeConfig = {}
                      }
                  }
                  if (!node.nodeConfig || typeof node.nodeConfig !== 'object') {
                      node.nodeConfig = {}
                  }
              })
          }

          this.nodes = nodes
          this.edges = edges

          // 恢复画布状态
          if (this.form.canvasData) {
              try {
                  const canvasData = JSON.parse(this.form.canvasData)
                  this.scale = canvasData.scale || 1
                  this.canvasOffset = canvasData.offset || { x: 0, y: 0 }
              } catch (e) {
                  this.scale = 1
                  this.canvasOffset = { x: 0, y: 0 }
              }
          }
      })
    },
    /** 返回列表 */
    goBack() {
        // 历史版本预览模式下，返回到列表页并自动打开对应工作流的历史版本弹窗
        if (this.readonlyMode && this.$route.query.workflowId) {
            this.$router.push({
                path: '/companyWx/companyWorkflow',
                query: {
                    openVersionWorkflowId: this.$route.query.workflowId
                }
            })
            return
        }

        // 普通编辑模式保持原逻辑
        this.$router.push('/companyWx/companyWorkflow')
    },
    /** 放大 */
    zoomIn() {
      this.scale = Math.min(2, this.scale + 0.1)
    },
    /** 缩小 */
    zoomOut() {
      this.scale = Math.max(0.5, this.scale - 0.1)
    },
    /** 适应画布 */
    fitView() {
      this.scale = 1
      this.canvasOffset = { x: 0, y: 0 }
      this.focusCanvasContainer()
    },
    /** 生成唯一Key */
    generateKey() {
      return 'node_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9)
    },
    /** 复制节点 */
    copyNode(e) {
        if (this.readonlyMode) return
        if (!this.selectedNode) {
            return
        }
        e.preventDefault()
        this.copiedNode = JSON.parse(JSON.stringify(this.selectedNode))
        this.$message.success('节点已复制')
    },
    /** 粘贴节点 */
    pasteNode(e) {
        if (this.readonlyMode) return
        if (!this.copiedNode) {
            this.$message.warning('没有可粘贴的节点')
            return
        }
        e.preventDefault()

        const newNode = {
            ...this.copiedNode,
            nodeKey: this.generateKey(),
            posX: this.copiedNode.posX + 30,
            posY: this.copiedNode.posY + 30,
            nodeConfig: this.copiedNode.nodeConfig ? JSON.parse(JSON.stringify(this.copiedNode.nodeConfig)) : {}
        }

        this.nodes.push(newNode)
        this.selectedNode = newNode
        this.selectedEdge = null

        this.checkAndExpandCanvas(newNode)

        this.$message.success('节点已粘贴')
    },
    /** 显示右键菜单 */
    showContextMenu(e) {
        if (this.readonlyMode) return

        const rect = this.$refs.canvasContainer.getBoundingClientRect()
        this.contextMenu.x = e.clientX - rect.left
        this.contextMenu.y = e.clientY - rect.top
        this.contextMenu.node = this.selectedNode
        this.contextMenu.visible = true
    },
    /** 隐藏右键菜单 */
    hideContextMenu() {
      this.contextMenu.visible = false
    },
    /** 从菜单复制节点 */
    copyNodeFromMenu() {
      if (this.contextMenu.node) {
        this.copiedNode = JSON.parse(JSON.stringify(this.contextMenu.node))
        this.$message.success('节点已复制')
      }
      this.hideContextMenu()
    },
    /** 从菜单粘贴节点 */
    pasteNodeFromMenu() {
      if (!this.copiedNode) {
        this.$message.warning('没有可粘贴的节点')
        return
      }

      const newNode = {
        ...this.copiedNode,
        nodeKey: this.generateKey(),
        posX: this.copiedNode.posX + 30,
        posY: this.copiedNode.posY + 30,
        nodeConfig: this.copiedNode.nodeConfig ? JSON.parse(JSON.stringify(this.copiedNode.nodeConfig)) : {}
      }

      this.nodes.push(newNode)
      this.selectedNode = newNode
      this.selectedEdge = null
      this.checkAndExpandCanvas(newNode)

      this.$message.success('节点已粘贴')
      this.hideContextMenu()
    },
    /** 从菜单删除节点 */
    deleteNodeFromMenu() {
      if (this.contextMenu.node) {
        this.deleteNode()
      }
      this.hideContextMenu()
    },
    /** 判断是否是开始节点 */
    isStartNodeType(typeCode) {
      return typeCode === 'START' || typeCode === 'start'
    },
    /** 判断是否是结束节点 */
    isEndNodeType(typeCode) {
      return typeCode === 'END' || typeCode === 'end'
    },
    /** 拖拽开始 */
    onDragStart(e, nodeType) {
      e.dataTransfer.setData('nodeType', JSON.stringify(nodeType))
    },
    /** 放置节点 */
    onDrop(e) {
        if (this.readonlyMode) return

        const nodeTypeStr = e.dataTransfer.getData('nodeType')
        if (!nodeTypeStr) return
        const nodeType = JSON.parse(nodeTypeStr)

        if (this.isStartNodeType(nodeType.typeCode)) {
            const existingStart = this.nodes.find(n => this.isStartNodeType(n.nodeType))
            if (existingStart) {
                this.$message.warning('已存在开始节点，工作流只能有一个开始节点')
                return
            }
        }
        if (this.isEndNodeType(nodeType.typeCode)) {
            const existingEnd = this.nodes.find(n => this.isEndNodeType(n.nodeType))
            if (existingEnd) {
                this.$message.warning('已存在结束节点，工作流只能有一个结束节点')
                return
            }
        }

        const rect = this.$refs.canvasContainer.getBoundingClientRect()
        const x = (e.clientX - rect.left - this.canvasOffset.x) / this.scale
        const y = (e.clientY - rect.top - this.canvasOffset.y) / this.scale

        const newNode = {
            nodeKey: this.generateKey(),
            nodeName: nodeType.typeName,
            nodeType: nodeType.typeCode,
            nodeIcon: nodeType.typeIcon,
            nodeColor: nodeType.typeColor,
            posX: Math.round(x - 50),
            posY: Math.round(y - 20),
            height: 40,
            nodeConfig: {}
        }
        this.nodes.push(newNode)
        this.selectNode(newNode)
        this.focusCanvasContainer()
        this.checkAndExpandCanvas(newNode)
    },

    /** 画布鼠标按下 */
    onCanvasMouseDown(e) {
        if (this.readonlyMode) return

        if (e.button !== 0) return
        if (e.target.tagName === 'rect' && e.target.getAttribute('fill') === 'url(#grid)') {
            this.isDraggingCanvas = true
            this.canvasDragStart = {
                x: e.clientX,
                y: e.clientY,
                scrollLeft: this.$refs.canvasContainer.scrollLeft,
                scrollTop: this.$refs.canvasContainer.scrollTop
            }
            e.preventDefault()
        }
    },

    /** 清除选中 */
    clearSelection() {
      this.selectedNode = null
      this.selectedEdge = null
    },
    /** 节点鼠标按下 */
    onNodeMouseDown(e, node) {
        if (this.readonlyMode) {
            this.selectNode(node)
            return
        }

        if (e.target.classList.contains('anchor')) return
        this.draggingNode = node
        const rect = this.$refs.canvasContainer.getBoundingClientRect()
        const scrollLeft = this.$refs.canvasContainer.scrollLeft
        const scrollTop = this.$refs.canvasContainer.scrollTop
        this.dragOffset = {
            x: (e.clientX - rect.left + scrollLeft - this.canvasOffset.x) / this.scale - node.posX,
            y: (e.clientY - rect.top + scrollTop - this.canvasOffset.y) / this.scale - node.posY
        }
        this.selectNode(node)
    },
    /** 鼠标移动 */
    onMouseMove(e) {
      // 拖动画布
      if (this.isDraggingCanvas) {
        const dx = e.clientX - this.canvasDragStart.x
        const dy = e.clientY - this.canvasDragStart.y
        this.$refs.canvasContainer.scrollLeft = this.canvasDragStart.scrollLeft - dx
        this.$refs.canvasContainer.scrollTop = this.canvasDragStart.scrollTop - dy
        return
      }
      // 拖动节点
      if (this.draggingNode) {
        const rect = this.$refs.canvasContainer.getBoundingClientRect()
        const scrollLeft = this.$refs.canvasContainer.scrollLeft
        const scrollTop = this.$refs.canvasContainer.scrollTop
        const x = (e.clientX - rect.left + scrollLeft - this.canvasOffset.x) / this.scale - this.dragOffset.x
        const y = (e.clientY - rect.top + scrollTop - this.canvasOffset.y) / this.scale - this.dragOffset.y
        this.draggingNode.posX = Math.max(0, x)
        this.draggingNode.posY = Math.max(0, y)
        // 检测并扩展画布
        this.checkAndExpandCanvas(this.draggingNode)
      }
      // 连线
      if (this.connecting && this.connectStart) {
        const rect = this.$refs.canvasContainer.getBoundingClientRect()
        const scrollLeft = this.$refs.canvasContainer.scrollLeft
        const scrollTop = this.$refs.canvasContainer.scrollTop
        const endX = (e.clientX - rect.left + scrollLeft - this.canvasOffset.x) / this.scale
        const endY = (e.clientY - rect.top + scrollTop - this.canvasOffset.y) / this.scale
        this.tempEdge = {
          path: this.calcPath(this.connectStart.x, this.connectStart.y, endX, endY)
        }
      }
    },
    /** 检测并扩展画布 */
    checkAndExpandCanvas(node) {
      const nodeHeight = node.height || 36
      const padding = 200 // 边缘预留空间
      const expandStep = 500 // 每次扩展的大小

      const nodeRight = node.posX + this.nodeWidth
      const nodeBottom = node.posY + nodeHeight

      // 检测右边缘
      if (nodeRight + padding > this.canvasSize.width) {
        this.canvasSize.width += expandStep
      }
      // 检测下边缘
      if (nodeBottom + padding > this.canvasSize.height) {
        this.canvasSize.height += expandStep
      }
    },
    /** 鼠标松开 */
    onMouseUp(e) {
      // 停止拖动画布
      if (this.isDraggingCanvas) {
        this.isDraggingCanvas = false
        this.focusCanvasContainer()
        return
      }
      // 停止连线
      if (this.connecting) {
        const targetNode = this.findNodeAtPoint(e.clientX, e.clientY)
        if (targetNode && targetNode.nodeKey !== this.connectStart.nodeKey) {
          this.createEdge(this.connectStart.nodeKey, targetNode.nodeKey,
            this.connectStart.anchor, e.target.dataset.type || 'top')
        }
        this.connecting = false
        this.connectStart = null
        this.tempEdge = null
      }
      this.draggingNode = null
    },
    /** 开始连线 */
    startConnect(e, node, anchor) {
        if (this.readonlyMode) return

        this.connecting = true
        const anchorPos = this.getAnchorPos(node, anchor)
        this.connectStart = {
            nodeKey: node.nodeKey,
            anchor: anchor,
            x: anchorPos.x,
            y: anchorPos.y
        }
        this.selectNode(node)
    },
    /** 获取锚点位置 */
    getAnchorPos(node, anchor) {
      const w = this.nodeWidth
      const h = node.height || 36
      switch (anchor) {
        case 'top': return { x: node.posX + w / 2, y: node.posY }
        case 'bottom': return { x: node.posX + w / 2, y: node.posY + h }
        case 'left': return { x: node.posX, y: node.posY + h / 2 }
        case 'right': return { x: node.posX + w, y: node.posY + h / 2 }
        default: return { x: node.posX + w / 2, y: node.posY + h }
      }
    },
    /** 查找点击位置的节点 */
    findNodeAtPoint(clientX, clientY) {
      const rect = this.$refs.canvasContainer.getBoundingClientRect()
      const scrollLeft = this.$refs.canvasContainer.scrollLeft
      const scrollTop = this.$refs.canvasContainer.scrollTop
      const x = (clientX - rect.left + scrollLeft - this.canvasOffset.x) / this.scale
      const y = (clientY - rect.top + scrollTop - this.canvasOffset.y) / this.scale
      return this.nodes.find(n => {
        const w = this.nodeWidth
        const h = n.height || 36
        return x >= n.posX && x <= n.posX + w && y >= n.posY && y <= n.posY + h
      })
    },
    /** 创建连线 */
    createEdge(sourceKey, targetKey, sourceAnchor, targetAnchor) {
      const exists = this.edges.find(e =>
        e.sourceNodeKey === sourceKey && e.targetNodeKey === targetKey)
      if (exists) return

      this.edges.push({
        edgeKey: 'edge_' + Date.now(),
        sourceNodeKey: sourceKey,
        targetNodeKey: targetKey,
        sourceAnchor: sourceAnchor,
        targetAnchor: targetAnchor,
        edgeType: 'smoothstep',
        conditionExprObj: [],
        edgeColor: '#999999'
      })
    },
    /** 获取连线路径 */
    getEdgePath(edge) {
      const sourceNode = this.nodes.find(n => n.nodeKey === edge.sourceNodeKey)
      const targetNode = this.nodes.find(n => n.nodeKey === edge.targetNodeKey)
      if (!sourceNode || !targetNode) return ''

      const start = this.getAnchorPos(sourceNode, edge.sourceAnchor || 'bottom')
      const end = this.getAnchorPos(targetNode, edge.targetAnchor || 'top')
      return this.calcPath(start.x, start.y, end.x, end.y, edge.sourceAnchor || 'bottom', edge.targetAnchor || 'top')
    },
    /** 计算贝塞尔曲线路径 */
    calcPath(x1, y1, x2, y2, sourceAnchor, targetAnchor) {
      const dx = x2 - x1
      const dy = y2 - y1
      const distance = Math.sqrt(dx * dx + dy * dy)

      // 根据锚点位置计算控制点偏移量，动态调整
      let offset = Math.min(distance * 0.4, 80)

      let cp1x = x1, cp1y = y1
      let cp2x = x2, cp2y = y2

      // 根据源节点锚点方向设置第一个控制点
      switch(sourceAnchor) {
        case 'top':
          cp1y = y1 - offset
          cp1x = x1
          break
        case 'bottom':
          cp1y = y1 + offset
          cp1x = x1
          break
        case 'left':
          cp1x = x1 - offset
          cp1y = y1
          break
        case 'right':
          cp1x = x1 + offset
          cp1y = y1
          break
        default:
          cp1y = y1 + offset
          cp1x = x1
      }

      // 根据目标节点锚点方向设置第二个控制点
      switch(targetAnchor) {
        case 'top':
          cp2y = y2 - offset
          cp2x = x2
          break
        case 'bottom':
          cp2y = y2 + offset
          cp2x = x2
          break
        case 'left':
          cp2x = x2 - offset
          cp2y = y2
          break
        case 'right':
          cp2x = x2 + offset
          cp2y = y2
          break
        default:
          cp2y = y2 - offset
          cp2x = x2
      }

      return `M ${x1} ${y1} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${x2} ${y2}`
    },
    /** 获取连线标签位置 */
    getEdgeLabelPos(edge) {
      const sourceNode = this.nodes.find(n => n.nodeKey === edge.sourceNodeKey)
      const targetNode = this.nodes.find(n => n.nodeKey === edge.targetNodeKey)
      if (!sourceNode || !targetNode) return { x: 0, y: 0 }
      const start = this.getAnchorPos(sourceNode, edge.sourceAnchor || 'bottom')
      const end = this.getAnchorPos(targetNode, edge.targetAnchor || 'top')
      return { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 }
    },
    /** 获取节点背景色 */
    getNodeBgColor(node) {
      const color = node.nodeColor || '#1890ff'
      // 处理各种颜色格式
      if (color.startsWith('rgba')) {
        // rgba 格式，替换透明度
        return color.replace(/[\d.]+\)$/g, '0.08)')
      } else if (color.startsWith('rgb')) {
        // rgb 格式，转为 rgba
        return color.replace('rgb', 'rgba').replace(')', ', 0.08)')
      } else if (color.startsWith('#')) {
        // 十六进制格式
        // 处理 3 位和 6 位十六进制
        let hex = color.slice(1)
        if (hex.length === 3) {
          hex = hex.split('').map(c => c + c).join('')
        }
        if (hex.length === 6) {
          return `#${hex}15`
        } else if (hex.length === 8) {
          // 已经带透明度，替换为 15
          return `#${hex.slice(0, 6)}15`
        }
      }
      // 默认返回原颜色 + 15
      return color + '15'
    },

    /** 获取节点类型名称 */
    getNodeTypeName(typeCode) {
      const t = this.nodeTypes.find(n => n.typeCode === typeCode)
      return t ? t.typeName : typeCode
    },
    /** 删除节点（按钮触发） */
    deleteNode() {
      this.deleteSelectedNode()
    },
    /** 删除连线（按钮触发） */
    addCondition() {
      if (!this.selectedEdge) {
        this.msgWarning('请先选择一条连线')
        return
      }
      if (!this.selectedEdge.conditionExprObj) {
        this.$set(this.selectedEdge, 'conditionExprObj', [])
      }
      this.selectedEdge.conditionExprObj.push(JSON.parse(JSON.stringify(this.conditionExprTemp)));
    },
    removeCondition(index) {
      this.selectedEdge.conditionExprObj.splice(index, 1);
    },
    /** 删除连线（按钮触发） */
    deleteEdge() {
      this.deleteSelectedEdge()
    },
    /** 保存工作流 */
    handleSave() {
      if (this.readonlyMode) {
        return
      }

      if (!this.form.workflowName) {
        this.$message.warning('请输入工作流名称')
        return
      }
      if (!this.form.workflowName) {
        this.$message.warning('请输入工作流名称')
        return
      }

      // 校验开始节点和结束节点
      const startNodes = this.nodes.filter(node => this.isStartNodeType(node.nodeType))
      const endNodes = this.nodes.filter(node => this.isEndNodeType(node.nodeType))

      if (endNodes.length === 0) {
        this.$message.warning('工作流必须包含一个结束节点')
        return
      }
      if (endNodes.length > 1) {
        this.$message.warning('工作流只能包含一个结束节点')
        return
      }

      // 校验所有节点都必须有连线
      if (this.nodes.length > 0) {
        const connectedNodeKeys = new Set()
        this.edges.forEach(edge => {
          connectedNodeKeys.add(edge.sourceNodeKey)
          connectedNodeKeys.add(edge.targetNodeKey)
        })
        const isolatedNodes = this.nodes.filter(node => !connectedNodeKeys.has(node.nodeKey))
        if (isolatedNodes.length > 0) {
          const isolatedNames = isolatedNodes.map(n => n.nodeName).join('、')
          this.$message.warning(`以下节点未连线：${isolatedNames}，所有节点必须连线`)
          return
        }
      }

      // 校验短信节点和外呼节点配置
      for (const node of this.nodes) {
        // 短信节点校验：短信模版必选
        if (node.nodeType === 'AI_SEND_MSG_TASK') {
          if (!node.nodeConfig || !node.nodeConfig.smsTempId) {
            this.$message.warning(`节点「${node.nodeName}」未选择短信模版`)
            return
          }
        }
        // 外呼节点校验
        if (node.nodeType === 'AI_CALL_TASK') {
          const callMode = node.nodeConfig ? node.nodeConfig.callMode : null
          // callMode=2 为AI自动外呼，需要校验必选项
          if (callMode === 2) {
            if (!node.nodeConfig.gatewayId) {
              this.$message.warning(`节点「${node.nodeName}」未选择外呼线路`)
              return
            }
            if (!node.nodeConfig.llmAccountId) {
              this.$message.warning(`节点「${node.nodeName}」未选择大模型`)
              return
            }
            if (!node.nodeConfig.voiceCode) {
              this.$message.warning(`节点「${node.nodeName}」未选择音色`)
              return
            }
          }
        }
        // 加企微节点校验：加微方式必选
        if (node.nodeType === 'AI_QW_ADD_WX_TASK') {
          if (!node.nodeConfig || !node.nodeConfig.qwWxAddWayId) {
            this.$message.warning(`节点「${node.nodeName}」未选择加微方式`)
            return
          }
        }
      }

      const nodes = JSON.parse(JSON.stringify(this.nodes))
      this.edges.forEach((edges) => {
        edges.conditionExpr = JSON.stringify(edges.conditionExprObj);
      })
      nodes.filter(node => typeof node.nodeConfig == 'object').forEach(node => {
        node.nodeConfig = JSON.stringify(node.nodeConfig);
      })

      const data = {
        workflowId: this.workflowId,
        workflowName: this.form.workflowName,
        workflowDesc: this.form.workflowDesc,
        workflowType: this.form.workflowType,
        canvasData: JSON.stringify({ scale: this.scale, offset: this.canvasOffset }),
        nodes: nodes,
        edges: this.edges,
        startNodeKey: startNodes[0].nodeKey,
        endNodeKey: endNodes[0].nodeKey
      }

      if (this.workflowId) {
        updateWorkflow(data).then(() => {
          this.$message.success('保存成功')
        })
      } else {
        addWorkflow(data).then(res => {
          this.$message.success('保存成功')
          this.workflowId = res.data
          this.$router.replace('/companyWx/companyWorkflow/design/' + this.workflowId)
        })
      }
    }
  }
}
</script>

<style lang="scss" scoped>
@import './design.scss';
</style>
