<template>
  <div class="workflow-canvas-page">
    <div class="canvas-header">
      <div class="header-left">
        <el-button @click="goBack" icon="el-icon-back" plain size="small">返回模板库</el-button>
        <span class="header-title">工作流可视化编辑</span>
        <el-tag v-if="templateData" size="small">{{ templateData.prompt_name || templateData.templateName }}</el-tag>
      </div>
      <div class="header-right">
        <el-radio-group v-model="viewMode" size="small">
          <el-radio-button label="canvas">画布视图</el-radio-button>
          <el-radio-button label="list">列表视图</el-radio-button>
        </el-radio-group>
        <el-button type="primary" size="small" @click="saveWorkflow" :loading="saving" style="margin-left:12px">
          <i class="el-icon-check"></i> 保存
        </el-button>
      </div>
    </div>

    <div v-if="!templateId" class="no-template">
      <el-empty description="请从模板库选择一个模板进行编辑">
        <el-button type="primary" @click="goBack">返回模板库</el-button>
      </el-empty>
    </div>

    <template v-else>
      <el-card class="info-card" shadow="never" v-if="templateData">
        <el-descriptions :column="4" size="small" border>
          <el-descriptions-item label="模板名称">{{ templateData.prompt_name || templateData.templateName }}</el-descriptions-item>
          <el-descriptions-item label="行业类型">{{ templateData.industry_type || templateData.industryType || '-' }}</el-descriptions-item>
          <el-descriptions-item label="模板编码">{{ templateData.prompt_key || templateData.templateCode || '-' }}</el-descriptions-item>
          <el-descriptions-item label="节点数量">{{ nodes.length }} 个</el-descriptions-item>
        </el-descriptions>
      </el-card>

      <div v-show="viewMode === 'canvas'" class="canvas-container" ref="canvasContainer">
        <div class="canvas-toolbar">
          <el-button-group>
            <el-button size="mini" @click="addNode(1)" type="success" plain>开始节点</el-button>
            <el-button size="mini" @click="addNode(2)" plain>消息节点</el-button>
            <el-button size="mini" @click="addNode(3)" type="warning" plain>判断节点</el-button>
            <el-button size="mini" @click="addNode(4)" type="info" plain>等待节点</el-button>
            <el-button size="mini" @click="addNode(6)" plain>API节点</el-button>
            <el-button size="mini" @click="addNode(5)" type="danger" plain>结束节点</el-button>
          </el-button-group>
          <el-button size="mini" @click="autoLayout" icon="el-icon-sort" style="margin-left:8px">自动排列</el-button>
        </div>
        <div class="canvas-area" ref="canvasArea"
             @mousedown="onCanvasMouseDown"
             @mousemove="onCanvasMouseMove"
             @mouseup="onCanvasMouseUp">
          <svg class="canvas-lines" v-if="nodes.length > 1">
            <defs>
              <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
                <polygon points="0 0, 10 3.5, 0 7" fill="#409EFF" />
              </marker>
            </defs>
            <line v-for="(edge, idx) in edges" :key="'e'+idx"
                  :x1="edge.x1" :y1="edge.y1" :x2="edge.x2" :y2="edge.y2"
                  stroke="#409EFF" stroke-width="2" marker-end="url(#arrowhead)" />
          </svg>
          <div v-for="(node, index) in nodes" :key="'n'+index"
               class="canvas-node"
               :class="'node-type-' + node.nodeType"
               :style="{ left: node.x + 'px', top: node.y + 'px' }"
               @mousedown.stop="onNodeMouseDown($event, index)">
            <div class="node-title">
              <span>{{ node.nodeName }}</span>
              <el-tag size="mini" :type="getNodeTypeColor(node.nodeType)">{{ getNodeTypeText(node.nodeType) }}</el-tag>
            </div>
            <div class="node-body" v-if="node.messageTemplate">
              <div class="node-msg">{{ node.messageTemplate.substring(0, 50) }}{{ node.messageTemplate.length > 50 ? '...' : '' }}</div>
            </div>
            <div class="node-actions">
              <el-button size="mini" type="text" icon="el-icon-edit" @click.stop="editNode(index)"></el-button>
              <el-button size="mini" type="text" icon="el-icon-delete" @click.stop="removeNode(index)" style="color:#F56C6C"></el-button>
            </div>
          </div>
        </div>
      </div>

      <div v-show="viewMode === 'list'" class="list-container">
        <el-card shadow="never">
          <div slot="header">
            <div style="display:flex;justify-content:space-between;align-items:center">
              <span>节点列表（{{ nodes.length }}个）</span>
              <el-button type="primary" size="small" @click="showAddNodeDialog = true">
                <i class="el-icon-plus"></i> 添加节点
              </el-button>
            </div>
          </div>
          <el-timeline>
            <el-timeline-item
              v-for="(node, index) in nodes"
              :key="index"
              :type="getNodeTypeColor(node.nodeType)"
            >
              <el-card shadow="hover" class="timeline-node-card">
                <div style="display:flex;justify-content:space-between;align-items:center">
                  <div>
                    <span style="font-weight:bold">{{ node.nodeName }}</span>
                    <el-tag size="small" :type="getNodeTypeColor(node.nodeType)" style="margin-left:8px">{{ getNodeTypeText(node.nodeType) }}</el-tag>
                  </div>
                  <div>
                    <el-button size="mini" type="text" icon="el-icon-edit" @click="editNode(index)">编辑</el-button>
                    <el-button size="mini" type="text" icon="el-icon-delete" @click="removeNode(index)" style="color:#F56C6C">删除</el-button>
                  </div>
                </div>
                <div v-if="node.messageTemplate" style="margin-top:8px;font-size:12px;color:#606266;white-space:pre-wrap;background:#f5f7fa;padding:8px;border-radius:4px">{{ node.messageTemplate }}</div>
                <div v-if="node.nodeType === 3 && node.conditionExpr" style="margin-top:8px">
                  <el-tag size="small" type="warning">条件分支</el-tag>
                  <span style="font-size:12px;color:#909399;margin-left:4px">{{ node.conditionExpr }}</span>
                </div>
              </el-card>
            </el-timeline-item>
          </el-timeline>
        </el-card>
      </div>
    </template>

    <el-dialog :title="editingNodeIndex >= 0 ? '编辑节点' : '添加节点'" :visible.sync="nodeDialogVisible" width="600px" append-to-body>
      <el-form :model="nodeForm" label-width="100px" size="small">
        <el-form-item label="节点名称">
          <el-input v-model="nodeForm.nodeName" placeholder="节点名称" />
        </el-form-item>
        <el-form-item label="节点类型">
          <el-select v-model="nodeForm.nodeType" style="width:100%">
            <el-option label="开始节点" :value="1" />
            <el-option label="消息节点" :value="2" />
            <el-option label="判断节点" :value="3" />
            <el-option label="等待节点" :value="4" />
            <el-option label="结束节点" :value="5" />
            <el-option label="API调用节点" :value="6" />
          </el-select>
        </el-form-item>
        <el-form-item label="节点编码">
          <el-input v-model="nodeForm.nodeCode" placeholder="节点编码" />
        </el-form-item>
        <el-form-item label="下一节点编码">
          <el-input v-model="nodeForm.nextNodeCode" placeholder="下一节点编码" />
        </el-form-item>
        <el-form-item v-if="nodeForm.nodeType === 2" label="消息模板">
          <el-input v-model="nodeForm.messageTemplate" type="textarea" :rows="4" placeholder="消息模板，支持{变量}占位符" />
        </el-form-item>
        <el-form-item v-if="nodeForm.nodeType === 3" label="条件表达式">
          <el-input v-model="nodeForm.conditionExpr" type="textarea" :rows="4" placeholder='条件分支JSON' />
        </el-form-item>
        <el-form-item v-if="nodeForm.nodeType === 4" label="等待配置">
          <el-input v-model="nodeForm.nodeConfig" type="textarea" :rows="3" placeholder='等待配置JSON' />
        </el-form-item>
        <el-form-item v-if="nodeForm.nodeType === 6" label="API配置">
          <el-input v-model="nodeForm.nodeConfig" type="textarea" :rows="3" placeholder='API调用配置JSON' />
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="nodeDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmNode">确定</el-button>
      </div>
    </el-dialog>

    <el-dialog title="添加节点" :visible.sync="showAddNodeDialog" width="400px" append-to-body>
      <div style="display:flex;flex-direction:column;gap:8px">
        <el-button @click="addNode(1); showAddNodeDialog=false" type="success" plain>开始节点</el-button>
        <el-button @click="addNode(2); showAddNodeDialog=false" plain>消息节点</el-button>
        <el-button @click="addNode(3); showAddNodeDialog=false" type="warning" plain>判断节点</el-button>
        <el-button @click="addNode(4); showAddNodeDialog=false" type="info" plain>等待节点</el-button>
        <el-button @click="addNode(6); showAddNodeDialog=false" plain>API节点</el-button>
        <el-button @click="addNode(5); showAddNodeDialog=false" type="danger" plain>结束节点</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getPrompt, listPrompts, updatePrompt } from '@/api/workflow/lobster'

