<template>
  <svg class="connection-svg" ref="svgRef">
    <defs>
      <!-- 跨层箭头（↓方向） -->
      <marker
        id="arrow-down"
        markerWidth="10"
        markerHeight="7"
        refX="5"
        refY="7"
        orient="auto"
      >
        <polygon points="0,0 10,3.5 0,7" fill="#909399" />
      </marker>
      <!-- 同层箭头（→方向） -->
      <marker
        id="arrow-right"
        markerWidth="10"
        markerHeight="7"
        refX="10"
        refY="3.5"
        orient="auto"
      >
        <polygon points="0,0 10,3.5 0,7" fill="#409eff" />
      </marker>
      <!-- 高亮箭头 -->
      <marker
        id="arrow-active"
        markerWidth="10"
        markerHeight="7"
        refX="10"
        refY="3.5"
        orient="auto"
      >
        <polygon points="0,0 10,3.5 0,7" fill="#f56c6c" />
      </marker>
    </defs>

    <!-- 跨层固定箭头：每层底部 → 下层顶部 -->
    <line
      v-for="(line, idx) in crossLayerLines"
      :key="'cross-' + idx"
      :x1="line.x1"
      :y1="line.y1"
      :x2="line.x2"
      :y2="line.y2"
      stroke="#909399"
      stroke-width="2"
      stroke-dasharray="6,3"
      marker-end="url(#arrow-down)"
      class="cross-layer-line"
    />

    <!-- 同层用户手动连线箭头（→方向） -->
    <g v-for="(conn, idx) in layerConnections" :key="'conn-' + idx">
      <path
        :d="conn.path"
        :class="[
          'conn-line',
          { 'conn-selected': selectedIdx === idx },
        ]"
        :stroke="selectedIdx === idx ? '#f56c6c' : '#409eff'"
        :stroke-width="selectedIdx === idx ? 3 : 2"
        fill="none"
        marker-end="url(#arrow-right)"
        @click.stop="$emit('select-connection', idx)"
        @mouseenter="hoverIdx = idx"
        @mouseleave="hoverIdx = null"
      />
      <!-- hover提示 -->
      <rect
        v-if="hoverIdx === idx"
        :x="conn.mx - 50"
        :y="conn.my - 10"
        width="100"
        height="20"
        rx="4"
        fill="rgba(0,0,0,0.65)"
        class="conn-hover-bg"
      />
      <text
        v-if="hoverIdx === idx"
        :x="conn.mx"
        :y="conn.my + 4"
        text-anchor="middle"
        fill="#fff"
        font-size="11"
        class="conn-hover-text"
      >
        点击选中
      </text>
      <!-- 删除按钮（选中时） -->
      <g v-if="selectedIdx === idx">
        <rect
          :x="conn.mx - 20"
          :y="conn.my - 28"
          width="88"
          height="24"
          rx="12"
          fill="#f56c6c"
          class="del-btn-bg"
          @click.stop="$emit('delete-connection', idx)"
        />
        <text
          :x="conn.mx + 24"
          :y="conn.my - 12"
          text-anchor="middle"
          fill="#fff"
          font-size="12"
          font-weight="bold"
          class="del-btn-text"
          @click.stop="$emit('delete-connection', idx)"
        >
          ✕ 删除连线
        </text>
      </g>
    </g>

    <!-- 绘制中的临时线 -->
    <line
      v-if="tempLine"
      :x1="tempLine.x1"
      :y1="tempLine.y1"
      :x2="tempLine.x2"
      :y2="tempLine.y2"
      stroke="#e6a23c"
      stroke-width="2"
      stroke-dasharray="6,3"
      marker-end="url(#arrow-down)"
    />
  </svg>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'

const props = defineProps({
  /** 各层DOM元素引用，格式：{ financial: HTMLElement, customer: HTMLElement, ... } */
  layerRefs: { type: Object, required: true },
  /** 节点DOM元素引用，格式：{ 'financial-0': HTMLElement, ... } */
  nodeRefs: { type: Object, default: () => ({}) },
  /** 层顺序列表 */
  layerKeys: { type: Array, default: () => ['financial', 'customer', 'process', 'learning'] },
  /** 同层连线数据 [{from: 'financial-0', to: 'financial-1'}] */
  connections: { type: Array, default: () => [] },
  /** 临时连线 */
  tempLine: { type: Object, default: null },
  /** 容器尺寸变化触发重算 */
  containerKey: { type: Number, default: 0 },
  /** 视角方向：cascade(级联,上层→下层) / causal(因果,下层→上层) */
  viewDirection: { type: String, default: 'cascade' },
})

