<template>
  <svg class="connection-svg" ref="svgRef">
    <defs>
      <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="8" refY="3.5" orient="auto">
        <polygon points="0 0, 10 3.5, 0 7" fill="#409eff" />
      </marker>
      <marker id="arrowhead-warn" markerWidth="10" markerHeight="7" refX="8" refY="3.5" orient="auto">
        <polygon points="0 0, 10 3.5, 0 7" fill="#e6a23c" />
      </marker>
      <marker id="arrowhead-red" markerWidth="10" markerHeight="7" refX="8" refY="3.5" orient="auto">
        <polygon points="0 0, 10 3.5, 0 7" fill="#f56c6c" />
      </marker>
    </defs>

    <!-- 固定跨层箭头：贝塞尔曲线（从下层泳道到上层泳道） -->
    <path
      v-for="(arrow, idx) in fixedLayerArrows"
      :key="'fixed-' + idx"
      :d="arrow.path"
      fill="none"
      stroke="#c0c4cc"
      stroke-width="1.5"
      stroke-dasharray="6,4"
      marker-end="url(#arrowhead)"
      class="fixed-layer-arrow"
    >
      <title>{{ arrow.from }} → {{ arrow.to }}</title>
    </path>

    <!-- 用户自定义连线：贝塞尔曲线 + 语义样式 + 因果链高亮 -->
    <g v-for="(line, idx) in connectionLines" :key="'conn-' + idx">
      <path
        :d="line.path"
        :class="['conn-line', {
          'conn-selected': selectedConnIdx === idx,
          'conn-chain': chainActive && chainConnIdxs.includes(idx),
          'conn-dim': chainActive && !chainConnIdxs.includes(idx),
        }]"
        :style="{ '--from-color': line.fromColor, '--to-color': line.toColor }"
        :stroke="strokeFor(line, idx)"
        :stroke-width="selectedConnIdx === idx ? 3 : (chainActive && chainConnIdxs.includes(idx) ? 3.5 : 2)"
        :stroke-dasharray="isNegative(line) ? '7,4' : 'none'"
        fill="none"
        :marker-end="markerFor(line, idx)"
        @click.stop="$emit('select-connection', idx)"
        @mouseenter="onConnEnter(idx)"
        @mouseleave="onConnLeave"
      />
      <!-- 连线语义标签 -->
      <g
        v-if="line.label"
        :class="['conn-label', { 'conn-label-dim': chainActive && !chainConnIdxs.includes(idx) }]"
        @click.stop="$emit('select-connection', idx)"
      >
        <rect
          :x="line.mx - labelW(line) / 2"
          :y="line.my - 22"
          :width="labelW(line)"
          height="16"
          rx="8"
          class="conn-label-bg"
          :style="{ '--label-color': isNegative(line) ? '#f56c6c' : '#409eff' }"
        />
        <text :x="line.mx" :y="line.my - 10.5" text-anchor="middle" font-size="10.5" class="conn-label-text">{{ line.label }}</text>
      </g>
    </g>

    <!-- 连线提示浮层 -->
    <g v-if="hoverConnIdx !== null && connectionLines[hoverConnIdx] && hoverConnIdx !== selectedConnIdx">
      <rect
        :x="connectionLines[hoverConnIdx].mx - 60"
        :y="connectionLines[hoverConnIdx].my - 36"
        width="120" height="22" rx="4" fill="rgba(0,0,0,0.65)"
        class="conn-hover-bg"
      />
      <text
        :x="connectionLines[hoverConnIdx].mx"
        :y="connectionLines[hoverConnIdx].my - 21"
        text-anchor="middle" fill="#fff" font-size="11"
        class="conn-hover-text"
      >点击选中连线</text>
    </g>

    <!-- 删除按钮（选中连线时） -->
    <g v-if="selectedConnIdx !== null && connectionLines[selectedConnIdx]">
      <rect
        :x="connectionLines[selectedConnIdx].mx - 18"
        :y="connectionLines[selectedConnIdx].my - 24"
        width="88" height="24" rx="12" fill="#f56c6c" class="del-btn-bg"
        @click.stop="$emit('delete-connection', selectedConnIdx)"
      />
      <text
        :x="connectionLines[selectedConnIdx].mx"
        :y="connectionLines[selectedConnIdx].my - 8"
        text-anchor="middle" fill="#fff" font-size="13" font-weight="bold"
        class="del-btn-text"
        @click.stop="$emit('delete-connection', selectedConnIdx)"
      >✕ 删除连线</text>
    </g>

    <!-- 绘制中的临时线 -->
    <path
      v-if="tempLine"
      :d="tempLinePath"
      fill="none"
      stroke="#e6a23c"
      stroke-width="2"
      stroke-dasharray="6,3"
      marker-end="url(#arrowhead-warn)"
    />
  </svg>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { getChainForConnection } from '../../utils/chainGraph'

