<template>
  <div class="tree-item" :style="{ marginLeft: depth * 24 + 'px' }">
    <div
      class="tree-item__header"
      :class="{ 'is-folder': node.type === 'folder', 'is-selected': isSelected }"
      @click="handleClick"
      @mouseenter="onHeaderMouseEnter"
      @mouseleave="onHeaderMouseLeave"
    >
      <!-- 多选模式下的复选框 -->
      <input
        v-if="multiSelectMode"
        type="checkbox"
        class="tree-checkbox"
        :checked="isSelected"
        @click.stop
        @change="handleCheckboxChange"
      />
      <!-- 文件夹/文件图标 -->
      <span v-if="multiSelectMode" class="tree-icon tree-icon--checkbox"></span>
      <span v-else-if="node.type === 'folder'" class="tree-icon">
        {{ isExpanded ? '📂' : '📁' }}
      </span>
      <span v-else class="tree-icon">📄</span>
      <span v-if="node.type === 'folder' && node.isLoading" class="tree-loading">加载中...</span>

      <!-- 刮削状态徽章（仅文件类型） -->
      <span
        v-if="node.type === 'file' && node.scrapeStatus"
        class="tree-scrape-badge"
        :class="`tree-scrape-badge--${node.scrapeStatus}`"
        :title="getScrapeStatusTitle(node)"
      >
        {{ getScrapeStatusText(node.scrapeStatus) }}
      </span>

      <!-- 排序权重标签 -->
      <span v-if="node.type === 'folder'" class="tree-sort-badge" :title="`排序权重：${node.sortWeight ?? 0}`">
        {{ node.sortWeight ?? 0 }}
      </span>
      
      <span class="tree-title">{{ node.title }}</span>

      <!-- 文件夹描述提示图标 -->
      <span
        v-if="node.type === 'folder' && node.description"
        class="tree-info-badge"
        title="有描述"
      >ℹ️</span>
      
      <div class="tree-actions" @click.stop>
        <!-- 刮削进度条（刮削中时显示） -->
        <div
          v-if="node.type === 'file' && node.scrapeStatus === 'scraping'"
          class="tree-scrape-progress"
        >
          <div class="tree-scrape-progress__bar"></div>
        </div>
        <button
          v-if="node.type === 'folder'"
          type="button"
          class="action-btn"
          title="添加子文件夹"
          @click="handleAddFolder"
        >
          +📁
        </button>
        <button
          v-if="node.type === 'folder'"
          type="button"
          class="action-btn"
          title="添加文件"
          @click="handleAddFile"
        >
          +📄
        </button>
        <button
          v-if="node.type === 'file'"
          type="button"
          class="action-btn action-btn--rescrape"
          title="重新刮削"
          @click="handleRescrape"
        >
          🔄
        </button>
        <button
          v-if="node.type === 'file'"
          type="button"
          class="action-btn action-btn--scrape"
          title="查询刮削状态"
          @click="handleScrapeStatus"
        >
          🔍
        </button>
        <button
          type="button"
          class="action-btn"
          title="编辑"
          @click="handleEdit"
        >
          ✏️
        </button>
        <button
          type="button"
          class="action-btn action-btn--danger"
          title="删除"
          @click="handleDelete"
        >
          🗑️
        </button>
      </div>
    </div>

    <!-- 文件夹描述悬浮提示（Teleport 到 body） -->
    <Teleport to="body">
      <Transition name="tooltip-fade">
        <div
          v-if="showTooltip"
          class="app-tooltip"
          :style="tooltipStyle"
        >
          <div class="app-tooltip__header">
            <span class="app-tooltip__icon">📁</span>
            <span class="app-tooltip__title">{{ node.title }}</span>
          </div>
          <div class="app-tooltip__body">
            <p v-if="node.description" class="app-tooltip__desc">{{ node.description }}</p>
            <span v-else class="app-tooltip__empty">暂无描述</span>
            <div v-if="node.sortWeight" class="app-tooltip__meta">
              排序权重：{{ node.sortWeight }}
            </div>
          </div>
          <div class="app-tooltip__arrow"></div>
        </div>
      </Transition>
    </Teleport>

    <!-- 递归渲染子节点 -->
    <Transition name="expand">
      <div v-if="node.type === 'folder' && isExpanded && node.children?.length" class="tree-children">
        <TreeNode
          v-for="child in node.children"
          :key="child.id"
          :node="child"
          :depth="depth + 1"
          :expanded-folder-ids="expandedFolderIds"
          :multi-select-mode="multiSelectMode"
          :selected-ids="selectedIds"
          @toggle-select="$emit('toggle-select', $event)"
          @add-folder="$emit('add-folder', $event)"
          @add-file="$emit('add-file', $event)"
          @expand="$emit('expand', $event)"
          @edit="$emit('edit', $event)"
          @delete="$emit('delete', $event)"
          @scrape-status="$emit('scrape-status', $event)"
          @rescrape="$emit('rescrape', $event)"
        />
      </div>
    </Transition>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'

