<script setup>
import { ref, computed, watch, nextTick } from 'vue';
import { useFlowStore } from '../../store/flowStore';
import { NODE_GROUPS, getAllNodeTypes } from '../../utils/nodeMetadata';

// 从统一管理文件获取所有节点类型
const ALL_NODE_TYPES = getAllNodeTypes();

const flowStore = useFlowStore();
const draggedNode = ref(null);
const searchText = ref('');
const activeTab = ref('all'); // all, recent, favorite
const favorites = ref(JSON.parse(localStorage.getItem('ai-agent-node-favorites') || '[]'));
const recent = ref(JSON.parse(localStorage.getItem('ai-agent-node-recent') || '[]'));
const tooltip = ref({ show: false, text: '', x: 0, y: 0, width: 200, direction: 'left' });
const isFullscreen = ref(false);
let tooltipTimer = null;

// 监听 recent-node-updated 事件，收到后刷新 recent
if (typeof window !== 'undefined') {
  window.addEventListener('recent-node-updated', () => {
    recent.value = JSON.parse(localStorage.getItem('ai-agent-node-recent') || '[]');
  });
}

// 监听全屏状态变化
if (typeof window !== 'undefined') {
  window.addEventListener('fullscreenchange', () => {
    isFullscreen.value = !!(
      document.fullscreenElement ||
      document.webkitFullscreenElement ||
      document.mozFullScreenElement ||
      document.msFullscreenElement
    );
  });
}

// 拖拽事件
const onDragStart = (event, nodeType) => {
  draggedNode.value = nodeType;
  event.dataTransfer.effectAllowed = 'move';
  event.dataTransfer.setData('application/vueflow', nodeType.type);
  event.dataTransfer.setData('text/plain', nodeType.type);
};
const onDragEnd = () => { draggedNode.value = null; };

function getCanvasCenter() {
  const vueFlowRoot = document.querySelector('.vue-flow-container');
  if (!vueFlowRoot) return { x: 200, y: 200 };
  const rect = vueFlowRoot.getBoundingClientRect();
  const centerX = rect.width / 2 + vueFlowRoot.scrollLeft;
  const centerY = rect.height / 2 + vueFlowRoot.scrollTop;
  if (window.vueFlowInstance && typeof window.vueFlowInstance.project === 'function') {
    const pos = window.vueFlowInstance.project({ x: centerX, y: centerY });
    pos.x += Math.random() * 20 - 10;
    pos.y += Math.random() * 20 - 10;
    return pos;
  }
  return { x: centerX, y: centerY };
}

const addNode = (nodeType) => {
  const position = getCanvasCenter();
  const newNode = {
    id: `${nodeType.type}-${Date.now()}`,
    type: nodeType.type,
    position,
    data: {}
  };
  flowStore.addNode(newNode);
  flowStore.selectNode(newNode.id);
  // 记录最近使用
  addRecent(nodeType.type);
};

function addFavorite(type) {
  if (!favorites.value.includes(type)) {
    favorites.value.push(type);
    localStorage.setItem('ai-agent-node-favorites', JSON.stringify(favorites.value));
  }
}
function removeFavorite(type) {
  favorites.value = favorites.value.filter(t => t !== type);
  localStorage.setItem('ai-agent-node-favorites', JSON.stringify(favorites.value));
}
function toggleFavorite(type) {
  if (favorites.value.includes(type)) removeFavorite(type);
  else addFavorite(type);
}
function addRecent(type) {
  recent.value = [type, ...recent.value.filter(t => t !== type)].slice(0, 12);
  localStorage.setItem('ai-agent-node-recent', JSON.stringify(recent.value));
}

const nodeTypeCount = computed(() => {
  const counts = {};
  flowStore.nodes.forEach(node => {
    counts[node.type] = (counts[node.type] || 0) + 1;
  });
  return counts;
});

const allNodeTypes = computed(() => {
  let list = ALL_NODE_TYPES;
  if (searchText.value.trim()) {
    const kw = searchText.value.trim().toLowerCase();
    list = list.filter(n => n.label.toLowerCase().includes(kw) || n.type.toLowerCase().includes(kw));
  }
  return list;
});

