<!--
  节点面板组件
  展示所有可用的节点类型，支持拖拽到画布
-->
<script setup lang="ts">
import { computed } from 'vue'
import { Collapse, CollapsePanel, Empty } from 'ant-design-vue'
import * as Icons from '@ant-design/icons-vue'
import { useWorkflowStore } from '../stores/useWorkflowStore'
import { NODE_CATEGORIES } from '../mock/nodeTypes'
import type { NodeTypeMetadata } from '#/types/workflow'

const workflowStore = useWorkflowStore()

/**
 * 按分类分组的节点
 */
const groupedNodes = computed(() => workflowStore.nodeTypesByCategory)

/**
 * 拖拽开始
 */
function onDragStart(event: DragEvent, nodeType: NodeTypeMetadata) {
  if (!event.dataTransfer) return

  // 设置拖拽数据
  event.dataTransfer.effectAllowed = 'copy'
  event.dataTransfer.setData(
    'application/vueflow',
    JSON.stringify({
      nodeTypeId: nodeType.id,
      metadata: nodeType,
    }),
  )

  // 添加拖拽样式
  const target = event.target as HTMLElement
  target.classList.add('dragging')
}

/**
 * 拖拽结束
 */
function onDragEnd(event: DragEvent) {
  const target = event.target as HTMLElement
  target.classList.remove('dragging')
}

/**
 * 获取图标组件
 */
function getIconComponent(iconName?: string) {
  if (!iconName) return Icons.AppstoreOutlined
  return (Icons as any)[iconName] || Icons.AppstoreOutlined
}

/**
 * 获取分类信息
 */
function getCategoryInfo(category: string) {
  return NODE_CATEGORIES.find((c) => c.category === category) || {
    category,
    label: category,
    icon: 'AppstoreOutlined',
  }
}
</script>

<template>
  <div class="node-palette">
    <div class="palette-header">
      <h3>节点类型</h3>
      <p class="palette-description">拖拽节点到画布创建</p>
    </div>

    <div class="palette-content">
      <Collapse
        v-model:activeKey="activeKeys"
        :bordered="false"
        expand-icon-position="end"
      >
        <CollapsePanel
          v-for="(nodes, category) in groupedNodes"
          :key="category"
          :header="getCategoryInfo(category).label"
        >
          <template #extra>
            <component
              :is="getIconComponent(getCategoryInfo(category).icon)"
              class="category-icon"
            />
          </template>

          <div v-if="nodes.length > 0" class="node-list">
            <div
              v-for="nodeType in nodes"
              :key="nodeType.id"
              class="node-item"
              draggable="true"
              :title="nodeType.description"
              @dragstart="onDragStart($event, nodeType)"
              @dragend="onDragEnd"
            >
              <div class="node-item-icon">
                <component :is="getIconComponent(nodeType.icon)" />
              </div>
              <div class="node-item-content">
                <div class="node-item-name">{{ nodeType.displayName }}</div>
                <div class="node-item-description">{{ nodeType.description }}</div>
              </div>
            </div>
          </div>

          <Empty v-else description="暂无节点" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
        </CollapsePanel>
      </Collapse>
    </div>
  </div>
</template>

<script lang="ts">
export default {
  name: 'NodePalette',
  data() {
    return {
      activeKeys: ['api', 'database', 'logic', 'notification', 'transform'],
    }
  },
}
</script>

<style scoped lang="less">
.node-palette {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-right: 1px solid #e8e8e8;

  .palette-header {
    padding: 16px;
    border-bottom: 1px solid #e8e8e8;

    h3 {
      margin: 0 0 4px;
      font-size: 16px;
      font-weight: 600;
    }

    .palette-description {
      margin: 0;
      font-size: 12px;
      color: #999;
    }
  }

  .palette-content {
    flex: 1;
    overflow-y: auto;
    padding: 8px 0;

    :deep(.ant-collapse) {
      background: transparent;
      border: none;

      .ant-collapse-item {
        border: none;
        border-bottom: 1px solid #f0f0f0;

        &:last-child {
          border-bottom: none;
        }
      }

      .ant-collapse-header {
        padding: 12px 16px;
        font-weight: 500;
        color: #333;

        .category-icon {
          font-size: 16px;
          color: #1890ff;
        }
      }

      .ant-collapse-content-box {
        padding: 8px 12px;
      }
    }
  }

  .node-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .node-item {
    display: flex;
    align-items: flex-start;
    padding: 10px 12px;
    background: #fafafa;
    border: 1px solid #e8e8e8;
    border-radius: 6px;
    cursor: grab;
    transition: all 0.2s;

    &:hover {
      background: #f0f7ff;
      border-color: #1890ff;
      box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15);
    }

    &:active {
      cursor: grabbing;
    }

    &.dragging {
      opacity: 0.5;
    }

    .node-item-icon {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 32px;
      height: 32px;
      margin-right: 12px;
      background: #fff;
      border: 1px solid #d9d9d9;
      border-radius: 4px;
      font-size: 16px;
      color: #1890ff;
      flex-shrink: 0;
    }

    .node-item-content {
      flex: 1;
      min-width: 0;
    }

    .node-item-name {
      font-size: 14px;
      font-weight: 500;
      color: #333;
      margin-bottom: 4px;
    }

    .node-item-description {
      font-size: 12px;
      color: #999;
      line-height: 1.4;
      overflow: hidden;
      text-overflow: ellipsis;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
    }
  }
}
</style>