const props = defineProps({
  node: {
    type: Object,
    required: true,
  },
  depth: {
    type: Number,
    default: 0,
  },
  expandedFolderIds: {
    type: Set,
    default: () => new Set(),
  },
  multiSelectMode: {
    type: Boolean,
    default: false,
  },
  selectedIds: {
    type: Set,
    default: () => new Set(),
  },
})

const emit = defineEmits(['add-folder', 'add-file', 'expand', 'edit', 'delete', 'toggle-select', 'scrape-status', 'rescrape'])

const isSelected = computed(() => props.selectedIds.has(props.node.id))

const isExpanded = ref(false)
const showTooltip = ref(false)
const tooltipPos = ref({ top: 0, left: 0 })
let tooltipTimer = null

// 当 buildTree 重建节点时，通过全局展开状态恢复 isExpanded
watch(
  () => props.expandedFolderIds.has(props.node.id),
  (shouldExpand) => {
    if (shouldExpand && !isExpanded.value) {
      isExpanded.value = true
    }
  },
  { immediate: true },
)

const tooltipStyle = computed(() => ({
  position: 'fixed',
  top: `${tooltipPos.value.top}px`,
  left: `${tooltipPos.value.left}px`,
  transform: 'translateX(-50%)',
  zIndex: 99999,
}))

function onHeaderMouseEnter(event) {
  if (props.node.type !== 'folder') return
  const el = event.currentTarget
  const rect = el.getBoundingClientRect()
  tooltipPos.value = {
    top: rect.bottom + 8,
    left: rect.left + rect.width / 2,
  }
  tooltipTimer = setTimeout(() => {
    showTooltip.value = true
  }, 300)
}

function onHeaderMouseLeave() {
  clearTimeout(tooltipTimer)
  showTooltip.value = false
}

function handleClick(event) {
  // 多选模式下，点击复选框触发选择/取消选择
  if (props.multiSelectMode && event.target.type !== 'checkbox') {
    emit('toggle-select', props.node.id)
  }
  // 文件夹展开逻辑
  toggleExpand()
}

function handleCheckboxChange(event) {
  emit('toggle-select', props.node.id)
}

function toggleExpand() {
  if (props.node.type === 'folder') {
    const nextExpanded = !isExpanded.value
    isExpanded.value = nextExpanded
    if (nextExpanded) {
      // 展开时立即将文件夹ID加入全局展开状态，确保buildTree重建时能保持展开
      props.expandedFolderIds.add(props.node.id)
      emit('expand', props.node)
    } else {
      // 收起时从全局展开状态中移除
      props.expandedFolderIds.delete(props.node.id)
    }
  }
}

function handleAddFolder() {
  emit('add-folder', props.node.id)
}

function handleAddFile() {
  emit('add-file', props.node.id)
}

function handleEdit() {
  emit('edit', props.node)
}

function handleDelete() {
  emit('delete', props.node)
}

function handleScrapeStatus() {
  emit('scrape-status', props.node)
}