export default {
  name: 'LobsterCanvas',
  data() {
    return {
      templateId: null,
      templateData: null,
      nodes: [],
      viewMode: 'canvas',
      saving: false,
      nodeDialogVisible: false,
      showAddNodeDialog: false,
      editingNodeIndex: -1,
      nodeForm: {},
      dragging: false,
      dragIndex: -1,
      dragOffsetX: 0,
      dragOffsetY: 0
    }
  },
  computed: {
    edges() {
      const result = []
      for (let i = 0; i < this.nodes.length - 1; i++) {
        const from = this.nodes[i]
        const to = this.nodes[i + 1]
        if (from && to && from.x !== undefined && to.x !== undefined) {
          result.push({
            x1: from.x + 90,
            y1: from.y + 40,
            x2: to.x + 90,
            y2: to.y + 40
          })
        }
      }
      return result
    }
  },
  created() {
    this.templateId = this.$route.query.templateId
    if (this.templateId) {
      this.loadTemplate()
    }
  },
  methods: {
    loadTemplate() {
      getPrompt(this.templateId).then(res => {
        this.templateData = res.data || {}
        if (this.templateData.prompt_content) {
          try {
            const parsed = JSON.parse(this.templateData.prompt_content)
            this.nodes = (parsed.nodes || []).map((n, i) => ({
              ...n,
              x: n.x || 100 + (i % 4) * 220,
              y: n.y || 80 + Math.floor(i / 4) * 120
            }))
          } catch (e) {
            this.nodes = []
          }
        }
      }).catch(() => {
        this.$message.error('加载模板失败')
      })
    },
    goBack() {
      this.$router.push('/lobster/production-workflow/template')
    },
    addNode(type) {
      const names = { 1: '开始', 2: '消息', 3: '判断', 4: '等待', 5: '结束', 6: 'API调用' }
      const codes = { 1: 'START', 2: 'MSG', 3: 'DECISION', 4: 'WAIT', 5: 'END', 6: 'API' }
      const idx = this.nodes.length + 1
      this.nodes.push({
        nodeType: type,
        nodeName: names[type] + '_' + idx,
        nodeCode: codes[type] + '_' + idx,
        nextNodeCode: '',
        messageTemplate: '',
        conditionExpr: '',
        nodeConfig: '',
        x: 100 + (idx % 4) * 220,
        y: 80 + Math.floor(idx / 4) * 120
      })
    },
    editNode(index) {
      this.editingNodeIndex = index
      this.nodeForm = { ...this.nodes[index] }
      this.nodeDialogVisible = true
    },
    confirmNode() {
      if (this.editingNodeIndex >= 0) {
        const pos = { x: this.nodes[this.editingNodeIndex].x, y: this.nodes[this.editingNodeIndex].y }
        this.$set(this.nodes, this.editingNodeIndex, { ...this.nodeForm, ...pos })
      }
      this.nodeDialogVisible = false
      this.editingNodeIndex = -1
    },
    removeNode(index) {
      this.$confirm('确定删除该节点吗？', '提示', { type: 'warning' }).then(() => {
        this.nodes.splice(index, 1)
      })
    },
    autoLayout() {
      const cols = 4
      this.nodes.forEach((node, i) => {
        this.$set(node, 'x', 100 + (i % cols) * 220)
        this.$set(node, 'y', 80 + Math.floor(i / cols) * 120)
      })
    },
    saveWorkflow() {
      this.saving = true
      const content = JSON.stringify({ nodes: this.nodes.map(n => {
        const { x, y, ...rest } = n
        return rest
      }) })
      updatePrompt(this.templateId, {
        promptContent: content
      }).then(res => {
        if (res.code === 200) {
          this.$message.success('保存成功')
        } else {
          this.$message.error(res.msg || '保存失败')
        }
      }).catch(err => {
        this.$message.error('保存失败：' + (err.message || ''))
      }).finally(() => {
        this.saving = false
      })
    },
    onNodeMouseDown(e, index) {
      this.dragging = true
      this.dragIndex = index
      this.dragOffsetX = e.clientX - this.nodes[index].x
      this.dragOffsetY = e.clientY - this.nodes[index].y
    },
    onCanvasMouseMove(e) {
      if (!this.dragging || this.dragIndex < 0) return
      const rect = this.$refs.canvasArea.getBoundingClientRect()
      const x = e.clientX - this.dragOffsetX
      const y = e.clientY - this.dragOffsetY
      this.$set(this.nodes[this.dragIndex], 'x', Math.max(0, x - rect.left))
      this.$set(this.nodes[this.dragIndex], 'y', Math.max(0, y - rect.top))
    },
    onCanvasMouseUp() {
      this.dragging = false
      this.dragIndex = -1
    },
    onCanvasMouseDown() {},
    getNodeTypeText(type) {
      const map = { 1: '开始', 2: '消息', 3: '判断', 4: '等待', 5: '结束', 6: 'API' }
      return map[type] || '未知'
    },
    getNodeTypeColor(type) {
      const map = { 1: 'success', 2: '', 3: 'warning', 4: 'info', 5: 'danger', 6: '' }
      return map[type] || ''
    }
  }
}
</script>

