<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { NButton, NIcon, NSpin, NEmpty, useMessage } from 'naive-ui'
import { AddOutline, ReloadOutline, SearchOutline } from '@vicons/ionicons5'
import { useSkillStore } from '../stores/skill'
import { getCategoryTree, createCategory, updateCategory, deleteCategory as deleteCategoryApi } from '../api/category'
import { setSkillCategory } from '../api/skill'
import { useConfirmDelete } from '../composables/useConfirmDelete'
import SkillCard from '../components/skill/SkillCard.vue'
import SkillUpload from '../components/skill/SkillUpload.vue'
import TagSelector from '../components/tag/TagSelector.vue'
import CategoryPicker from '../components/skill/CategoryPicker.vue'
import CategoryTree from '../components/skill/CategoryTree.vue'

const router = useRouter()
const skillStore = useSkillStore()
const message = useMessage()
const confirmDelete = useConfirmDelete()

const showUpload = ref(false)
const showTagSelector = ref(false)
const taggingSkill = ref(null)

// 分类选择器状态
const showCategoryPicker = ref(false)
const categorizingSkill = ref(null)

// 分类树相关
const categories = ref([])
const expandedIds = ref(new Set())

// 分类树内联编辑状态
const editingId = ref(null)
const editingName = ref('')
const addingParentId = ref(undefined) // undefined = 未激活，null = 添加根分类，数字 = 添加子分类
const addingName = ref('')

onMounted(() => {
  skillStore.init()
  loadCategories()
})

onUnmounted(() => {
  skillStore.destroy()
})

// ==================== 分类树操作 ====================

async function loadCategories() {
  try {
    const res = await getCategoryTree()
    categories.value = res.data || []
  } catch (err) {
    message.error('加载分类失败')
  }
}

function toggleExpand(id) {
  if (expandedIds.value.has(id)) {
    expandedIds.value.delete(id)
  } else {
    expandedIds.value.add(id)
  }
}

function selectCategory(categoryId) {
  if (skillStore.selectedCategoryId === categoryId) {
    skillStore.setCategory(null)
  } else {
    skillStore.setCategory(categoryId)
  }
}

function startAdd(parentId) {
  addingParentId.value = parentId
  addingName.value = ''
}

function cancelAdd() {
  addingParentId.value = undefined
  addingName.value = ''
}

async function confirmAdd() {
  if (!addingName.value.trim()) return
  try {
    await createCategory({ parentId: addingParentId.value, name: addingName.value.trim() })
    await loadCategories()
    if (addingParentId.value != null) {
      expandedIds.value.add(addingParentId.value)
    }
    cancelAdd()
  } catch (err) {
    message.error(err.message || '创建失败')
  }
}

function startEdit({ id, name }) {
  editingId.value = id
  editingName.value = name
}

function cancelEdit() {
  editingId.value = null
  editingName.value = ''
}

async function confirmEdit() {
  if (!editingName.value.trim()) return
  try {
    await updateCategory(editingId.value, { name: editingName.value.trim() })
    await loadCategories()
    cancelEdit()
  } catch (err) {
    message.error(err.message || '更新失败')
  }
}

function handleDeleteCategory({ id, name }) {
  confirmDelete({
    name,
    itemType: '分类',
    content: `确定要删除分类「${name}」吗？该分类下的技能将变为未分类。`,
    onConfirm: async () => {
      try {
        await deleteCategoryApi(id)
        await loadCategories()
        if (skillStore.selectedCategoryId === id) {
          skillStore.setCategory(null)
        }
        message.success('删除成功')
      } catch (err) {
        message.error(err.message || '删除失败')
      }
    },
  })
}

// ==================== 技能操作 ====================

function handleRefresh() {
  skillStore.fetchSkills()
  loadCategories()
}

async function handleUpload(file) {
  try {
    await skillStore.createSkill(file)
    showUpload.value = false
    loadCategories()
    message.success('技能上传成功')
  } catch (err) {
    message.error(err.message || '上传失败')
  }
}

function handleEdit(skill) {
  router.push(`/skill/edit/${skill.folderName}`)
}

function handleDelete(skill) {
  confirmDelete({
    name: skill.displayName || skill.translatedDisplayName || skill.name,
    itemType: '技能',
    onConfirm: async () => {
      try {
        await skillStore.removeSkill(skill.folderName)
        loadCategories()
        message.success('删除成功')
      } catch (err) {
        message.error(err.message || '删除失败')
      }
    },
  })
}

function handleTag(skill) {
  taggingSkill.value = skill
  showTagSelector.value = true
}

function handleCategory(skill) {
  categorizingSkill.value = skill
  showCategoryPicker.value = true
}

async function onCategorySaved(categoryId) {
  if (!categorizingSkill.value) return
  try {
    await setSkillCategory(categorizingSkill.value.folderName, categoryId)
    await skillStore.fetchSkills()
    await loadCategories()
    message.success('分类已更新')
  } catch (err) {
    message.error(err.response?.data?.message || '设置分类失败')
  } finally {
    categorizingSkill.value = null
  }
}

