<!--
  Vue Flow 工作流设计器主组件
  集成节点面板、配置面板、画布等
-->
<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import { VueFlow, useVueFlow, Panel, PanelPosition } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls'
import { MiniMap } from '@vue-flow/minimap'
import {
  Button,
  Space,
  Divider,
  message,
  Modal,
  Input,
  Dropdown,
  Menu,
  MenuItem,
} from 'ant-design-vue'
import {
  SaveOutlined,
  UndoOutlined,
  RedoOutlined,
  ClearOutlined,
  DownloadOutlined,
  UploadOutlined,
  EyeOutlined,
  PlayCircleOutlined,
} from '@ant-design/icons-vue'

// Vue Flow 样式
import '@vue-flow/core/dist/style.css'
import '@vue-flow/core/dist/theme-default.css'
import '@vue-flow/controls/dist/style.css'
import '@vue-flow/minimap/dist/style.css'

// 组件
import NodePalette from './components/NodePalette.vue'
import NodeConfigPanel from './components/NodeConfigPanel.vue'
import BaseNode from './components/BaseNode.vue'

// Store
import { useWorkflowStore } from './stores/useWorkflowStore'

// Mock 数据
import { EXAMPLE_WORKFLOW } from './mock/workflows'

defineOptions({ name: 'VueFlowWorkflowDesigner' })

const workflowStore = useWorkflowStore()

// Vue Flow 实例
const { 
  onConnect, 
  addEdges, 
  fitView, 
  zoomIn, 
  zoomOut, 
  zoomTo,
  toObject,
  fromObject,
  project,
  getNodes,
  getEdges,
} = useVueFlow({
  deleteKeyCode: 'Delete',
  multiSelectionKeyCode: ['Meta', 'Control'],
  panOnScroll: true,
  zoomOnScroll: true,
  panOnDrag: [1, 2], // 鼠标中键和右键拖拽
  preventScrolling: false,
})

/** 工作流名称编辑框可见性 */
const workflowNameVisible = ref(false)

/** 工作流名称输入 */
const workflowNameInput = ref('')

/** 是否显示预览 */
const showPreview = ref(false)

/** 预览数据 */
const previewData = ref<any>(null)

/**
 * 自定义节点类型映射
 * 将所有节点类型都使用 BaseNode 渲染
 */
const nodeTypes = computed(() => {
  const types: Record<string, any> = {}
  workflowStore.nodeTypes.forEach((nodeType) => {
    types[nodeType.id] = BaseNode
  })
  return types
})

/**
 * 统计信息
 */
const statistics = computed(() => ({
  nodeCount: workflowStore.vueFlowNodes.length,
  edgeCount: workflowStore.vueFlowEdges.length,
  categoryCount: new Set(
    workflowStore.vueFlowNodes.map((n) => n.data.metadata?.category),
  ).size,
}))

/**
 * 连接节点事件
 */
onConnect((connection) => {
  if (connection.source && connection.target) {
    workflowStore.addEdge(connection.source, connection.target)
    message.success('节点已连接')
  }
})

/**
 * 画布拖拽放置事件
 */
function onDrop(event: DragEvent) {
  event.preventDefault()

  if (!event.dataTransfer) return

  const data = event.dataTransfer.getData('application/vueflow')
  if (!data) return

  const { nodeTypeId } = JSON.parse(data)
  if (!nodeTypeId) return

  // 计算放置位置（将屏幕坐标转换为流程图坐标）
  const { left, top } = (event.currentTarget as HTMLElement).getBoundingClientRect()
  const position = project({
    x: event.clientX - left,
    y: event.clientY - top,
  })

  // 添加节点
  const nodeId = workflowStore.addNode(nodeTypeId, position)
  if (nodeId) {
    message.success('节点已添加')
    // 选中新节点
    nextTick(() => {
      workflowStore.selectNode(nodeId)
    })
  }
}

/**
 * 画布拖拽悬停事件
 */
function onDragOver(event: DragEvent) {
  event.preventDefault()
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'copy'
  }
}

/**
 * 节点点击事件
 */
function handleNodeClick(event: any) {
  workflowStore.selectNode(event.node.id)
}

/**
 * 边点击事件
 */
function handleEdgeClick(event: any) {
  workflowStore.selectEdge(event.edge.id)
}

/**
 * 画布点击事件（取消选中）
 */
function handlePaneClick() {
  workflowStore.selectNode(null)
  workflowStore.selectEdge(null)
}

/**
 * 节点拖拽结束事件
 */
function handleNodeDragStop(event: any) {
  const { node } = event
  if (node) {
    workflowStore.updateNodePosition(node.id, node.position)
  }
}

/**
 * 保存工作流
 */
function handleSave() {
  const definition = workflowStore.getWorkflowDefinition()
  console.log('保存工作流:', definition)

  // 这里可以调用 API 保存到后端
  // await api.saveWorkflow(definition)

  message.success('工作流已保存')
}