const filteredNodeTypes = computed(() => {
  let list = ALL_NODE_TYPES;
  if (searchText.value.trim()) {
    const kw = searchText.value.trim().toLowerCase();
    list = list.filter(n => n.label.toLowerCase().includes(kw) || n.type.toLowerCase().includes(kw));
  }
  if (activeTab.value === 'favorite') {
    list = list.filter(n => favorites.value.includes(n.type));
  } else if (activeTab.value === 'recent') {
    list = recent.value.map(type => list.find(n => n.type === type)).filter(Boolean);
  }
  return list;
});

const groupedNodeTypes = computed(() => {
  // 按分组返回 {group, label, nodes:[]} 数组
  const groups = [];
  NODE_GROUPS.forEach(g => {
    const nodes = filteredNodeTypes.value.filter(n => n.group === g.group || (!n.group && g.group === '其他'));
    if (nodes.length) groups.push({ ...g, nodes });
  });
  // 兜底：如果还有未分组节点，归入“其他”
  const otherNodes = filteredNodeTypes.value.filter(n => !n.group || !NODE_GROUPS.some(g => g.group === n.group));
  if (otherNodes.length && !groups.some(g => g.group === '其他')) {
    groups.push({ group: '其他', label: '其他', nodes: otherNodes });
  }
  return groups;
});

function showTooltip(event, text) {
  tooltip.value.show = true;
  tooltip.value.text = text;

  const rect = event.target.getBoundingClientRect();
  const tooltipWidth = 200;
  const tooltipHeight = 38;
  const gap = 8;

  // 默认向左弹出，垂直居中
  let x = rect.left - tooltipWidth - gap;
  let y = rect.top + (rect.height / 2) - (tooltipHeight / 2);
  let direction = 'left';

  // 边界处理
  if (x < 8) {
    // 左侧空间不足，向右弹出
    x = rect.right + gap;
    direction = 'right';
  }
  // 上下边界
  const minY = 8;
  const maxY = window.innerHeight - tooltipHeight - 8;
  if (y < minY) y = minY;
  if (y > maxY) y = maxY;

  tooltip.value.x = x;
  tooltip.value.y = y;
  tooltip.value.width = tooltipWidth;
  tooltip.value.direction = direction;
}
function showTooltipWithDelay(event, text) {
  clearTimeout(tooltipTimer);
  tooltipTimer = setTimeout(() => showTooltip(event, text), 200);
}
function hideTooltip() {
  clearTimeout(tooltipTimer);
  tooltip.value.show = false;
}
</script>

