<template>
  <div class="kb-page">
    <div class="page-header">
      <div class="header-content">
        <div class="title-section">
          <h1 class="page-title">知识库管理</h1>
          <p class="page-desc">上传文档并建立向量索引，支持多种文档格式。</p>
        </div>
        <div class="header-actions">
          <el-button type="primary" @click="handleUploadClick">
            <el-icon><Upload /></el-icon>
            上传文档
          </el-button>
          <el-button type="success" @click="handleBatchUploadClick">
            <el-icon><Upload /></el-icon>
            批量上传
          </el-button>
          <el-button type="warning" @click="handleJsonUploadClick">
            <el-icon><Upload /></el-icon>
            JSON上传
          </el-button>
        </div>
      </div>
    </div>

    <el-card shadow="hover" class="table-card">
      <el-table v-loading="loading" :data="tableData" style="width: 100%">
        <el-table-column prop="name" label="文件名" min-width="200">
          <template #default="scope">
            <div class="file-name">
              <el-icon class="file-icon"><Document /></el-icon>
              <span>{{ scope.row.name }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="120">
          <template #default="scope">
            <el-tag :type="getStatusType(scope.row.status)" size="small">
              {{ getStatusText(scope.row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="jobId" label="任务ID" width="180">
          <template #default="scope">
            <span class="job-id">{{ scope.row.jobId || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="上传时间" width="180" />
        <el-table-column label="操作" width="160" fixed="right">
          <template #default="scope">
            <el-button link type="primary" @click="handleViewJob(scope.row)">
              <el-icon><View /></el-icon>
              详情
            </el-button>
            <el-button link type="danger" @click="handleDelete(scope.row)">
              <el-icon><Delete /></el-icon>
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <el-dialog v-model="jobDialogVisible" title="索引任务详情" width="500px" class="job-dialog">
      <el-descriptions :column="1" border v-if="currentJob">
        <el-descriptions-item label="任务ID">
          <span class="job-id">{{ currentJob.jobId }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="状态">
          <el-tag :type="getStatusType(currentJob.status)" size="small">
            {{ getStatusText(currentJob.status) }}
          </el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="进度">
          <div class="progress-wrapper">
            <el-progress :percentage="currentJob.progress" :status="getProgressStatus(currentJob.status)" />
          </div>
        </el-descriptions-item>
        <el-descriptions-item label="错误信息" v-if="currentJob.errorMsg">
          <el-alert type="error" :closable="false">{{ currentJob.errorMsg }}</el-alert>
        </el-descriptions-item>
      </el-descriptions>
      <template #footer>
        <el-button @click="jobDialogVisible = false">关闭</el-button>
        <el-button 
          v-if="currentJob?.status === 'pending' || currentJob?.status === 'processing'" 
          type="primary" 
          @click="refreshJobStatus"
        >
          刷新状态
        </el-button>
      </template>
    </el-dialog>

    <input ref="fileInput" type="file" style="display: none" @change="handleFileChange" />
    <input ref="batchFileInput" type="file" accept=".zip" style="display: none" @change="handleBatchFileChange" />
    <input ref="jsonFileInput" type="file" accept=".json,.jsonl,.txt" style="display: none" @change="handleJsonFileChange" />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Upload, Document, View, Delete } from '@element-plus/icons-vue'
import { uploadDocument, listDocuments, getIndexJob, deleteDocument, batchUploadDocuments, jsonBatchUpload } from '@/api/kb'

interface DocumentItem {
  docId: string
  name: string
  status: string
  jobId: string
  createTime: string
}

interface IndexJob {
  jobId: string
  status: string
  progress: number
  errorMsg?: string
}

const tableData = ref<DocumentItem[]>([])
const loading = ref(false)
const jobDialogVisible = ref(false)
const currentJob = ref<IndexJob | null>(null)
const pollingJobs = ref<Set<string>>(new Set())
let pollingInterval: number | null = null

const getStatusType = (status: string) => {
  const typeMap: Record<string, string> = {
    completed: 'success',
    processing: 'warning',
    pending: 'info',
    failed: 'danger'
  }
  return typeMap[status] || 'info'
}

const getStatusText = (status: string) => {
  const textMap: Record<string, string> = {
    completed: '已完成',
    processing: '处理中',
    pending: '等待中',
    failed: '失败'
  }
  return textMap[status] || status
}

const getProgressStatus = (status: string) => {
  if (status === 'completed') return 'success'
  if (status === 'failed') return 'exception'
  return undefined
}

const fetchDocuments = async () => {
  try {
    const res = await listDocuments({})
    tableData.value = res.data.map((doc: any) => ({
      docId: doc.docId,
      name: doc.fileName,
      status: doc.status,
      jobId: doc.jobId,
      createTime: new Date(doc.createdAt).toLocaleString('zh-CN')
    }))
  } catch (error) {
    console.error('Failed to fetch documents:', error)
  }
}

const fetchJobStatus = async (jobId: string): Promise<IndexJob | null> => {
  try {
    const res: any = await getIndexJob(jobId)
    return {
      jobId: res.jobId || jobId,
      status: res.status || 'pending',
      progress: res.progress || 0,
      errorMsg: res.errorMsg
    }
  } catch (error) {
    console.error('Failed to fetch job status:', error)
    return null
  }
}

const handleViewJob = async (row: DocumentItem) => {
  if (!row.jobId) {
    ElMessage.warning('该文档没有任务ID')
    return
  }
  currentJob.value = await fetchJobStatus(row.jobId)
  jobDialogVisible.value = true
}

const handleDelete = async (row: DocumentItem) => {
  try {
    await ElMessageBox.confirm(`确定要删除文档 "${row.name}" 吗？`, '确认删除', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    
    await deleteDocument(row.docId)
    ElMessage.success('文档删除成功')
    fetchDocuments()
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error(error.message || '删除失败')
    }
  }
}

const refreshJobStatus = async () => {
  if (currentJob.value?.jobId) {
    currentJob.value = await fetchJobStatus(currentJob.value.jobId)
  }
}

const startPolling = (jobId: string) => {
  pollingJobs.value.add(jobId)
  if (!pollingInterval) {
    pollingInterval = window.setInterval(async () => {
      for (const jobId of pollingJobs.value) {
        const job = await fetchJobStatus(jobId)
        if (job) {
          if (job.status === 'completed') {
            pollingJobs.value.delete(jobId)
            ElMessage.success('文档索引任务已完成')
            fetchDocuments()
          } else if (job.status === 'failed') {
            pollingJobs.value.delete(jobId)
            ElMessage.error('文档索引任务失败')
            ElMessage.warning(`错误: ${job.errorMsg}`)
          }
        }
      }
      if (pollingJobs.value.size === 0 && pollingInterval) {
        clearInterval(pollingInterval)
        pollingInterval = null
      }
    }, 3000)
  }
}

onMounted(() => {
  fetchDocuments()
})

onUnmounted(() => {
  if (pollingInterval) {
    clearInterval(pollingInterval)
  }
})

const fileInput = ref<HTMLInputElement | null>(null)
const batchFileInput = ref<HTMLInputElement | null>(null)
const jsonFileInput = ref<HTMLInputElement | null>(null)

const handleUploadClick = () => {
  fileInput.value?.click()
}

const handleBatchUploadClick = () => {
  batchFileInput.value?.click()
}

const handleJsonUploadClick = () => {
  jsonFileInput.value?.click()
}

const handleFileChange = async (event: Event) => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]
  if (!file) return

  const formData = new FormData()
  formData.append('file', file)
  formData.append('kb_id', 'kb_default')

  try {
    loading.value = true
    const res: any = await uploadDocument(formData)
    const jobId = res.jobId as string
    ElMessage.success(`文档上传成功！任务ID: ${jobId}`)
    console.log('Upload response:', res)
    
    const newDoc: DocumentItem = {
      docId: res.docId || '',
      name: file.name,
      status: (res.status as string) || 'pending',
      jobId: jobId,
      createTime: new Date().toLocaleString('zh-CN')
    }
    tableData.value.unshift(newDoc)
    
    startPolling(jobId)
  } catch (error) {
    ElMessage.error('文档上传失败')
    console.error('Upload error:', error)
  } finally {
    loading.value = false
    target.value = ''
  }
}

const handleBatchFileChange = async (event: Event) => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]
  if (!file) return

  if (!file.name.toLowerCase().endsWith('.zip')) {
    ElMessage.error('请上传 .zip 格式的压缩包')
    target.value = ''
    return
  }

  const formData = new FormData()
  formData.append('file', file)
  formData.append('kb_id', 'kb_default')

  try {
    loading.value = true
    const res: any = await batchUploadDocuments(formData)
    
    const { total, succeeded, failed, results } = res
    
    if (succeeded > 0) {
      ElMessage.success(`批量上传成功！成功: ${succeeded}, 失败: ${failed}, 总计: ${total}`)
      
      for (const result of results) {
        if (result.status === 'created') {
          const newDoc: DocumentItem = {
            docId: result.docId,
            name: result.fileName,
            status: 'pending',
            jobId: result.jobId,
            createTime: new Date().toLocaleString('zh-CN')
          }
          tableData.value.unshift(newDoc)
          startPolling(result.jobId)
        }
      }
    } else {
      ElMessage.error('批量上传失败，请检查压缩包格式')
    }
    
    if (failed > 0) {
      const failedItems = results.filter((r: any) => r.status === 'failed')
      console.error('Failed uploads:', failedItems)
    }
    
    fetchDocuments()
  } catch (error: any) {
    ElMessage.error(error.message || '批量上传失败')
    console.error('Batch upload error:', error)
  } finally {
    loading.value = false
    target.value = ''
  }
}

const handleJsonFileChange = async (event: Event) => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]
  if (!file) return

  const fileName = file.name.toLowerCase()
  if (!fileName.endsWith('.json') && !fileName.endsWith('.jsonl') && !fileName.endsWith('.txt')) {
    ElMessage.error('请上传 .json、.jsonl 或 .txt 格式的文件')
    target.value = ''
    return
  }

  const kbId = '75c465fe-277d-455d-a30b-4b168adcc03b'
  
  const formData = new FormData()
  formData.append('file', file)
  formData.append('tenant_id', 'szmp@ash@2026')

  try {
    loading.value = true
    ElMessage.info('正在上传 JSON 文件...')
    
    const res: any = await jsonBatchUpload(kbId, formData)
    
    if (res.success) {
      ElMessage.success(`JSON 批量上传成功！成功: ${res.succeeded}, 失败: ${res.failed}`)
      
      if (res.valid_metadata_fields) {
        console.log('有效的元数据字段:', res.valid_metadata_fields)
      }
      
      if (res.failed > 0) {
        const failedItems = res.results.filter((r: any) => !r.success)
        console.warn('失败的项目:', failedItems)
      }
      
      fetchDocuments()
    } else {
      ElMessage.error('JSON 批量上传失败')
    }
  } catch (error: any) {
    ElMessage.error(error.message || 'JSON 批量上传失败')
    console.error('JSON batch upload error:', error)
  } finally {
    loading.value = false
    target.value = ''
  }
}
</script>