/**
 * 撤销
 */
function handleUndo() {
  workflowStore.undo()
  message.success('已撤销')
}

/**
 * 重做
 */
function handleRedo() {
  workflowStore.redo()
  message.success('已重做')
}

/**
 * 清空画布
 */
function handleClear() {
  Modal.confirm({
    title: '确认清空画布？',
    content: '此操作将清除所有节点和连接线',
    onOk: () => {
      workflowStore.clearWorkflow()
      message.success('画布已清空')
    },
  })
}

/**
 * 导出工作流
 */
function handleExport() {
  const definition = workflowStore.getWorkflowDefinition()
  const dataStr = JSON.stringify(definition, null, 2)
  const blob = new Blob([dataStr], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = `workflow-${definition.name || 'untitled'}-${Date.now()}.json`
  link.click()
  URL.revokeObjectURL(url)
  message.success('工作流已导出')
}

/**
 * 导入工作流
 */
function handleImport() {
  const input = document.createElement('input')
  input.type = 'file'
  input.accept = '.json'
  input.onchange = (e: any) => {
    const file = e.target?.files?.[0]
    if (!file) return

      const reader = new FileReader()
      reader.onload = (event) => {
        try {
        const definition = JSON.parse(event.target?.result as string)
        workflowStore.loadWorkflow(definition)
          nextTick(() => {
          fitView({ padding: 0.2 })
          })
        message.success('工作流已导入')
        } catch (error) {
          message.error('文件格式错误')
        console.error(error)
      }
    }
    reader.readAsText(file)
  }
  input.click()
}

/**
 * 预览工作流定义
 */
function handlePreview() {
  previewData.value = workflowStore.getWorkflowDefinition()
  showPreview.value = true
}

/**
 * 加载示例工作流
 */
function loadExample() {
  Modal.confirm({
    title: '加载示例工作流？',
    content: '当前工作流将被替换',
    onOk: () => {
      workflowStore.loadWorkflow(EXAMPLE_WORKFLOW)
      nextTick(() => {
        fitView({ padding: 0.2 })
      })
      message.success('示例工作流已加载')
    },
  })
}

/**
 * 编辑工作流名称
 */
function handleEditName() {
  workflowNameInput.value = workflowStore.workflow.name
  workflowNameVisible.value = true
}

/**
 * 保存工作流名称
 */
function handleSaveName() {
  if (workflowNameInput.value.trim()) {
    workflowStore.workflow.name = workflowNameInput.value.trim()
    workflowNameVisible.value = false
    message.success('名称已更新')
  }
}

/**
 * 小地图节点颜色
 */
function getMinimapNodeColor(node: any) {
  const categoryColors: Record<string, string> = {
    api: '#1890ff',
    database: '#52c41a',
    logic: '#faad14',
    notification: '#f5222d',
    transform: '#722ed1',
    other: '#8c8c8c',
  }
  return categoryColors[node.data?.metadata?.category || 'other'] || '#8c8c8c'
}

/**
 * 初始化
 */
onMounted(() => {
  nextTick(() => {
    fitView({ padding: 0.2 })
  })
})
</script>

<template>
  <div class="workflow-designer">
    <!-- 顶部工具栏 -->
    <div class="designer-toolbar">
      <div class="toolbar-left">
        <h2 class="workflow-title" @click="handleEditName">
          {{ workflowStore.workflow.name || '未命名工作流' }}
        </h2>
        <span class="workflow-id">{{ workflowStore.workflow.id || 'new' }}</span>
      </div>

      <div class="toolbar-right">
      <Space>
          <!-- 撤销/重做 -->
          <Button
          size="small"
            :disabled="!workflowStore.canUndo"
            @click="handleUndo"
          >
            <UndoOutlined />
          撤销
        </Button>
          <Button
            size="small"
            :disabled="!workflowStore.canRedo"
            @click="handleRedo"
          >
            <RedoOutlined />
          重做
        </Button>
        
        <Divider type="vertical" />
        
          <!-- 保存 -->
          <Button type="primary" size="small" @click="handleSave">
            <SaveOutlined />
          保存
        </Button>

          <!-- 更多操作 -->
          <Dropdown>
            <Button size="small">
              更多
              <DownOutlined />
            </Button>
            <template #overlay>
              <Menu>
                <MenuItem @click="handlePreview">
                  <EyeOutlined />
                  预览定义
                </MenuItem>
                <MenuItem @click="handleExport">
                  <DownloadOutlined />
                  导出
                </MenuItem>
                <MenuItem @click="handleImport">
                  <UploadOutlined />
                  导入
                </MenuItem>
                <MenuItem @click="loadExample">
                  <PlayCircleOutlined />
                  加载示例
                </MenuItem>
                <MenuItem danger @click="handleClear">
                  <ClearOutlined />
                  清空画布
                </MenuItem>
              </Menu>
            </template>
          </Dropdown>
      </Space>
      </div>
    </div>

    <!-- 主内容区 -->
    <div class="designer-content">
      <!-- 左侧节点面板 -->
      <div class="left-panel">
        <NodePalette />
      </div>

      <!-- 中间画布 -->
      <div
        class="canvas-container"
        @drop="onDrop"
        @dragover="onDragOver"
      >
      <VueFlow
          v-model:nodes="workflowStore.vueFlowNodes"
          v-model:edges="workflowStore.vueFlowEdges"
        :node-types="nodeTypes"
          :default-viewport="{ zoom: 1, x: 0, y: 0 }"
        :min-zoom="0.1"
          :max-zoom="2"
        fit-view-on-init
          @node-click="handleNodeClick"
          @edge-click="handleEdgeClick"
          @pane-click="handlePaneClick"
          @node-drag-stop="handleNodeDragStop"
      >
        <!-- 背景 -->
          <Background pattern-color="#aaa" :gap="16" />
        
        <!-- 控制面板 -->
        <Controls />
        
        <!-- 小地图 -->
        <MiniMap 
          :node-stroke-width="3"
            :node-color="getMinimapNodeColor"
            position="bottom-right"
          />

          <!-- 统计信息 -->
          <Panel :position="PanelPosition.TopLeft" class="stats-panel">
            <div class="stats-content">
              <div class="stat-item">
                <span class="stat-label">节点:</span>
                <span class="stat-value">{{ statistics.nodeCount }}</span>
              </div>
              <div class="stat-item">
                <span class="stat-label">连线:</span>
                <span class="stat-value">{{ statistics.edgeCount }}</span>
            </div>
          </div>
        </Panel>
      </VueFlow>
    </div>

      <!-- 右侧配置面板（通过 Drawer 实现） -->
      <NodeConfigPanel />
      </div>
      
    <!-- 工作流名称编辑对话框 -->
    <Modal
      v-model:open="workflowNameVisible"
      title="编辑工作流名称"
      @ok="handleSaveName"
    >
      <Input v-model:value="workflowNameInput" placeholder="请输入工作流名称" />
    </Modal>

    <!-- 预览对话框 -->
    <Modal
      v-model:open="showPreview"
      title="工作流定义预览"
      width="800px"
      :footer="null"
    >
      <pre class="preview-code">{{ JSON.stringify(previewData, null, 2) }}</pre>
    </Modal>
  </div>
</template>

<style scoped lang="less">
.workflow-designer {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 100px);
  background: #f0f2f5;

  .designer-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 24px;
    background: #fff;
    border-bottom: 1px solid #e8e8e8;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);

    .toolbar-left {
      display: flex;
      align-items: center;
      gap: 12px;

      .workflow-title {
        margin: 0;
        font-size: 18px;
        font-weight: 600;
        color: #333;
        cursor: pointer;
        transition: color 0.2s;

        &:hover {
          color: #1890ff;
        }
      }

      .workflow-id {
        font-size: 12px;
        color: #999;
        font-family: monospace;
        padding: 2px 8px;
        background: #f5f5f5;
        border-radius: 3px;
      }
    }
  }

  .designer-content {
    flex: 1;
    display: flex;
    overflow: hidden;

    .left-panel {
      width: 300px;
  flex-shrink: 0;
      background: #fff;
      border-right: 1px solid #e8e8e8;
      overflow-y: auto;
}

    .canvas-container {
  flex: 1;
  position: relative;
      background: #fafafa;
    }
  }

  .stats-panel {
  background: rgba(255, 255, 255, 0.95);
    padding: 12px 16px;
  border-radius: 6px;
  border: 1px solid #e8e8e8;
  backdrop-filter: blur(8px);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

    .stats-content {
  display: flex;
      gap: 16px;

.stat-item {
  display: flex;
  align-items: center;
        gap: 6px;
        font-size: 13px;

.stat-label {
  color: #666;
}

.stat-value {
  font-weight: 600;
  color: #1890ff;
  background: #f0f7ff;
          padding: 2px 8px;
  border-radius: 4px;
          min-width: 24px;
  text-align: center;
}
      }
    }
  }

  .preview-code {
    max-height: 600px;
    overflow-y: auto;
    padding: 16px;
    background: #f5f5f5;
    border-radius: 4px;
    font-family: 'Courier New', monospace;
    font-size: 12px;
    line-height: 1.6;
  }
}

/* Vue Flow 自定义样式 */
:deep(.vue-flow__node) {
  cursor: pointer;

  &:hover {
  transform: scale(1.02);
    transition: transform 0.2s;
}
}

:deep(.vue-flow__edge) {
  cursor: pointer;

  &:hover path {
  stroke-width: 3px !important;
}

  &.selected path {
  stroke: #722ed1 !important;
  stroke-width: 3px !important;
  }
}

:deep(.vue-flow__controls) {
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid #e8e8e8;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

:deep(.vue-flow__minimap) {
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid #e8e8e8;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
</style>