<template>
  <div class="node-palette">
    <div class="palette-header">
      <div class="palette-tabs">
        <button :class="['tab-btn', {active: activeTab==='all'}]" @click="activeTab='all'">全部</button>
        <button :class="['tab-btn', {active: activeTab==='recent'}]" @click="activeTab='recent'">最近使用</button>
        <button :class="['tab-btn', {active: activeTab==='favorite'}]" @click="activeTab='favorite'">收藏</button>
      </div>
      <input v-model="searchText" class="palette-search" placeholder="搜索节点类型/名称..." />
    </div>
    <div class="palette-content">
      <template v-if="activeTab==='all'">
        <div v-for="group in groupedNodeTypes" :key="group.group" class="node-group">
          <div class="group-label">{{ group.label }}</div>
          <div class="node-types-grid">
            <div v-for="nodeType in group.nodes" :key="nodeType.type" class="node-type-item"
              :class="{ 'dragging': draggedNode?.type === nodeType.type, 'is-favorite': favorites.includes(nodeType.type) }"
              draggable="true"
              @dragstart="onDragStart($event, nodeType)"
              @dragend="onDragEnd"
              @dblclick="addNode(nodeType)"
              @click.right.prevent="toggleFavorite(nodeType.type)"
              @mouseenter="e => showTooltipWithDelay(e, nodeType.description)"
              @mouseleave="hideTooltip()"
            >
              <div class="node-type-icon" :style="{ color: nodeType.color }">
                <i :class="`fa ${nodeType.icon}`"></i>
              </div>
              <div class="node-type-label">
                {{ nodeType.label }}
                <span v-if="nodeTypeCount[nodeType.type]" class="node-count">
                  ({{ nodeTypeCount[nodeType.type] }})
                </span>
                <i class="fa fa-star favorite-icon" v-if="favorites.includes(nodeType.type)" style="color:#f59e0b;margin-left:2px;font-size:13px;"></i>
              </div>
            </div>
          </div>
        </div>
        <div v-if="groupedNodeTypes.length===0" class="empty-tip">无匹配节点</div>
      </template>
      <template v-else>
        <div v-for="group in groupedNodeTypes" :key="group.group" class="node-group">
          <div class="group-label">{{ group.label }}</div>
          <div class="node-types-grid">
            <div v-for="nodeType in group.nodes" :key="nodeType.type" class="node-type-item"
              :class="{ 'dragging': draggedNode?.type === nodeType.type, 'is-favorite': favorites.includes(nodeType.type) }"
              draggable="true"
              @dragstart="onDragStart($event, nodeType)"
              @dragend="onDragEnd"
              @dblclick="addNode(nodeType)"
              @click.right.prevent="toggleFavorite(nodeType.type)"
              @mouseenter="e => showTooltipWithDelay(e, nodeType.description)"
              @mouseleave="hideTooltip()"
            >
              <div class="node-type-icon" :style="{ color: nodeType.color }">
                <i :class="`fa ${nodeType.icon}`"></i>
              </div>
              <div class="node-type-label">
                {{ nodeType.label }}
                <span v-if="nodeTypeCount[nodeType.type]" class="node-count">
                  ({{ nodeTypeCount[nodeType.type] }})
                </span>
                <i class="fa fa-star favorite-icon" v-if="favorites.includes(nodeType.type)" style="color:#f59e0b;margin-left:2px;font-size:13px;"></i>
              </div>
            </div>
          </div>
        </div>
        <div v-if="filteredNodeTypes.length===0" class="empty-tip">无匹配节点</div>
      </template>
      <div class="palette-tips">
        <div class="tip-item">
          <i class="fa fa-info-circle"></i>
          <span>拖拽节点到画布添加</span>
        </div>
        <div class="tip-item">
          <i class="fa fa-mouse-pointer"></i>
          <span>双击节点快速添加</span>
        </div>
        <div class="tip-item">
          <i class="fa fa-star"></i>
          <span>右键节点可收藏/取消收藏</span>
        </div>
      </div>
    </div>
  </div>
  <!-- Tooltip -->
  <transition name="fade">
    <div v-if="tooltip.show" class="custom-tooltip" :class="tooltip.direction" :style="{ left: tooltip.x + 'px', top: tooltip.y + 'px', width: tooltip.width + 'px' }">
      {{ tooltip.text }}
    </div>
  </transition>
</template>