async function onTagsSaved() {
  await skillStore.fetchSkills()
  message.success('标签已更新')
}

// 搜索防抖
let searchTimer = null
function onSearchInput(value) {
  clearTimeout(searchTimer)
  searchTimer = setTimeout(() => {
    skillStore.setSearch(value)
  }, 300)
}
</script>

<template>
  <div class="skill-management">
    <div class="main-layout">
      <!-- 左侧分类树 -->
      <div class="sidebar">
        <div class="sidebar-header">
          <span class="sidebar-title">分类</span>
          <button class="icon-btn" @click="startAdd(null)" title="新建根分类">
            <n-icon size="16"><AddOutline /></n-icon>
          </button>
        </div>

        <div class="category-list">
          <!-- 全部 -->
          <div
            class="all-item"
            :class="{ active: !skillStore.selectedCategoryId }"
            @click="selectCategory(null)"
          >
            <span class="cat-name">全部技能</span>
            <span class="cat-count">{{ skillStore.unfilteredTotal }}</span>
          </div>

          <!-- 递归分类树 -->
          <CategoryTree
            :nodes="categories"
            :level="0"
            :selected-id="skillStore.selectedCategoryId"
            :expanded-ids="expandedIds"
            :editing-id="editingId"
            v-model:editing-name="editingName"
            :adding-parent-id="addingParentId"
            v-model:adding-name="addingName"
            @select="selectCategory"
            @toggle="toggleExpand"
            @add="startAdd"
            @delete="handleDeleteCategory"
            @edit-start="startEdit"
            @edit-confirm="confirmEdit"
            @edit-cancel="cancelEdit"
            @add-confirm="confirmAdd"
            @add-cancel="cancelAdd"
          />

          <!-- 根分类添加输入框 -->
          <div v-if="addingParentId === null" class="root-adding">
            <input
              class="inline-input"
              v-model="addingName"
              placeholder="输入分类名称"
              @keyup.enter="confirmAdd"
              @keyup.escape="cancelAdd"
              @blur="cancelAdd"
              autofocus
            />
          </div>
        </div>
      </div>

      <!-- 右侧内容 -->
      <div class="content">
        <!-- 工具栏 -->
        <div class="toolbar">
          <div class="toolbar-left">
            <div class="search-box">
              <n-icon size="16" class="search-icon"><SearchOutline /></n-icon>
              <input
                class="search-input"
                :value="skillStore.searchKeyword"
                @input="onSearchInput($event.target.value)"
                placeholder="搜索技能名称或描述..."
              />
            </div>
            <span class="skill-count">
              共 <span class="count-num">{{ skillStore.total }}</span> 个技能
            </span>
          </div>
          <div class="toolbar-right">
            <n-button size="small" @click="handleRefresh" :disabled="skillStore.loading">
              <template #icon><n-icon><ReloadOutline /></n-icon></template>
              刷新
            </n-button>
            <n-button size="small" type="primary" @click="showUpload = true">
              <template #icon><n-icon><AddOutline /></n-icon></template>
              新增技能
            </n-button>
          </div>
        </div>

        <!-- 加载状态 -->
        <div v-if="skillStore.loading && skillStore.skills.length === 0" class="loading-area">
          <n-spin size="large" />
          <p class="loading-text">正在加载技能列表...</p>
        </div>

        <!-- 空状态 -->
        <div v-else-if="skillStore.skills.length === 0" class="empty-area">
          <div class="empty-illustration">
            <svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
              <rect x="20" y="30" width="80" height="60" rx="8" stroke="rgba(56, 189, 248, 0.15)" stroke-width="2" fill="none"/>
              <path d="M45 55H75" stroke="rgba(56, 189, 248, 0.2)" stroke-width="2" stroke-linecap="round"/>
              <path d="M45 65H65" stroke="rgba(56, 189, 248, 0.15)" stroke-width="2" stroke-linecap="round"/>
              <circle cx="60" cy="60" r="30" stroke="rgba(37, 99, 235, 0.1)" stroke-width="1" fill="none"/>
            </svg>
          </div>
          <p class="empty-title">暂无技能</p>
          <p class="empty-desc">点击「新增技能」上传您的第一个 Skill</p>
          <n-button type="primary" @click="showUpload = true" style="margin-top: 16px">
            <template #icon>
              <n-icon><AddOutline /></n-icon>
            </template>
            新增技能
          </n-button>
        </div>

        <!-- 卡片网格 -->
        <div v-else class="skill-grid">
          <SkillCard
            v-for="(skill, index) in skillStore.skills"
            :key="skill.folderName"
            :skill="skill"
            :style="{ animationDelay: `${index * 60}ms` }"
            class="fade-in"
            @edit="handleEdit"
            @delete="handleDelete"
            @tag="handleTag"
            @category="handleCategory"
          />
        </div>

        <!-- 分页 -->
        <div v-if="skillStore.totalPages > 1" class="pagination">
          <button
            class="page-btn"
            :disabled="skillStore.currentPage <= 1"
            @click="skillStore.setPage(skillStore.currentPage - 1)"
          >上一页</button>
          <template v-for="p in skillStore.totalPages" :key="p">
            <button
              v-if="p === 1 || p === skillStore.totalPages || Math.abs(p - skillStore.currentPage) <= 1"
              class="page-btn"
              :class="{ active: p === skillStore.currentPage }"
              @click="skillStore.setPage(p)"
            >{{ p }}</button>
            <span v-else-if="Math.abs(p - skillStore.currentPage) === 2" class="page-ellipsis">...</span>
          </template>
          <button
            class="page-btn"
            :disabled="skillStore.currentPage >= skillStore.totalPages"
            @click="skillStore.setPage(skillStore.currentPage + 1)"
          >下一页</button>
        </div>
      </div>
    </div>

    <!-- 上传弹窗 -->
    <SkillUpload
      v-model:show="showUpload"
      :uploading="skillStore.uploading"
      :progress="skillStore.uploadProgress"
      @upload="handleUpload"
    />

    <!-- 标签选择器 -->
    <TagSelector
      v-model:show="showTagSelector"
      entity-type="skill"
      :entity-id="taggingSkill?.folderName || ''"
      :selected-tag-ids="taggingSkill?.tags?.map(t => t.tagId) || []"
      @saved="onTagsSaved"
    />

    <!-- 分类选择器 -->
    <CategoryPicker
      v-model:show="showCategoryPicker"
      category-type="skill"
      :selected-id="categorizingSkill?.categoryId || null"
      @confirm="onCategorySaved"
    />
  </div>