const emit = defineEmits(['select-connection', 'delete-connection'])

const svgRef = ref(null)
const hoverIdx = ref(null)
const selectedIdx = ref(null)
const layerConnections = ref([])
const crossLayerLines = ref([])

/**
 * 计算跨层固定箭头
 * cascade: 从上层底部中心 → 下层顶部中心（管理视角，上层驱动下层）
 * causal:  从下层顶部中心 → 上层底部中心（因果视角，下层驱动上层）
 */
function calcCrossLayerLines() {
  const lines = []
  const keys = props.layerKeys
  const isCausal = props.viewDirection === 'causal'
  for (let i = 0; i < keys.length - 1; i++) {
    const upperEl = props.layerRefs[keys[i]]
    const lowerEl = props.layerRefs[keys[i + 1]]
    if (!upperEl || !lowerEl) continue

    const ur = upperEl.getBoundingClientRect()
    const lr = lowerEl.getBoundingClientRect()
    const svg = svgRef.value
    if (!svg) continue
    const svgRect = svg.getBoundingClientRect()

    if (isCausal) {
      // 因果视角：从下层顶 → 上层底（箭头向上）
      lines.push({
        x1: lr.left + lr.width / 2 - svgRect.left,
        y1: lr.top - svgRect.top,
        x2: ur.left + ur.width / 2 - svgRect.left,
        y2: ur.bottom - svgRect.top,
      })
    } else {
      // 级联视角：从上层底 → 下层顶（箭头向下）
      lines.push({
        x1: ur.left + ur.width / 2 - svgRect.left,
        y1: ur.bottom - svgRect.top,
        x2: lr.left + lr.width / 2 - svgRect.left,
        y2: lr.top - svgRect.top,
      })
    }
  }
  crossLayerLines.value = lines
}

/**
 * 计算同层用户连线
 * 使用贝塞尔曲线从源节点右侧 → 目标节点左侧
 */
function calcLayerConnections() {
  const result = []
  const svg = svgRef.value
  if (!svg) return
  const svgRect = svg.getBoundingClientRect()

  for (const conn of props.connections) {
    const fromEl = props.nodeRefs[conn.from]
    const toEl = props.nodeRefs[conn.to]
    if (!fromEl || !toEl) continue

    const fr = fromEl.getBoundingClientRect()
    const tr = toEl.getBoundingClientRect()

    // 源节点右侧中点 → 目标节点左侧中点
    const x1 = fr.right - svgRect.left
    const y1 = fr.top + fr.height / 2 - svgRect.top
    const x2 = tr.left - svgRect.left
    const y2 = tr.top + tr.height / 2 - svgRect.top

    // 贝塞尔曲线控制点
    const dx = Math.abs(x2 - x1) * 0.5
    const cp1x = x1 + dx
    const cp1y = y1
    const cp2x = x2 - dx
    const cp2y = y2

    const path = `M ${x1} ${y1} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${x2} ${y2}`

    result.push({
      path,
      mx: (x1 + x2) / 2,
      my: (y1 + y2) / 2,
      from: conn.from,
      to: conn.to,
    })
  }
  layerConnections.value = result
}

function recalcAll() {
  calcCrossLayerLines()
  calcLayerConnections()
}

// 暴露给父组件调用
defineExpose({ recalcAll })

onMounted(() => {
  nextTick(recalcAll)
})
</script>

<style scoped>
.connection-svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 5;
  pointer-events: none;
  overflow: visible;
}
.cross-layer-line {
  pointer-events: none;
}
.conn-line {
  cursor: pointer;
  transition: stroke 0.15s, stroke-width 0.15s;
  pointer-events: stroke;
}
.conn-line:hover {
  stroke: #e6a23c !important;
  stroke-width: 4 !important;
}
.conn-selected {
  stroke: #f56c6c !important;
  stroke-width: 3;
}
.del-btn-bg {
  cursor: pointer;
  pointer-events: all;
}
.del-btn-bg:hover {
  fill: #e74c3c !important;
}
.del-btn-text {
  cursor: pointer;
  pointer-events: all;
  user-select: none;
}
.conn-hover-bg,
.conn-hover-text {
  pointer-events: none;
}
</style>
