<template>
  <div class="flex flex-col h-full">
    <!-- 头部 -->
    <div v-if="!hideHeader" class="flex items-center justify-between px-4 py-2 bg-base-300 text-xs text-base-content/60">
      <span>人设树</span>
      <span v-if="store.highlightedNodeIds.size > 0" class="text-primary">
        已高亮 {{ store.highlightedNodeIds.size }} 个节点
      </span>
    </div>

    <!-- 搜索框 -->
    <div class="px-4 py-2 bg-base-200 border-b border-base-300 relative">
      <input
        type="text"
        v-model="searchQuery"
        @input="onSearchInput"
        @focus="showSuggestions = true"
        @keydown.down.prevent="navigateSuggestion(1)"
        @keydown.up.prevent="navigateSuggestion(-1)"
        @keydown.enter.prevent="selectSuggestion"
        @keydown.escape="showSuggestions = false"
        placeholder="搜索节点..."
        class="input input-xs input-bordered w-full"
      />
      <!-- 自动补全下拉 -->
      <div
        v-show="showSuggestions && filteredNodes.length > 0"
        class="absolute left-4 right-4 top-full mt-1 bg-base-100 border border-base-300 rounded shadow-lg max-h-48 overflow-y-auto z-50"
      >
        <div
          v-for="(node, index) in filteredNodes"
          :key="node.id"
          @click="selectNode(node)"
          @mouseenter="suggestionIndex = index"
          :class="[
            'px-3 py-1.5 cursor-pointer text-xs flex items-center gap-2',
            index === suggestionIndex ? 'bg-primary/20' : 'hover:bg-base-200'
          ]"
        >
          <!-- 标签用圆形，分类用方形 -->
          <span
            v-if="node.type === '分类'"
            class="w-2 h-2 rounded-sm"
            :style="{ backgroundColor: getNodeColorById(node) }"
          ></span>
          <span
            v-else
            class="w-2 h-2 rounded-full"
            :style="{ backgroundColor: getNodeColorById(node) }"
          ></span>
          <span>{{ node.name }}</span>
          <span class="text-base-content/40 text-xs">{{ node.dimension || node.type }}</span>
        </div>
      </div>
    </div>

    <!-- SVG 容器 -->
    <div ref="containerRef" class="flex-1 overflow-hidden bg-base-100">
      <svg ref="svgRef" class="w-full h-full" @click="handleSvgClick"></svg>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
import * as d3 from 'd3'
import { useGraphStore } from '../stores/graph'
import { dimColors, getNodeStyle } from '../config/nodeStyle'
import { applyHighlight } from '../utils/highlight'

const props = defineProps({
  hideHeader: {
    type: Boolean,
    default: false
  }
})

const store = useGraphStore()

const containerRef = ref(null)
const svgRef = ref(null)

// zoom 实例和主 g 元素
let zoom = null
let mainG = null
let treeWidth = 0
let treeHeight = 0

// 搜索相关
const searchQuery = ref('')
const showSuggestions = ref(false)
const suggestionIndex = ref(0)

// 获取所有节点列表
const allNodes = computed(() => {
  const nodes = store.graphData.nodes || {}
  return Object.entries(nodes).map(([id, node]) => ({
    id,
    ...node
  }))
})

// 过滤后的节点（搜索结果）
const filteredNodes = computed(() => {
  if (!searchQuery.value.trim()) return []
  const query = searchQuery.value.toLowerCase()
  return allNodes.value
    .filter(node => node.name && node.name.toLowerCase().includes(query))
    .slice(0, 20) // 最多显示20个结果
})

// 搜索输入
function onSearchInput() {
  showSuggestions.value = true
  suggestionIndex.value = 0
}

// 键盘导航
function navigateSuggestion(delta) {
  const len = filteredNodes.value.length
  if (len === 0) return
  suggestionIndex.value = (suggestionIndex.value + delta + len) % len
}

// 选中建议项
function selectSuggestion() {
  if (filteredNodes.value.length > 0) {
    selectNode(filteredNodes.value[suggestionIndex.value])
  }
}

// 选中节点（激活）
function selectNode(node) {
  store.selectNode(node)
  searchQuery.value = ''
  showSuggestions.value = false
}

// 根据节点数据获取颜色（用于搜索列表）
function getNodeColorById(node) {
  return getNodeStyle(node).color
}

// 节点元素映射
let nodeElements = {}
let currentRoot = null

// 处理节点点击
function handleNodeClick(event, d) {
  event.stopPropagation()
  store.selectNode(d)
}