function handleRescrape() {
  console.log('[TreeNode] handleRescrape called, node:', props.node)
  emit('rescrape', props.node)
}

function getScrapeStatusText(status) {
  const statusMap = {
    scraping: '刮削中',
    success: '成功',
    failed: '失败',
  }
  return statusMap[status] || ''
}

function getScrapeStatusTitle(node) {
  const parts = []
  if (node.scrapeMessage) parts.push(node.scrapeMessage)
  if (node.scrapeRating) parts.push(`评分: ${node.scrapeRating}`)
  if (node.scrapeCategory) parts.push(`分类: ${node.scrapeCategory}`)
  return parts.length > 0 ? parts.join(' | ') : node.scrapeStatus
}
</script>

<style scoped>
.tree-item {
  margin-bottom: 4px;
}

.tree-item__header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 8px;
  background: rgba(99, 102, 241, 0.05);
  cursor: pointer;
  transition: all 0.2s;
}

.tree-item__header:hover {
  background: rgba(99, 102, 241, 0.1);
}

.tree-item__header.is-folder {
  font-weight: 600;
}

.tree-icon {
  font-size: 18px;
  flex-shrink: 0;
}

.tree-icon--checkbox {
  width: 18px;
  visibility: hidden;
}

.tree-checkbox {
  width: 16px;
  height: 16px;
  cursor: pointer;
  flex-shrink: 0;
}

.tree-item__header.is-selected {
  background: rgba(99, 102, 241, 0.2);
}

.tree-loading {
  flex-shrink: 0;
  font-size: 12px;
  color: #6366f1;
}

.tree-sort-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: rgba(99, 102, 241, 0.12);
  color: #6366f1;
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
  line-height: 1;
  letter-spacing: 0.02em;
}

.tree-title {
  flex: 1;
  font-size: 14px;
  color: #1f2937;
}

.tree-info-badge {
  font-size: 12px;
  flex-shrink: 0;
  opacity: 0.6;
  transition: opacity 0.2s;
}

.tree-item__header:hover .tree-info-badge {
  opacity: 1;
}

.tree-actions {
  display: flex;
  gap: 4px;
  opacity: 1;
  transition: opacity 0.2s;
}

.tree-item__header:hover .tree-actions {
  opacity: 1;
}

.action-btn {
  padding: 4px 8px;
  border: none;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s;
}

.action-btn:hover {
  background: rgba(99, 102, 241, 0.15);
}

.action-btn--danger:hover {
  background: rgba(239, 68, 68, 0.15);
}

.tree-children {
  margin-top: 4px;
}

.expand-enter-active,
.expand-leave-active {
  transition: all 0.3s ease;
  max-height: 1000px;
  overflow: hidden;
}

.expand-enter-from,
.expand-leave-to {
  max-height: 0;
  opacity: 0;
}

/* ===== 刮削状态徽章样式 ===== */
.tree-scrape-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
  line-height: 1;
}

.tree-scrape-badge--scraping {
  background: rgba(59, 130, 246, 0.15);
  color: #3b82f6;
  animation: scrape-pulse 2s ease-in-out infinite;
}

.tree-scrape-badge--success {
  background: rgba(34, 197, 94, 0.15);
  color: #22c55e;
}

.tree-scrape-badge--failed {
  background: rgba(239, 68, 68, 0.15);
  color: #ef4444;
}

@keyframes scrape-pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.6;
  }
}

/* 刮削进度条动画 */
.tree-scrape-progress {
  width: 40px;
  height: 3px;
  background: rgba(59, 130, 246, 0.1);
  border-radius: 2px;
  overflow: hidden;
  flex-shrink: 0;
}

.tree-scrape-progress__bar {
  width: 40%;
  height: 100%;
  background: linear-gradient(90deg, #3b82f6, #60a5fa);
  border-radius: 2px;
  animation: scrape-progress-slide 1.2s ease-in-out infinite;
}

@keyframes scrape-progress-slide {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(350%);
  }
}
</style>
