<script setup>
import { ref, computed, onMounted } from 'vue'
import { useTagStore } from '../stores/tag'
import {
  NButton, NInput, NModal, NForm, NFormItem, NEmpty, NSpin,
  NPopconfirm, NIcon, NSelect, NTag, useMessage
} from 'naive-ui'
import {
  AddOutline, CreateOutline, TrashOutline, DownloadOutline, CloudUploadOutline
} from '@vicons/ionicons5'
import TreeNodeItem from '../components/tag/TreeNodeItem.vue'
import { exportTags, importTags } from '../api/tag'

const tagStore = useTagStore()
const message = useMessage()

// ========== 标签组表单 ==========
const showGroupModal = ref(false)
const editingGroup = ref(null)
const groupForm = ref({ name: '', description: '' })

function openCreateGroup() {
  editingGroup.value = null
  groupForm.value = { name: '', description: '' }
  showGroupModal.value = true
}

function openEditGroup(group) {
  editingGroup.value = group
  groupForm.value = { name: group.name, description: group.description || '' }
  showGroupModal.value = true
}

async function saveGroup() {
  if (!groupForm.value.name.trim()) {
    message.warning('请输入标签组名称')
    return
  }
  try {
    if (editingGroup.value) {
      await tagStore.updateGroup(editingGroup.value.id, groupForm.value.name, groupForm.value.description)
      message.success('标签组已更新')
    } else {
      await tagStore.createGroup(groupForm.value.name, groupForm.value.description)
      message.success('标签组已创建')
    }
    showGroupModal.value = false
  } catch (e) {
    message.error(e.response?.data?.message || '操作失败')
  }
}

async function handleDeleteGroup(id) {
  try {
    await tagStore.removeGroup(id)
    message.success('标签组已删除')
  } catch (e) {
    message.error(e.response?.data?.message || '删除失败')
  }
}

// ========== 标签节点操作 ==========
const selectedGroupId = computed(() => tagStore.activeGroupId)

async function selectGroup(group) {
  await tagStore.fetchTags(group.id)
}

async function renameTag(id, name) {
  try {
    await tagStore.updateTag(id, name)
    message.success('标签已重命名')
  } catch (e) {
    message.error(e.response?.data?.message || '修改失败')
  }
}

// ========== 添加标签（对话框） ==========
const showAddRootDialog = ref(false)
const newRootTagName = ref('')

function openAddRootDialog() {
  if (!selectedGroupId.value) return
  newRootTagName.value = ''
  showAddRootDialog.value = true
}

async function confirmAddRoot() {
  const name = newRootTagName.value.trim()
  if (!name) return
  try {
    await tagStore.addTag(selectedGroupId.value, null, name)
    showAddRootDialog.value = false
  } catch (e) {
    message.error(e.response?.data?.message || '添加失败')
  }
}

async function addChild(parentId, name) {
  if (!selectedGroupId.value || !name.trim()) return
  try {
    await tagStore.addTag(selectedGroupId.value, parentId, name.trim())
  } catch (e) {
    message.error(e.response?.data?.message || '添加失败')
  }
}

async function handleDeleteNode(id) {
  try {
    await tagStore.removeTag(id)
    message.success('标签已删除')
  } catch (e) {
    message.error(e.response?.data?.message || '删除失败')
  }
}

// ========== 树渲染（递归） ==========
const tree = computed(() => tagStore.buildTree())

const expandedNodes = ref(new Set())

function toggleExpand(id) {
  if (expandedNodes.value.has(id)) {
    expandedNodes.value.delete(id)
  } else {
    expandedNodes.value.add(id)
  }
  expandedNodes.value = new Set(expandedNodes.value)
}

// ========== 导入导出 ==========
const showImportModal = ref(false)
const importData = ref(null)
const importLoading = ref(false)
const importResult = ref(null)

const strategyOptions = [
  { label: '覆盖标签组', value: 'overwrite' },
  { label: '合并标签', value: 'merge' },
  { label: '跳过', value: 'skip' }
]