const props = defineProps<{
  connectionLines: any[]
  selectedConnIdx: number | null
  tempLine: any
  fixedLayerArrows: { from: string; to: string; path: string }[]
}>()

const emit = defineEmits<{
  (e: 'select-connection', idx: number): void
  (e: 'delete-connection', idx: number): void
  (e: 'chain-hover', nodes: string[] | null): void
}>()

const svgRef = ref<SVGSVGElement | null>(null)
const hoverConnIdx = ref<number | null>(null)
const hoverChain = ref<{ nodes: string[]; connIdxs: number[] } | null>(null)

const chainActive = computed(() => hoverChain.value !== null)
const chainConnIdxs = computed<number[]>(() => hoverChain.value?.connIdxs || [])

function isNegative(line: any) {
  return line && line.effect === 'negative'
}

function strokeFor(line: any, idx: number) {
  if (selectedConnIdx.value === idx) return '#f56c6c'
  if (chainActive.value && chainConnIdxs.value.includes(idx)) return '#e6a23c'
  if (chainActive.value) return '#c0c4cc'
  return isNegative(line) ? '#f56c6c' : '#409eff'
}

function markerFor(line: any, idx: number) {
  if (selectedConnIdx.value === idx) return 'url(#arrowhead-red)'
  if (chainActive.value && chainConnIdxs.value.includes(idx)) return 'url(#arrowhead-warn)'
  return isNegative(line) ? 'url(#arrowhead-red)' : 'url(#arrowhead)'
}

function labelW(line: any) {
  return (line.label ? line.label.length : 0) * 12 + 16
}

function onConnEnter(idx: number) {
  hoverConnIdx.value = idx
  const chain = getChainForConnection(props.connectionLines.map(toConnLike), idx)
  hoverChain.value = chain
  emit('chain-hover', chain ? chain.nodes : null)
}

function onConnLeave() {
  hoverConnIdx.value = null
  hoverChain.value = null
  emit('chain-hover', null)
}

/** connectionLines 条目（含 x1/y1/x2/y2）转成 {from,to} 形状供链算法使用 */
function toConnLike(line: any, idx: number) {
  const conns = props.connectionLines
  // 从原数据推断 from/to：算法只需 from/to 字段
  return {
    from: line.from || `n-${idx}`,
    to: line.to || `n-${idx}`,
  }
}

const tempLinePath = computed(() => {
  if (!props.tempLine) return ''
  const { x1, y1, x2, y2 } = props.tempLine
  const dx = Math.max(Math.abs(x2 - x1) * 0.5, 40)
  return `M ${x1} ${y1} C ${x1 + dx} ${y1}, ${x2 - dx} ${y2}, ${x2} ${y2}`
})

defineExpose({ svgRef })
</script>

<style scoped>
.connection-svg {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  z-index: 5; pointer-events: none;
  overflow: visible;
}
.conn-line {
  cursor: pointer; transition: stroke .15s, stroke-width .15s, opacity .2s;
  pointer-events: stroke;
}
.conn-line:hover { stroke: #e6a23c !important; stroke-width: 4 !important; cursor: pointer; }
.conn-line.conn-chain { filter: drop-shadow(0 0 3px rgba(230,162,60,0.65)); }
.conn-line.conn-dim { opacity: 0.25; }
.conn-selected { stroke: #f56c6c !important; stroke-width: 3; }
.conn-label { cursor: pointer; pointer-events: all; transition: opacity .2s; }
.conn-label-dim { opacity: 0.25; }
.conn-label-bg { fill: rgba(255,255,255,0.92); stroke: var(--label-color, #409eff); stroke-width: 1; }
.conn-label-text { fill: #303133; font-weight: 600; pointer-events: none; }
.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; }
.fixed-layer-arrow {
  pointer-events: none;
  opacity: 0.5;
}
.conn-hover-bg,
.conn-hover-text {
  pointer-events: none;
}
</style>
