<template>
  <div class="strategy-layer" :class="`layer-${layerKey}`" :style="{ borderColor: color }">
    <div class="layer-header" :style="{ background: color }">
      <span class="layer-icon">{{ icon }}</span>
      <span class="layer-name">{{ label }}</span>
      <span class="layer-objective-count">{{ objectives.length }} 个目标</span>
      <el-dropdown trigger="click" @command="onLayerAction">
        <el-button class="layer-more-btn" size="small" text>
          <el-icon><MoreFilled /></el-icon>
        </el-button>
        <template #dropdown>
          <el-dropdown-item command="rename">重命名</el-dropdown-item>
          <el-dropdown-item command="color">更换颜色</el-dropdown-item>
          <el-dropdown-item command="icon">更换图标</el-dropdown-item>
        </template>
      </el-dropdown>
    </div>
    <div class="layer-body" ref="bodyRef">
      <!-- vuedraggable: 每层独立group → 禁止跨层拖拽 -->
      <draggable
        v-if="objectives.length > 0"
        :list="objectives"
        :group="layerKey"
        item-key="name"
        :animation="150"
        @end="onDragEnd"
        class="layer-draggable"
      >
        <template #item="{ element, index }">
          <div class="layer-node-wrapper">
            <MapNode
              :key="`${layerKey}-${index}`"
              :ref="el => setNodeRef(`${layerKey}-${index}`, el)"
              :objective="element"
              :node-key="`${layerKey}-${index}`"
              :index="index"
              :level="getNodeLevel(`${layerKey}-${index}`)"
              :progress-data="getNodeProgress(`${layerKey}-${index}`)"
              :draggable="false"
              :is-linking-source="linkingFromKey === `${layerKey}-${index}`"
              :is-linking-target="!!linkingFromKey && linkingFromKey !== `${layerKey}-${index}`"
              :is-drag-connect-target="dragConnectTarget === `${layerKey}-${index}`"
              :link-eligibility="linkEligibilityMap?.[`${layerKey}-${index}`] ?? null"
              :icon-map="iconMap"
              :kpi-name-map="kpiNameMap"
              :all-kpis="allKpis"
              :chain-dimmed="chainNodeKeys.length > 0 && !chainNodeKeys.includes(`${layerKey}-${index}`)"
              @click="onNodeClick(layerKey, index, element)"
              @edit="$emit('edit-objective', { dimKey: layerKey, idx: index, obj: element })"
              @delete="$emit('delete-objective', { dimKey: layerKey, idx: index })"
              @link-click="$emit('start-link', { key: `${layerKey}-${index}`, obj: element })"
              @link-drag-start="(e: MouseEvent) => $emit('link-drag-start', e, layerKey, index, element)"
              @kpi-click="(code: string) => $emit('kpi-click', code)"
              @plan-click="$emit('show-plan-list', { dimKey: layerKey, idx: index, obj: element })"
              @edit-kr="(p: any) => $emit('edit-kr', { dimKey: layerKey, idx: index, obj: element, ki: p.index, kr: p.kr })"
              @add-kr="$emit('add-kr', { dimKey: layerKey, idx: index, obj: element })"
              />
          </div>
        </template>
      </draggable>

      <!-- 空状态占位提示 -->
      <div v-if="objectives.length === 0" class="layer-empty">
        <el-empty description="暂无目标" :image-size="60">
          <el-button type="primary" size="small" @click="$emit('add-objective', layerKey)">
            点击 + 添加目标
          </el-button>
        </el-empty>
      </div>

      <!-- 底部添加按钮 -->
      <el-button type="primary" size="small" class="layer-add-btn" @click="$emit('add-objective', layerKey)">
        + 添加目标
      </el-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import { MoreFilled } from '@element-plus/icons-vue'
import draggable from 'vuedraggable'
import MapNode from './MapNode.vue'

