<template>
  <div class="x6-demo">
    <div class="x6-demo__header">
      <h2>AntV X6 v3 Phase 0 验证</h2>
      <div class="x6-demo__status">
        <span :class="['x6-demo__badge', status]">{{ statusText }}</span>
        <a-button size="mini" @click="rebuild">重建画布</a-button>
        <a-button size="mini" @click="exportData">导出 JSON</a-button>
      </div>
    </div>
    <div ref="containerRef" class="x6-demo__canvas" />
    <div class="x6-demo__log">
      <div v-for="(log, i) in logs" :key="i" class="x6-demo__log-line">[{{ log.t }}] {{ log.msg }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref, reactive } from 'vue'
import { Graph } from '@antv/x6'
// v3: 插件全部从核心包内置导出（不再需要 @antv/x6-plugin-* 独立包）
import { Selection, Snapline, History, MiniMap, Scroller } from '@antv/x6'

const containerRef = ref<HTMLElement | null>(null)
const status = ref<'pending' | 'ok' | 'fail'>('pending')
const statusText = ref('初始化中...')
const logs = reactive<{ t: string; msg: string }[]>([])

let graph: Graph | null = null

function log(msg: string) {
  const now = new Date().toLocaleTimeString('zh-CN', { hour12: false })
  logs.unshift({ t: now, msg })
  if (logs.length > 20) logs.pop()
}

function buildGraph() {
  if (!containerRef.value) return
  log('开始创建 Graph 实例 (X6 v3)')

  graph = new Graph({
    container: containerRef.value,
    background: { color: '#F2F7FA' },
    grid: { visible: true, size: 10 },
    mousewheel: { enabled: true, modifiers: ['ctrl'], minScale: 0.5, maxScale: 2 },
  })

  // v3: 插件通过 graph.use() 注册，类从核心包导入
  graph.use(new Selection({ enabled: true, rubberband: true }))
  log('✅ Selection 插件（框选）注册成功')

  graph.use(new Snapline({ enabled: true }))
  log('✅ Snapline 插件（对齐线）注册成功')

  graph.use(new History({ enabled: true }))
  log('✅ History 插件（撤销重做）注册成功')

  graph.use(new Scroller({ enabled: true, pannable: true }))
  log('✅ Scroller 插件（画布滚动）注册成功')

  graph.use(new MiniMap({ width: 200, height: 120 }))
  log('✅ MiniMap 插件（小地图）注册成功')

  // 渲染节点 + 边（模拟 DevFlow 多工程依赖图）
  graph.fromJSON({
    nodes: [
      { id: 'devflow', shape: 'rect', x: 80, y: 80, width: 140, height: 48,
        label: 'DevFlow\n(Tauri+Vue3)', attrs: { body: { fill: '#e8f3ff', stroke: '#165dff' } } },
      { id: 'df-types', shape: 'rect', x: 320, y: 40, width: 120, height: 40,
        label: 'df-types', attrs: { body: { fill: '#fff7e8', stroke: '#ff7d00' } } },
      { id: 'df-storage', shape: 'rect', x: 320, y: 120, width: 120, height: 40,
        label: 'df-storage', attrs: { body: { fill: '#fff7e8', stroke: '#ff7d00' } } },
      { id: 'df-ai', shape: 'rect', x: 540, y: 80, width: 120, height: 40,
        label: 'df-ai', attrs: { body: { fill: '#e8ffea', stroke: '#00b42a' } } },
    ],
    edges: [
      { source: 'devflow', target: 'df-types', labels: [{ text: '类库' }] },
      { source: 'devflow', target: 'df-storage', labels: [{ text: '类库' }] },
      { source: 'df-storage', target: 'df-ai', labels: [{ text: '依赖' }] },
    ],
  })
  log('✅ 渲染 4 节点 + 3 边（DevFlow 依赖图 mock）')

  // 事件验证
  graph.on('node:click', ({ node }) => {
    log(`🖱️ 节点点击: ${node.id}`)
  })
  graph.on('blank:click', () => {
    log('🖱️ 空白处点击')
  })

  status.value = 'ok'
  statusText.value = '渲染成功'
  log('🎉 Phase 0 验证通过：X6 v3 在当前环境正常工作')
}

function rebuild() {
  if (graph) {
    graph.dispose()
    log('画布已销毁，重建中...')
  }
  status.value = 'pending'
  statusText.value = '重建中'
  setTimeout(buildGraph, 100)
}

function exportData() {
  if (!graph) return
  const json = graph.toJSON()
  log(`📤 导出 JSON: ${JSON.stringify(json).slice(0, 80)}...`)
  console.log('X6 graph JSON:', json)
}

onMounted(() => {
  try {
    buildGraph()
  } catch (e) {
    status.value = 'fail'
    statusText.value = '验证失败'
    log(`❌ 错误: ${e instanceof Error ? e.message : String(e)}`)
    console.error(e)
  }
})

onBeforeUnmount(() => {
  if (graph) {
    graph.dispose()
    graph = null
    log('画布已销毁（组件卸载）')
  }
})
</script>

<style scoped>
.x6-demo {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 16px;
  gap: 12px;
}
.x6-demo__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.x6-demo__header h2 {
  margin: 0;
  font-size: 16px;
}
.x6-demo__status {
  display: flex;
  align-items: center;
  gap: 8px;
}
.x6-demo__badge {
  padding: 2px 10px;
  border-radius: 10px;
  font-size: 12px;
  font-weight: 500;
}
.x6-demo__badge.pending { background: #fff7e8; color: #ff7d00; }
.x6-demo__badge.ok { background: #e8ffea; color: #00b42a; }
.x6-demo__badge.fail { background: #ffece8; color: #f53f3f; }
.x6-demo__canvas {
  flex: 1;
  min-height: 400px;
  border: 1px solid #e5e6eb;
  border-radius: 4px;
  overflow: hidden;
}
.x6-demo__log {
  height: 120px;
  overflow-y: auto;
  background: #1d2129;
  border-radius: 4px;
  padding: 8px 12px;
  font-family: 'Consolas', monospace;
  font-size: 12px;
}
.x6-demo__log-line {
  color: #c9cdd4;
  line-height: 1.6;
}
</style>