// 渲染树（缩放模式）
function renderTree() {
  const svg = d3.select(svgRef.value)
  svg.selectAll('*').remove()
  nodeElements = {}

  const treeData = store.treeData
  if (!treeData || !treeData.id) return

  const container = containerRef.value
  if (!container) return

  const width = container.clientWidth
  const height = container.clientHeight

  svg.attr('viewBox', `0 0 ${width} ${height}`)

  // 创建层级数据
  const root = d3.hierarchy(treeData)
  currentRoot = root

  // 智能计算树的尺寸
  const allNodes = root.descendants()
  const maxDepth = d3.max(allNodes, d => d.depth)
  const leafCount = allNodes.filter(d => !d.children).length

  // 高度：基于叶子节点数量
  treeHeight = Math.max(800, leafCount * 20 + 100)
  // 宽度：根据深度
  treeWidth = Math.max(600, (maxDepth + 1) * 150 + 50)

  // 创建缩放行为
  zoom = d3.zoom()
    .scaleExtent([0.1, 3])
    .on('zoom', (e) => {
      mainG.attr('transform', e.transform)
    })

  svg.call(zoom)

  // 创建主组
  mainG = svg.append('g')

  // 创建树布局
  const treeLayout = d3.tree()
    .size([treeHeight - 50, treeWidth - 100])
    .separation((a, b) => a.parent === b.parent ? 1 : 1.2)

  treeLayout(root)

  // 内容组（带偏移）
  const contentG = mainG.append('g')
    .attr('transform', 'translate(25, 25)')

  // 绘制边
  contentG.append('g')
    .attr('class', 'tree-edges')
    .selectAll('.tree-link')
    .data(root.links())
    .join('path')
    .attr('class', 'tree-link')
    .attr('fill', 'none')
    .attr('stroke', '#9b59b6')
    .attr('stroke-opacity', 0.3)
    .attr('stroke-width', 1)
    .attr('d', d => {
      const midX = (d.source.y + d.target.y) / 2
      return `M${d.source.y},${d.source.x} C${midX},${d.source.x} ${midX},${d.target.x} ${d.target.y},${d.target.x}`
    })

  // 绘制节点
  const nodes = contentG.append('g')
    .attr('class', 'tree-nodes')
    .selectAll('.tree-node')
    .data(root.descendants())
    .join('g')
    .attr('class', 'tree-node')
    .attr('transform', d => `translate(${d.y},${d.x})`)
    .style('cursor', 'pointer')
    .on('click', handleNodeClick)

  // 节点形状（使用统一配置）
  nodes.each(function(d) {
    const el = d3.select(this)
    const style = getNodeStyle(d)

    if (style.shape === 'rect') {
      el.append('rect')
        .attr('class', 'tree-shape')
        .attr('x', -4)
        .attr('y', -4)
        .attr('width', 8)
        .attr('height', 8)
        .attr('rx', 1)
        .attr('fill', style.color)
        .attr('stroke', 'rgba(255,255,255,0.5)')
        .attr('stroke-width', 1)
    } else {
      el.append('circle')
        .attr('class', 'tree-shape')
        .attr('r', style.size / 2)
        .attr('fill', style.color)
        .attr('stroke', 'rgba(255,255,255,0.5)')
        .attr('stroke-width', 1)
    }

    // 记录节点位置（用于 zoomToNode）
    nodeElements[d.data.id] = { element: this, x: d.y + 25, y: d.x + 25 }
  })

  // 节点标签（使用统一配置）
  nodes.append('text')
    .attr('dy', '0.31em')
    .attr('x', d => d.children ? -8 : 8)
    .attr('text-anchor', d => d.children ? 'end' : 'start')
    .attr('fill', d => getNodeStyle(d).text.fill)
    .attr('font-size', d => getNodeStyle(d).text.fontSize)
    .attr('font-weight', d => getNodeStyle(d).text.fontWeight)
    .text(d => {
      const name = d.data.name
      const maxLen = d.children ? 6 : 8
      return name.length > maxLen ? name.slice(0, maxLen) + '…' : name
    })

  // 初始适应视图
  fitToView()
}

// 适应视图（自动缩放以显示全部内容）
function fitToView() {
  if (!zoom || !mainG || !containerRef.value) return

  const container = containerRef.value
  const width = container.clientWidth
  const height = container.clientHeight

  // 计算缩放比例以适应容器
  const scaleX = width / treeWidth
  const scaleY = height / treeHeight
  const scale = Math.min(scaleX, scaleY, 1) * 0.9 // 留一点边距

  // 计算居中偏移
  const translateX = (width - treeWidth * scale) / 2
  const translateY = (height - treeHeight * scale) / 2

  const svg = d3.select(svgRef.value)
  svg.call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale))
}

// 定位到指定节点
function zoomToNode(nodeId) {
  const nodeInfo = nodeElements[nodeId]
  if (!nodeInfo || !zoom || !containerRef.value) return

  const container = containerRef.value
  const width = container.clientWidth
  const height = container.clientHeight

  // 计算平移使节点居中
  const scale = 1
  const translateX = width / 2 - nodeInfo.x * scale
  const translateY = height / 2 - nodeInfo.y * scale

  const svg = d3.select(svgRef.value)
  svg.transition().duration(300).call(
    zoom.transform,
    d3.zoomIdentity.translate(translateX, translateY).scale(scale)
  )
}

// 更新选中/高亮状态
function updateSelection() {
  applyHighlight(svgRef.value, store.highlightedNodeIds, store.walkedEdgeSet, store.selectedNodeId)
}

// 点击空白取消激活
function handleSvgClick(event) {
  if (!event.target.closest('.tree-node')) {
    store.clearSelection()
  }
}

// 监听选中/高亮变化，统一更新
watch(() => store.selectedNodeId, (nodeId, oldNodeId) => {
  updateSelection()
  if (nodeId && nodeId !== oldNodeId) {
    zoomToNode(nodeId)
  }
})

watch(() => store.highlightedNodeIds.size, updateSelection)

// 监听布局变化，过渡结束后重新适应视图
function handleTransitionEnd(e) {
  if (['width', 'height', 'flex', 'flex-grow', 'flex-shrink'].includes(e.propertyName)) {
    nextTick(() => {
      renderTree()
    })
  }
}

let transitionParent = null

onMounted(() => {
  nextTick(() => {
    renderTree()
  })

  // 监听父容器的过渡结束事件
  if (containerRef.value) {
    let parent = containerRef.value.parentElement
    while (parent && !parent.classList.contains('transition-all')) {
      parent = parent.parentElement
    }
    if (parent) {
      transitionParent = parent
      parent.addEventListener('transitionend', handleTransitionEnd)
    }
  }
})

onUnmounted(() => {
  if (transitionParent) {
    transitionParent.removeEventListener('transitionend', handleTransitionEnd)
  }
})
</script>