const props = defineProps<{
  layerKey: string
  label: string
  icon: string
  color: string
  objectives: any[]
  linkingFromKey?: string | null
  dragConnectTarget?: string | null
  /** 拖拽连线时的目标合法性：valid=合法高亮 / forbidden=反方向灰显 */
  linkEligibilityMap?: Record<string, 'valid' | 'forbidden'>
  iconMap?: Record<string, string>
  kpiNameMap?: Record<string, string>
  allKpis?: any[]
  /** 因果链查看模式下，不在链上的节点变淡 */
  chainNodeKeys?: string[]
  getNodeLevel: (key: string) => string
  getNodeProgress: (key: string) => any
}>()

const emit = defineEmits<{
  (e: 'add-objective', dimKey: string): void
  (e: 'edit-objective', payload: { dimKey: string; idx: number; obj: any }): void
  (e: 'delete-objective', payload: { dimKey: string; idx: number }): void
  (e: 'start-link', payload: { key: string; obj: any }): void
  (e: 'link-drag-start', event: MouseEvent, dimKey: string, oi: number, obj: any): void
  (e: 'kpi-click', code: string): void
  (e: 'show-plan-list', payload: { dimKey: string; idx: number; obj: any }): void
  (e: 'node-click', dimKey: string, oi: number, obj: any): void
  (e: 'reorder', dimKey: string): void
  (e: 'layer-action', cmd: string): void
  (e: 'update:label', val: string): void
  (e: 'update:color', val: string): void
  (e: 'update:icon', val: string): void
  (e: 'edit-kr', payload: { dimKey: string; idx: number; obj: any; ki: number; kr: any }): void
  (e: 'add-kr', payload: { dimKey: string; idx: number; obj: any }): void
}>()

const bodyRef = ref<HTMLElement | null>(null)

// Node DOM refs for line calculation (reactive so parent can aggregate)
const nodeRefs = reactive<Record<string, any>>({})
function setNodeRef(key: string, el: any) {
  if (el) nodeRefs[key] = el
}

// Expose nodeRefs to parent for connection line calculation
defineExpose({ nodeRefs, bodyRef })

function onLayerAction(cmd: string) {
  emit('layer-action', cmd)
}

/**
 * 拖拽排序完成回调（由 vuedraggable/SortableJS 触发）
 * 由于 :list 传递的是父级响应式数组的引用，SortableJS 已直接完成了数组重排，
 * 此处仅需通知父级重算连线位置和触发保存
 */
function onDragEnd() {
  emit('reorder', props.layerKey)
}

function onNodeClick(dimKey: string, oi: number, obj: any) {
  emit('node-click', dimKey, oi, obj)
}
</script>

<script lang="ts">
import { reactive } from 'vue'

export default {
  inheritAttrs: false,
}
</script>

<style scoped>
.strategy-layer {
  border: none;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  background: #fff;
  min-height: 120px;
  width: 100%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
  transition: box-shadow 0.2s;
  overflow: hidden;
}
.strategy-layer:hover {
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}

.layer-header {
  padding: 12px 16px;
  color: #fff;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 600;
  flex-shrink: 0;
  user-select: none;
  letter-spacing: 0.3px;
}

.layer-icon {
  font-size: 18px;
  line-height: 1;
}

.layer-name {
  flex: 1;
}

.layer-objective-count {
  font-size: 11px;
  opacity: 0.85;
  font-weight: 400;
  background: rgba(255,255,255,0.2);
  padding: 2px 10px;
  border-radius: 10px;
}

.layer-more-btn {
  color: rgba(255,255,255,0.7) !important;
  padding: 2px !important;
}
.layer-more-btn:hover {
  color: #fff !important;
}

.layer-body {
  padding: 12px 14px;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
  background: #f8f9fb;
}

/* vuedraggable 容器 */
.layer-draggable {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 40px;
}

/* 每个节点包裹元素 */
.layer-node-wrapper {
  flex: 0 0 auto;
  width: 100%;
}

/* 空状态 */
.layer-empty {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 80px;
  padding: 12px 0;
}

/* 底部添加按钮 */
.layer-add-btn {
  width: 100% !important;
  flex-shrink: 0;
  margin-top: 6px;
}
</style>