async function handleExport() {
  try {
    const res = await exportTags()
    const blob = new Blob([JSON.stringify(res.data, null, 2)], { type: 'application/json' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `tags-export-${new Date().toISOString().slice(0, 10)}.json`
    a.click()
    URL.revokeObjectURL(url)
    message.success('导出成功')
  } catch (e) {
    message.error('导出失败')
  }
}

function handleImportFileSelect(e) {
  const file = e.target.files?.[0]
  if (!file) return
  const reader = new FileReader()
  reader.onload = (ev) => {
    try {
      const data = JSON.parse(ev.target.result)
      if (!data.groups || !Array.isArray(data.groups)) {
        message.error('无效的标签导出文件')
        return
      }
      // 标记冲突状态
      const existingNames = new Set(tagStore.groups.map(g => g.name))
      importData.value = {
        raw: data,
        groups: data.groups.map(g => ({
          name: g.name,
          tagCount: countTags(g.tags),
          conflict: existingNames.has(g.name),
          strategy: existingNames.has(g.name) ? 'overwrite' : 'create'
        }))
      }
      importResult.value = null
      showImportModal.value = true
    } catch {
      message.error('文件解析失败，请确认是有效的 JSON 文件')
    }
  }
  reader.readAsText(file)
  // 重置 input 以支持重复选择同一文件
  e.target.value = ''
}

function countTags(tags) {
  if (!tags) return 0
  let count = 0
  for (const t of tags) {
    count += 1 + countTags(t.children)
  }
  return count
}

async function confirmImport() {
  if (!importData.value) return
  importLoading.value = true
  importResult.value = null
  try {
    const strategies = {}
    for (const g of importData.value.groups) {
      if (g.conflict) {
        strategies[g.name] = g.strategy
      }
    }
    const res = await importTags({ data: importData.value.raw, strategies })
    importResult.value = res.data
    await tagStore.fetchGroups()
    message.success('导入完成')
  } catch (e) {
    message.error(e.response?.data?.message || '导入失败')
  } finally {
    importLoading.value = false
  }
}

onMounted(() => {
  tagStore.fetchGroups()
})
</script>

<template>
  <div class="tag-management">
    <!-- 左侧：标签组列表 -->
    <div class="group-panel">
      <div class="panel-header">
        <h3 class="panel-title">标签组</h3>
        <div style="display: flex; gap: 4px;">
          <button class="icon-btn" title="导出" @click="handleExport">
            <n-icon size="16"><DownloadOutline /></n-icon>
          </button>
          <label class="icon-btn" title="导入">
            <n-icon size="16"><CloudUploadOutline /></n-icon>
            <input type="file" accept=".json" style="display: none;" @change="handleImportFileSelect" />
          </label>
          <button class="icon-btn" title="新建标签组" @click="openCreateGroup">
            <n-icon size="18"><AddOutline /></n-icon>
          </button>
        </div>
      </div>
      <div class="group-list">
        <div
          v-for="group in tagStore.groups"
          :key="group.id"
          class="group-item"
          :class="{ active: selectedGroupId === group.id }"
          @click="selectGroup(group)"
        >
          <div class="group-info">
            <span class="group-name">{{ group.name }}</span>
            <span class="group-desc" v-if="group.description">{{ group.description }}</span>
          </div>
          <div class="group-actions" @click.stop>
            <button class="icon-btn-sm" title="编辑" @click="openEditGroup(group)">
              <n-icon size="14"><CreateOutline /></n-icon>
            </button>
            <n-popconfirm
              @positive-click="handleDeleteGroup(group.id)"
              positive-text="确定"
              negative-text="取消"
            >
              <template #trigger>
                <button class="icon-btn-sm danger" title="删除">
                  <n-icon size="14"><TrashOutline /></n-icon>
                </button>
              </template>
              确定删除标签组「{{ group.name }}」及其所有标签？
            </n-popconfirm>
          </div>
        </div>
        <n-empty v-if="!tagStore.groups.length" description="暂无标签组" style="margin-top: 40px" />
      </div>
    </div>

    <!-- 右侧：标签树编辑器 -->
    <div class="tree-panel">
      <div class="panel-header" v-if="selectedGroupId">
        <h3 class="panel-title">
          {{ tagStore.groups.find(g => g.id === selectedGroupId)?.name || '标签树' }}
        </h3>
        <button class="icon-btn" title="添加根级标签" @click="openAddRootDialog">
          <n-icon size="18"><AddOutline /></n-icon>
        </button>
      </div>

      <div class="tree-container" v-if="selectedGroupId">
        <div v-if="tagStore.loading" style="padding: 40px; text-align: center;">
          <n-spin size="small" />
        </div>
        <template v-else>
          <!-- 递归树组件 -->
          <TreeNodeItem
            v-for="rootNode in tree"
            :key="rootNode.id"
            :node="rootNode"
            :expanded-nodes="expandedNodes"
            @toggle="toggleExpand"
            @add="addChild"
            @delete="handleDeleteNode"
            @rename="renameTag"
          />
          <n-empty v-if="!tree.length" description="暂无标签，点击上方按钮添加" style="margin-top: 40px" />
        </template>
      </div>

      <div v-else class="empty-tree">
        <n-empty description="请从左侧选择一个标签组" />
      </div>
    </div>

    <!-- 添加根级标签对话框 -->
    <n-modal
      v-model:show="showAddRootDialog"
      preset="dialog"
      title="添加根级标签"
      :mask-closable="false"
      positive-text="确定"
      negative-text="取消"
      @positive-click="confirmAddRoot"
      style="max-width: 380px"
    >
      <div style="padding: 8px 0">
        <n-input
          v-model:value="newRootTagName"
          placeholder="请输入标签名称"
          @keyup.enter="confirmAddRoot"
        />
      </div>
    </n-modal>

    <!-- 标签组创建/编辑弹窗 -->
    <n-modal
      v-model:show="showGroupModal"
      preset="card"
      :title="editingGroup ? '编辑标签组' : '新建标签组'"
      :mask-closable="false"
      style="max-width: 420px"
      :bordered="false"
    >
      <n-form>
        <n-form-item label="名称">
          <n-input v-model:value="groupForm.name" placeholder="输入标签组名称" />
        </n-form-item>
        <n-form-item label="描述">
          <n-input v-model:value="groupForm.description" type="textarea" :rows="2" placeholder="可选描述" />
        </n-form-item>
      </n-form>
      <template #action>
        <n-button @click="showGroupModal = false">取消</n-button>
        <n-button type="primary" @click="saveGroup" style="margin-left: 8px">保存</n-button>
      </template>
    </n-modal>

    <!-- 导入对话框 -->
    <n-modal v-model:show="showImportModal" preset="card" title="导入标签" :mask-closable="false" style="max-width: 560px" :bordered="false">
      <div v-if="importData" class="import-content">
        <p class="import-hint">文件包含 {{ importData.groups.length }} 个标签组，请处理冲突：</p>
        <div class="import-group-list">
          <div v-for="g in importData.groups" :key="g.name" class="import-group-item">
            <div class="import-group-info">
              <span class="import-group-name">{{ g.name }}</span>
              <span class="import-group-count">{{ g.tagCount }} 个标签</span>
              <n-tag v-if="!g.conflict" type="success" size="small">新建</n-tag>
              <n-tag v-else type="warning" size="small">冲突</n-tag>
            </div>
            <div v-if="g.conflict" class="import-strategy">
              <n-select
                v-model:value="g.strategy"
                :options="strategyOptions"
                size="small"
                style="width: 150px;"
              />
            </div>
          </div>
        </div>
        <!-- 导入结果 -->
        <div v-if="importResult" class="import-result">
          <p v-for="d in importResult.details" :key="d" class="import-detail">{{ d }}</p>
        </div>
      </div>
      <template #action>
        <n-button @click="showImportModal = false">{{ importResult ? '关闭' : '取消' }}</n-button>
        <n-button v-if="!importResult" type="primary" :loading="importLoading" @click="confirmImport">
          确认导入
        </n-button>
      </template>
    </n-modal>
  </div>
</template>

<style scoped>
.tag-management {
  display: flex;
  gap: 24px;
  height: calc(100vh - var(--header-height) - 56px);
  padding: 0;
}

/* ===== 左侧标签组面板 ===== */
.group-panel {
  width: 300px;
  min-width: 300px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-color);
}

.panel-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
}

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

