<!--
  WidgetPanel.vue — 左侧组件库面板

  功能：
  - 分类展示（基础/营销/工具）
  - 点击添加到预览区末尾
  - 拖拽到预览区（由 SortableJS group 处理）
  - 搜索过滤
-->
<template>
  <aside class="widget-panel">
    <div class="panel-header">
      <span class="panel-title">🧩 组件库</span>
      <span class="panel-count">{{ totalCount }}个</span>
    </div>

    <!-- 搜索 -->
    <div class="panel-search">
      <el-input
        v-model="searchText"
        placeholder="搜索组件..."
        size="small"
        clearable
        prefix-icon="Search"
      />
    </div>

    <!-- 分类列表 -->
    <div class="category-list">
      <div
        v-for="cat in filteredCategories"
        :key="cat.key"
        class="category-section"
      >
        <div class="category-title" @click="toggleCategory(cat.key)">
          <span>{{ cat.label }}</span>
          <span class="cat-badge">{{ getCategoryComponents(cat.key).length }}</span>
          <span class="cat-arrow" :class="{ open: expandedCategories[cat.key] }">▼</span>
        </div>

        <TransitionGroup
          v-if="expandedCategories[cat.key]"
          name="widget-list"
          tag="div"
          class="widget-grid"
        >
          <div
            v-for="comp in getCategoryComponents(cat.key)"
            :key="comp.type"
            class="widget-card"
            :title="comp.description"
            draggable="true"
            :class="{ 'is-dragging-src': draggingType === comp.type }"
            @click="handleAdd(comp.type)"
            @dragstart="handleDragStart(comp.type, $event)"
            @dragend="draggingType = null"
          >
            <div class="widget-thumb"><img :src="thumbnailFor(comp.type)" alt="" draggable="false" /></div>
            <div class="widget-label">{{ comp.label }}</div>
          </div>
        </TransitionGroup>
      </div>
    </div>

    <div v-if="noResults" class="no-results">
      <div class="nr-icon">🔍</div>
      <div class="nr-text">未找到匹配组件</div>
    </div>
  </aside>
</template>

<script setup>
import { ref, computed } from 'vue'
import { CATEGORIES, getComponentsByCategory, COMPONENT_REGISTRY } from '../utils/componentRegistry.js'
import thumbnailFor from '../utils/thumbnails.js'

const emit = defineEmits(['add-component'])

// 正在拖拽的组件类型（用于高亮反馈）
const draggingType = ref(null)

const searchText = ref('')

// 手风琴：默认只展开第一个分类（基础组件）
const expandedCategories = ref(
  Object.fromEntries(CATEGORIES.map((c, i) => [c.key, i === 0]))
)

const grouped = computed(() => getComponentsByCategory())

const filteredCategories = computed(() => {
  return CATEGORIES.filter(cat =>
    getCategoryComponents(cat.key).length > 0
  )
})

const totalCount = computed(() =>
  Object.values(COMPONENT_REGISTRY).length
)

const noResults = computed(() => {
  if (!searchText.value) return false
  return filteredCategories.value.length === 0
})

function getCategoryComponents(catKey) {
  const list = grouped.value[catKey] || []
  if (!searchText.value) return list
  const q = searchText.value.toLowerCase()
  return list.filter(c =>
    c.label.toLowerCase().includes(q) ||
    c.type.toLowerCase().includes(q) ||
    c.description.toLowerCase().includes(q)
  )
}

function toggleCategory(key) {
  // 手风琴：展开当前，收起其他
  if (expandedCategories.value[key]) {
    expandedCategories.value[key] = false
  } else {
    expandedCategories.value = Object.fromEntries(
      CATEGORIES.map(c => [c.key, c.key === key])
    )
  }
}

function handleAdd(type) {
  emit('add-component', type)
}

// 启动 HTML5 拖拽：把组件 type 写入 dataTransfer，供预览区 drop 接收
function handleDragStart(type, event) {
  draggingType.value = type
  if (event.dataTransfer) {
    event.dataTransfer.effectAllowed = 'copy'
    // 关键：写 type，预览区 drop 时读取（含 fallback 到 dataset）
    event.dataTransfer.setData('text/plain', type)
    try { event.dataTransfer.setData('application/x-litedesign-component', type) } catch (e) { /* 忽略 */ }
  }
}
</script>

<style scoped>
.widget-panel {
  width: 210px;
  background: #fff;
  border-right: 1px solid #eee;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex-shrink: 0;
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 14px 8px;
}

.panel-title {
  font-size: 15px;
  font-weight: 700;
  color: #333;
}

.panel-count {
  font-size: 11px;
  color: #999;
  background: #f5f5f5;
  padding: 2px 8px;
  border-radius: 10px;
}

.panel-search {
  padding: 0 12px 8px;
}

.category-list {
  flex: 1;
  overflow-y: auto;
  padding: 0 8px 12px;
}

.category-section {
  margin-bottom: 4px;
}

.category-title {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  font-size: 13px;
  font-weight: 600;
  color: #666;
  cursor: pointer;
  border-radius: 6px;
  user-select: none;
}

.category-title:hover {
  background: #f5f5f5;
}

.cat-badge {
  font-size: 10px;
  color: #aaa;
  font-weight: 400;
  margin-left: auto;
}

.cat-arrow {
  font-size: 9px;
  color: #bbb;
  transition: transform 0.2s;
}

.cat-arrow.open {
  transform: rotate(180deg);
}

.widget-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  padding: 2px 0 8px;
}

.widget-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 6px;
  border: 1px solid #f0f0f0;
  border-radius: 10px;
  cursor: grab;
  transition: all 0.15s;
  user-select: none;
}

.widget-card:hover {
  border-color: #7C3AED;
  background: #f5f3ff;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(124, 58, 237, 0.1);
}

.widget-card:active {
  cursor: grabbing;
}

/* 拖拽源高亮反馈 */
.widget-card.is-dragging-src {
  opacity: 0.5;
  border-style: dashed;
  border-color: #7C3AED;
  background: #f5f3ff;
}

.widget-thumb {
  width: 84px;
  height: 56px;
  border-radius: 6px;
  overflow: hidden;
  background: #faf8ff;
  border: 1px solid #eef0f5;
  box-shadow: 0 1px 3px rgba(0,0,0,.04);
}

.widget-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.widget-label {
  font-size: 11px;
  color: #555;
  text-align: center;
  line-height: 1.2;
}

.no-results {
  padding: 40px 0;
  text-align: center;
  color: #bbb;
}

.nr-icon {
  font-size: 32px;
  margin-bottom: 6px;
}

.nr-text {
  font-size: 13px;
}

/* Transition */
.widget-list-enter-active,
.widget-list-leave-active {
  transition: all 0.2s ease;
}
.widget-list-enter-from {
  opacity: 0;
  transform: translateY(-8px);
}
.widget-list-leave-to {
  opacity: 0;
  transform: translateY(8px);
}
</style>