<style scoped>
.kb-page {
  padding: 24px;
  min-height: calc(100vh - 60px);
}

.page-header {
  margin-bottom: 24px;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 20px;
  flex-wrap: wrap;
}

.title-section {
  flex: 1;
  min-width: 200px;
}

.page-title {
  margin: 0 0 8px 0;
  font-size: 24px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.5px;
}

.page-desc {
  margin: 0;
  font-size: 14px;
  color: var(--text-secondary);
  line-height: 1.6;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.table-card {
  animation: fadeInUp 0.5s ease-out;
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.file-name {
  display: flex;
  align-items: center;
  gap: 10px;
}

.file-icon {
  color: var(--primary-color);
  font-size: 18px;
}

.job-id {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-secondary);
  background-color: var(--bg-tertiary);
  padding: 2px 8px;
  border-radius: 4px;
}

.progress-wrapper {
  width: 100%;
}

.job-dialog :deep(.el-dialog__header) {
  border-bottom: 1px solid var(--border-light);
}

.job-dialog :deep(.el-dialog__body) {
  padding: 24px;
}

@media (max-width: 768px) {
  .kb-page {
    padding: 16px;
  }

  .page-title {
    font-size: 20px;
  }

  .header-content {
    flex-direction: column;
  }

  .title-section {
    min-width: 100%;
  }
}
</style>