</template>

<style scoped>
.skill-management {
  height: 100%;
  overflow: hidden;
}

.main-layout {
  display: flex;
  gap: 24px;
  height: 100%;
}

/* ==================== 左侧分类树 ==================== */
.sidebar {
  width: 240px;
  min-width: 240px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  padding: 16px 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px 12px;
  border-bottom: 1px solid rgba(56, 189, 248, 0.06);
}

.sidebar-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}

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

.all-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 16px;
  cursor: pointer;
  transition: all 0.15s;
  min-height: 32px;
}

.all-item:hover {
  background: rgba(37, 99, 235, 0.06);
}

.all-item.active {
  background: rgba(37, 99, 235, 0.12);
}

.all-item.active .cat-name {
  color: var(--color-accent);
  font-weight: 500;
}

.cat-name {
  font-size: 13px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cat-count {
  font-size: 11px;
  color: var(--text-muted);
  background: rgba(100, 116, 139, 0.1);
  padding: 1px 6px;
  border-radius: 8px;
  min-width: 20px;
  text-align: center;
}

.icon-btn {
  background: none;
  border: none;
  color: var(--text-tertiary);
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  transition: all 0.15s;
}

.icon-btn:hover {
  color: var(--color-accent);
  background: rgba(37, 99, 235, 0.1);
}

.root-adding {
  padding: 6px 16px;
}

.inline-input {
  background: rgba(37, 99, 235, 0.08);
  border: 1px solid rgba(37, 99, 235, 0.2);
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 13px;
  color: var(--text-primary);
  outline: none;
  width: 100%;
  font-family: inherit;
}

.inline-input:focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.15);
}

/* ==================== 右侧内容 ==================== */
.content {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
  padding-right: 4px;
}

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg-primary);
  padding-bottom: 12px;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 16px;
}

.search-box {
  position: relative;
  width: 280px;
}

.search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
}

.search-input {
  width: 100%;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  padding: 8px 12px 8px 32px;
  font-size: 13px;
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.2s;
  font-family: inherit;
}

.search-input:focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.15);
}

.search-input::placeholder {
  color: var(--text-muted);
}

.skill-count {
  font-size: 14px;
  color: var(--text-secondary);
}

.count-num {
  color: var(--color-accent);
  font-weight: 600;
}

.toolbar-right {
  display: flex;
  gap: 8px;
}

/* 加载状态 */
.loading-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 0;
  gap: 16px;
}

.loading-text {
  font-size: 14px;
  color: var(--text-tertiary);
}

/* 空状态 */
.empty-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 0;
}

.empty-illustration {
  margin-bottom: 20px;
  opacity: 0.6;
}

.empty-title {
  font-size: 16px;
  font-weight: 500;
  color: var(--text-secondary);
  margin-bottom: 8px;
}

.empty-desc {
  font-size: 13px;
  color: var(--text-muted);
}

/* 卡片网格 */
.skill-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

/* 分页 */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-top: 32px;
  padding-top: 20px;
  border-top: 1px solid rgba(56, 189, 248, 0.06);
}

.page-btn {
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  padding: 6px 14px;
  font-size: 13px;
  color: var(--text-secondary);
  cursor: pointer;
  transition: all 0.15s;
  font-family: inherit;
}

.page-btn:hover:not(:disabled) {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.page-btn.active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}

.page-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.page-ellipsis {
  color: var(--text-muted);
  padding: 0 4px;
}
</style>