.group-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all var(--transition-normal);
  margin-bottom: 4px;
}

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

.group-item.active {
  background: rgba(37, 99, 235, 0.12);
  border: 1px solid rgba(37, 99, 235, 0.2);
}

.group-info {
  flex: 1;
  min-width: 0;
}

.group-name {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.group-desc {
  display: block;
  font-size: 12px;
  color: var(--text-tertiary);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.group-actions {
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity var(--transition-fast);
}

.group-item:hover .group-actions {
  opacity: 1;
}

/* ===== 右侧标签树面板 ===== */
.tree-panel {
  flex: 1;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.tree-container {
  flex: 1;
  overflow-y: auto;
  padding: 16px 20px;
}

.empty-tree {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ===== 按钮 ===== */
.icon-btn {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-color);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.icon-btn:hover {
  background: rgba(255, 255, 255, 0.09);
  color: var(--text-primary);
  border-color: var(--border-color-hover);
}

.icon-btn-sm {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  border: none;
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: all var(--transition-fast);
}

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

.icon-btn-sm.danger:hover {
  color: var(--color-danger);
  background: rgba(239, 68, 68, 0.1);
}

/* ===== 导入对话框 ===== */
.import-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.import-hint {
  font-size: 13px;
  color: var(--text-secondary);
  margin: 0;
}

.import-group-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 320px;
  overflow-y: auto;
}

.import-group-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.import-group-info {
  display: flex;
  align-items: center;
  gap: 8px;
}

.import-group-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
}

.import-group-count {
  font-size: 12px;
  color: var(--text-tertiary);
}

.import-result {
  padding: 12px;
  border-radius: var(--radius-md);
  background: rgba(34, 197, 94, 0.06);
  border: 1px solid rgba(34, 197, 94, 0.15);
}

.import-detail {
  font-size: 13px;
  color: var(--text-secondary);
  margin: 2px 0;
}
</style>