<style scoped>
.workflow-canvas-page { padding: 16px; }
.canvas-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; padding: 12px 16px; background: #fff; border-radius: 4px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); }
.header-left { display: flex; align-items: center; gap: 12px; }
.header-title { font-size: 16px; font-weight: bold; }
.header-right { display: flex; align-items: center; }
.info-card { margin-bottom: 16px; }
.no-template { text-align: center; padding: 100px 0; }
.canvas-container { position: relative; }
.canvas-toolbar { margin-bottom: 12px; }
.canvas-area { position: relative; width: 100%; height: 600px; border: 1px solid #dcdfe6; border-radius: 4px; background: #fafafa; overflow: hidden; }
.canvas-lines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
.canvas-node { position: absolute; width: 180px; background: #fff; border: 2px solid #dcdfe6; border-radius: 8px; cursor: move; user-select: none; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
.canvas-node:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.15); }
.canvas-node.node-type-1 { border-color: #67C23A; }
.canvas-node.node-type-2 { border-color: #409EFF; }
.canvas-node.node-type-3 { border-color: #E6A23C; }
.canvas-node.node-type-4 { border-color: #909399; }
.canvas-node.node-type-5 { border-color: #F56C6C; }
.canvas-node.node-type-6 { border-color: #409EFF; }
.node-title { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; border-bottom: 1px solid #ebeef5; font-size: 13px; font-weight: bold; }
.node-body { padding: 8px 12px; }
.node-msg { font-size: 12px; color: #606266; white-space: pre-wrap; }
.node-actions { padding: 4px 8px; text-align: right; border-top: 1px solid #ebeef5; }
.list-container { margin-top: 16px; }
.timeline-node-card { margin-bottom: 4px; }
</style>
