<script setup>
import { ref, computed } from 'vue'
import { NModal, NButton, NIcon, NProgress, NSelect } from 'naive-ui'
import { CloudUploadOutline, CloseOutline, DocumentTextOutline } from '@vicons/ionicons5'
import { uploadKbDocument } from '../../api/knowledge'

const props = defineProps({
  show: { type: Boolean, default: false },
  /** 当前选中分类（默认上传到此分类） */
  categoryId: { type: [Number, null], default: null },
  /** 扁平化的分类列表（用于下拉选择） */
  categories: { type: Array, default: () => [] }
})
const emit = defineEmits(['update:show', 'uploaded'])

const visible = computed({
  get: () => props.show,
  set: v => emit('update:show', v)
})

const selectedCategory = ref(props.categoryId)
const files = ref([])  // [{file, progress, status, error}]
const uploading = ref(false)

const categoryOptions = computed(() => {
  const flatten = (nodes, prefix = '') => {
    const result = []
    for (const n of nodes || []) {
      result.push({ label: prefix + n.name, value: n.id })
      if (n.children?.length) {
        result.push(...flatten(n.children, prefix + n.name + ' / '))
      }
    }
    return result
  }
  const opts = flatten(props.categories)
  return [{ label: '未分类', value: null }, ...opts]
})

function onFileChange(e) {
  const arr = Array.from(e.target.files || [])
  for (const f of arr) {
    files.value.push({ file: f, progress: 0, status: 'pending', error: null })
  }
  // 清空 input 允许重复选同一文件
  e.target.value = ''
}

function onDrop(e) {
  e.preventDefault()
  const arr = Array.from(e.dataTransfer.files || [])
  for (const f of arr) {
    files.value.push({ file: f, progress: 0, status: 'pending', error: null })
  }
}

function removeFile(idx) {
  files.value.splice(idx, 1)
}

async function startUpload() {
  if (!files.value.length) return
  uploading.value = true
  for (const item of files.value) {
    if (item.status === 'success') continue
    item.status = 'uploading'
    item.error = null
    try {
      await uploadKbDocument(item.file, selectedCategory.value, (p) => {
        item.progress = p
      })
      item.status = 'success'
      item.progress = 100
      emit('uploaded')
    } catch (e) {
      item.status = 'error'
      item.error = e.message || '上传失败'
    }
  }
  uploading.value = false
}

function close() {
  if (uploading.value) return
  files.value = []
  visible.value = false
}
</script>

<template>
  <n-modal
    :show="visible"
    @update:show="visible = $event"
    preset="card"
    style="max-width: 640px; width: 90vw"
    :bordered="false"
    :mask-closable="!uploading"
  >
    <template #header>
      <div class="modal-header">
        <span class="modal-title">上传文档</span>
        <button class="icon-btn" @click="close" :disabled="uploading">
          <n-icon size="18"><CloseOutline /></n-icon>
        </button>
      </div>
    </template>

    <div class="uploader-body">
      <!-- 分类选择 -->
      <div class="form-row">
        <label class="form-label">目标分类</label>
        <n-select
          v-model:value="selectedCategory"
          :options="categoryOptions"
          :disabled="uploading"
          placeholder="选择分类（可选）"
          size="small"
        />
      </div>

      <!-- 拖拽区 -->
      <div
        class="drop-zone"
        @click="$refs.fileInput.click()"
        @drop="onDrop"
        @dragover.prevent
        @dragenter.prevent
      >
        <input ref="fileInput" type="file" multiple @change="onFileChange" hidden />
        <n-icon size="32" color="var(--color-accent)"><CloudUploadOutline /></n-icon>
        <div class="drop-text">点击选择文件或拖拽到此处</div>
        <div class="drop-hint">支持 PDF / Word / Excel / PPT / TXT / Markdown / HTML，单文件最大 50MB</div>
      </div>

      <!-- 待上传列表 -->
      <div class="file-list" v-if="files.length">
        <div class="file-item" v-for="(item, idx) in files" :key="idx">
          <div class="file-info">
            <n-icon size="16" color="var(--color-accent)"><DocumentTextOutline /></n-icon>
            <span class="file-name" :title="item.file.name">{{ item.file.name }}</span>
            <span class="file-size">{{ (item.file.size / 1024).toFixed(1) }} KB</span>
          </div>
          <div class="file-status">
            <span v-if="item.status === 'success'" class="badge badge-success">完成</span>
            <span v-else-if="item.status === 'error'" class="badge badge-error" :title="item.error">失败</span>
            <span v-else-if="item.status === 'uploading'" class="progress-wrap">
              <n-progress
                type="line"
                :percentage="item.progress"
                :height="4"
                :show-indicator="false"
              />
            </span>
            <span v-else class="badge badge-pending">等待</span>
            <button
              v-if="!uploading && item.status !== 'success'"
              class="icon-btn-sm"
              @click="removeFile(idx)"
            >
              <n-icon size="12"><CloseOutline /></n-icon>
            </button>
          </div>
        </div>
      </div>
    </div>

    <template #footer>
      <div class="modal-footer">
        <n-button size="small" @click="close" :disabled="uploading">取消</n-button>
        <n-button
          size="small"
          type="primary"
          :loading="uploading"
          :disabled="!files.length || files.every(f => f.status === 'success')"
          @click="startUpload"
        >
          {{ uploading ? '上传中...' : '开始上传' }}
        </n-button>
      </div>
    </template>
  </n-modal>
</template>

<style scoped>
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-right: 8px;
}
.modal-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}
.icon-btn {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 6px;
  transition: all 0.15s;
}
.icon-btn:hover { color: var(--text-primary); background: rgba(255,255,255,0.08); }
.icon-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.uploader-body { display: flex; flex-direction: column; gap: 14px; padding: 4px 0; }
.form-row { display: flex; flex-direction: column; gap: 6px; }
.form-label { font-size: 12px; color: var(--text-secondary); font-weight: 500; }

.drop-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 24px 16px;
  background: rgba(37, 99, 235, 0.04);
  border: 1.5px dashed rgba(37, 99, 235, 0.3);
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
  text-align: center;
}
.drop-zone:hover {
  background: rgba(37, 99, 235, 0.08);
  border-color: var(--color-accent);
}
.drop-text { font-size: 13px; color: var(--text-primary); font-weight: 500; }
.drop-hint { font-size: 11px; color: var(--text-muted); }

.file-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
}
.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 6px;
  font-size: 12px;
  gap: 12px;
}
.file-info {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
}
.file-name {
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
}
.file-size { color: var(--text-muted); font-size: 11px; }
.file-status {
  display: flex;
  align-items: center;
  gap: 8px;
}
.badge {
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 500;
}
.badge-success { color: #10b981; background: rgba(16, 185, 129, 0.1); }
.badge-error { color: #ef4444; background: rgba(239, 68, 68, 0.1); cursor: help; }
.badge-pending { color: var(--text-muted); background: rgba(100, 116, 139, 0.1); }

.progress-wrap {
  width: 100px;
}

.icon-btn-sm {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px;
  border-radius: 3px;
  display: flex;
  align-items: center;
}
.icon-btn-sm:hover { color: var(--color-danger); }

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
</style>