<style scoped>
.node-palette {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  height: 100%;
  display: flex;
  flex-direction: column;
}
.palette-header {
  background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
  padding: 12px 12px 8px 12px;
  border-bottom: 1px solid #e2e8f0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.palette-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 2px;
}
.tab-btn {
  background: none;
  border: none;
  font-size: 14px;
  color: #6b7280;
  padding: 4px 12px;
  border-radius: 6px 6px 0 0;
  cursor: pointer;
  font-weight: 500;
  transition: color 0.2s, background 0.2s;
}
.tab-btn.active {
  color: #3b82f6;
  background: none; /* 移除背景色 */
  border-bottom: 2px solid #3b82f6;
}
.palette-search {
  width: 100%;
  padding: 6px 10px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 13px;
  outline: none;
  transition: border 0.2s;
}
.palette-search:focus {
  border-color: #6366f1;
}
.palette-content {
  flex: 1;
  padding: 12px 12px 0 12px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.node-group {
  margin-bottom: 8px;
}
.group-label {
  font-size: 13px;
  color: #64748b;
  font-weight: 600;
  margin-bottom: 4px;
  margin-left: 2px;
}
.node-types-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px 6px;
}
.node-type-item {
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 2px;
  border: 2px solid transparent;
  border-radius: 8px;
  background: #f9fafb;
  cursor: grab;
  transition: all 0.2s ease;
  user-select: none;
  position: relative;
}
.node-type-item:hover {
  background: #f3f4f6;
  border-color: #d1d5db;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.node-type-item:active {
  cursor: grabbing;
}
.node-type-item.dragging {
  opacity: 0.5;
  transform: rotate(5deg);
}
.node-type-icon {
  font-size: 20px;
  width: 24px;
  text-align: center;
  flex-shrink: 0;
}
.node-type-label {
  font-size: 13px; 
  font-weight: 600;
  color: #1f2937;
  display: flex;
  align-items: center;
  gap: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.node-count {
  font-size: 11px;
  background: #e5e7eb;
  color: #6b7280;
  padding: 2px 6px;
  border-radius: 10px;
  font-weight: 500;
  margin-left: 2px;
}
.favorite-icon {
  margin-left: 2px;
}
.is-favorite {
}
.empty-tip {
  color: #b91c1c;
  text-align: center;
  font-size: 13px;
  margin: 18px 0 0 0;
}
.palette-tips {
  padding-top: 10px;
  border-top: 1px solid #e5e7eb;
  margin-top: 10px;
}
.tip-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  font-size: 12px;
  color: #6b7280;
}
.tip-item i {
  color: #9ca3af;
  width: 14px;
  text-align: center;
}
.custom-tooltip {
  position: fixed;
  z-index: 9999999;
  min-width: 120px;
  max-width: 260px;
  background: rgba(255,255,255,0.98);
  color: #222;
  font-size: 13px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.10);
  border: 1px solid #e5e7eb;
  padding: 10px 16px;
  pointer-events: none;
  white-space: pre-line;
  line-height: 1.5;
  opacity: 0.98;
  transition: opacity 0.13s;
  text-align: left;
}
.custom-tooltip.top .tooltip-arrow {
  top: 100%;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-top: 7px solid #fff;
  border-bottom: none;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.08));
}
.custom-tooltip.bottom .tooltip-arrow {
  bottom: 100%;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-bottom: 7px solid #fff;
  border-top: none;
  filter: drop-shadow(0 -1px 2px rgba(0,0,0,0.08));
}
.custom-tooltip.left .tooltip-arrow {
  position: absolute;
  right: -7px;
  top: 50%;
  transform: translateY(-50%);
  width: 0; height: 0;
  pointer-events: none;
}
.custom-tooltip.left .tooltip-arrow::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 0; height: 0;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  border-left: 8px solid #fff;
  margin-right: -1px;
  box-shadow: -1px 0 2px rgba(0,0,0,0.08);
  border-radius: 2px 0 0 2px;
  border-left: 1px solid #e5e7eb;
}
.custom-tooltip.left {
  border-right: 1px solid #e5e7eb;
}

.custom-tooltip.right .tooltip-arrow {
  position: absolute;
  left: -7px;
  top: 50%;
  transform: translateY(-50%);
  width: 0; height: 0;
  pointer-events: none;
}
.custom-tooltip.right .tooltip-arrow::after {
  content: '';
  position: absolute;
  right: 0;
  top: 0;
  width: 0; height: 0;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  border-right: 8px solid #fff;
  margin-left: -1px;
  box-shadow: 1px 0 2px rgba(0,0,0,0.08);
  border-radius: 0 2px 2px 0;
  border-right: 1px solid #e5e7eb;
}
.custom-tooltip.right {
  border-left: 1px solid #e5e7eb;
}

/* 全屏模式下的tooltip样式 */
.ai-agent-flow-builder.fullscreen .custom-tooltip {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(229, 231, 235, 0.8);
  box-shadow: 0 8px 32px rgba(0,0,0,0.2);
}
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.13s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style> 