<script lang="ts" setup>
import { h, onMounted, ref } from 'vue';

import { Page } from '@vben/common-ui';

import {
  Badge,
  Button,
  Collapse,
  CollapsePanel,
  Descriptions,
  DescriptionsItem,
  Form,
  FormItem,
  Input,
  InputNumber,
  message,
  Modal,
  Popconfirm,
  Progress,
  Space,
  Spin,
  Table,
  Tag,
  Upload,
} from 'ant-design-vue';

import {
  createKnowledgeBaseApi,
  deleteKnowledgeBaseApi,
  getDocumentChunksApi,
  getDocumentsApi,
  getKnowledgeBasesApi,
  processDocumentApi,
  uploadDocumentToKbApi,
  type ChunkApi,
  type KnowledgeBaseApi,
} from '#/api/core';

const loading = ref(false);
const knowledgeBases = ref<KnowledgeBaseApi.KnowledgeBase[]>([]);
const showCreate = ref(false);
const formState = ref({ name: '', description: '', chunkSize: 500, chunkOverlap: 50 });

// 文档管理
const expandedKbId = ref<string | null>(null);
const documents = ref<KnowledgeBaseApi.Document[]>([]);
const docsLoading = ref(false);
const uploadProgress = ref(0);
const uploading = ref(false);

// 分片预览
const showChunkPreview = ref(false);
const chunkDocTitle = ref('');
const chunks = ref<ChunkApi.ChunkPreview[]>([]);
const chunksLoading = ref(false);
const expandedChunkKeys = ref<number[]>([]);

const statusMap: Record<string, { color: string; text: string }> = {
  Active: { color: 'green', text: '启用' },
  Inactive: { color: 'red', text: '禁用' },
  Pending: { color: 'default' as const, text: '待处理' },
  Processing: { color: 'processing' as const, text: '处理中' },
  Completed: { color: 'success' as const, text: '已完成' },
  Failed: { color: 'error' as const, text: '失败' },
};

const columns = [
  { title: '名称', dataIndex: 'name', key: 'name' },
  { title: '描述', dataIndex: 'description', key: 'description', ellipsis: true },
  { title: '分块大小', dataIndex: 'chunkSize', key: 'chunkSize', width: 100 },
  { title: '状态', dataIndex: 'status', key: 'status', width: 100,
    customRender: ({ text }: { text: string }) => {
      const s = statusMap[text] || { color: 'default', text };
      return h(Tag, { color: s.color }, () => s.text);
    },
  },
  { title: '创建时间', dataIndex: 'createdAt', key: 'createdAt', width: 180,
    customRender: ({ text }: { text: string }) => new Date(text).toLocaleString('zh-CN'),
  },
  { title: '操作', key: 'action', width: 250 },
];

const docColumns = [
  { title: '文档名', dataIndex: 'title', key: 'title' },
  { title: '文件名', dataIndex: 'fileName', key: 'fileName', ellipsis: true },
  { title: '大小', dataIndex: 'fileSize', key: 'fileSize', width: 100,
    customRender: ({ text }: { text: number }) => formatSize(text),
  },
  { title: '分块数', dataIndex: 'chunkCount', key: 'chunkCount', width: 80 },
  { title: '状态', dataIndex: 'status', key: 'status', width: 100,
    customRender: ({ text }: { text: string }) => {
      const s = statusMap[text] || { color: 'default', text };
      return h(Tag, { color: s.color }, () => s.text);
    },
  },
  { title: '操作', key: 'action', width: 200 },
];

function formatSize(bytes: number) {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

async function loadData() {
  loading.value = true;
  try {
    knowledgeBases.value = await getKnowledgeBasesApi();
  } catch {
    message.error('加载知识库失败');
  } finally {
    loading.value = false;
  }
}

async function handleCreate() {
  if (!formState.value.name.trim()) {
    message.warning('请输入名称');
    return;
  }
  try {
    await createKnowledgeBaseApi(formState.value);
    message.success('创建成功');
    showCreate.value = false;
    formState.value = { name: '', description: '', chunkSize: 500, chunkOverlap: 50 };
    loadData();
  } catch {
    message.error('创建失败');
  }
}

async function handleDelete(id: string) {
  try {
    await deleteKnowledgeBaseApi(id);
    message.success('已删除');
    loadData();
  } catch {
    message.error('删除失败');
  }
}

async function handleExpand(kbId: string) {
  if (expandedKbId.value === kbId) {
    expandedKbId.value = null;
    return;
  }
  expandedKbId.value = kbId;
  docsLoading.value = true;
  try {
    documents.value = await getDocumentsApi(kbId);
  } catch {
    message.error('加载文档失败');
  } finally {
    docsLoading.value = false;
  }
}

async function handleUpload(kbId: string, file: File) {
  uploading.value = true;
  uploadProgress.value = 0;
  try {
    await uploadDocumentToKbApi(kbId, file, undefined, (p) => { uploadProgress.value = p; });
    message.success('上传成功');
    documents.value = await getDocumentsApi(kbId);
  } catch {
    message.error('上传失败');
  } finally {
    uploading.value = false;
    uploadProgress.value = 0;
  }
  return false;
}

async function handleProcess(docId: string) {
  try {
    message.loading({ content: '处理中...', key: 'process', duration: 0 });
    await processDocumentApi(docId);
    message.success({ content: '处理完成', key: 'process' });
    if (expandedKbId.value) documents.value = await getDocumentsApi(expandedKbId.value);
  } catch {
    message.error({ content: '处理失败', key: 'process' });
  }
}

async function handlePreviewChunks(docId: string, title: string) {
  showChunkPreview.value = true;
  chunkDocTitle.value = title;
  chunksLoading.value = true;
  chunks.value = [];
  expandedChunkKeys.value = [];
  try {
    chunks.value = await getDocumentChunksApi(docId);
  } catch {
    message.error('加载分片失败');
  } finally {
    chunksLoading.value = false;
  }
}

onMounted(loadData);
</script>

<template>
  <Page auto-content-height>
    <div class="mb-4 flex items-center justify-between">
      <h2 class="text-lg font-medium">知识库管理</h2>
      <Button type="primary" @click="showCreate = true">创建知识库</Button>
    </div>

    <!-- Knowledge Base Table -->
    <Table
      :columns="columns"
      :data-source="knowledgeBases"
      :loading="loading"
      row-key="id"
      :pagination="false"
    >
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'action'">
          <Space>
            <Button size="small" @click="handleExpand(record.id)">
              {{ expandedKbId === record.id ? '收起文档' : '查看文档' }}
            </Button>
            <Popconfirm title="确定删除？" @confirm="handleDelete(record.id)">
              <Button size="small" danger>删除</Button>
            </Popconfirm>
          </Space>
        </template>
      </template>
    </Table>

    <!-- Documents for expanded KB -->
    <div v-if="expandedKbId" class="mt-4 rounded-lg border border-border p-4">
      <div class="mb-3 flex items-center justify-between">
        <h3 class="font-medium">文档列表</h3>
        <Upload
          :show-upload-list="false"
          :before-upload="(file: File) => handleUpload(expandedKbId!, file)"
          accept=".txt,.md,.pdf,.doc,.docx"
        >
          <Button type="primary" size="small" :loading="uploading">上传文档</Button>
        </Upload>
      </div>
      <Progress v-if="uploading" :percent="uploadProgress" class="mb-3" size="small" />
      <Table
        :columns="docColumns"
        :data-source="documents"
        :loading="docsLoading"
        row-key="id"
        :pagination="false"
        size="small"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'action'">
            <Space>
              <Button
                v-if="record.status === 'Pending' || record.status === 'Failed'"
                size="small"
                @click="handleProcess(record.id)"
              >
                处理
              </Button>
              <Button
                v-if="record.chunkCount > 0"
                size="small"
                type="link"
                @click="handlePreviewChunks(record.id, record.title)"
              >
                分片预览
              </Button>
              <Tag v-if="record.status === 'Completed' && record.chunkCount === 0" color="success">
                已处理
              </Tag>
            </Space>
          </template>
        </template>
      </Table>
    </div>

    <!-- Create Modal -->
    <Modal v-model:open="showCreate" title="创建知识库" @ok="handleCreate">
      <Form layout="vertical">
        <FormItem label="名称" required>
          <Input v-model:value="formState.name" placeholder="知识库名称" />
        </FormItem>
        <FormItem label="描述">
          <Input.TextArea v-model:value="formState.description" :rows="2" placeholder="可选描述" />
        </FormItem>
        <FormItem label="分块大小">
          <InputNumber v-model:value="formState.chunkSize" :min="100" :max="2000" />
        </FormItem>
        <FormItem label="分块重叠">
          <InputNumber v-model:value="formState.chunkOverlap" :min="0" :max="500" />
        </FormItem>
      </Form>
    </Modal>

    <!-- Chunk Preview Modal -->
    <Modal
      v-model:open="showChunkPreview"
      :title="`分片预览 — ${chunkDocTitle}`"
      width="900px"
      :footer="null"
    >
      <Spin :spinning="chunksLoading">
        <div v-if="chunks.length > 0" class="space-y-3">
          <!-- 统计摘要 -->
          <div class="mb-4 flex gap-4 text-sm">
            <span>总分块数: <strong>{{ chunks.length }}</strong></span>
            <span>已向量化: <strong class="text-green-600">{{ chunks.filter(c => c.hasEmbedding).length }}</strong></span>
            <span>未向量化: <strong class="text-red-500">{{ chunks.filter(c => !c.hasEmbedding).length }}</strong></span>
          </div>

          <Collapse v-model:activeKey="expandedChunkKeys" accordion>
            <CollapsePanel
              v-for="chunk in chunks"
              :key="chunk.chunkIndex"
              :header="`分片 #${chunk.chunkIndex} — ${chunk.tokenCount} tokens`"
            >
              <template #extra>
                <Badge
                  :status="chunk.hasEmbedding ? 'success' : 'error'"
                  :text="chunk.hasEmbedding ? `${chunk.embeddingDimension}维` : '未向量化'"
                />
              </template>

              <!-- 分块内容 -->
              <div class="mb-3 rounded bg-muted p-3 text-sm whitespace-pre-wrap break-words max-h-[200px] overflow-y-auto">
                {{ chunk.content }}
              </div>

              <!-- 向量信息 -->
              <Descriptions v-if="chunk.hasEmbedding" :column="2" size="small" bordered>
                <DescriptionsItem label="向量维度">
                  <Tag color="blue">{{ chunk.embeddingDimension }}</Tag>
                </DescriptionsItem>
                <DescriptionsItem label="Token 数">
                  {{ chunk.tokenCount }}
                </DescriptionsItem>
                <DescriptionsItem label="向量预览（前10维）" :span="2">
                  <code class="text-xs">
                    [{{ chunk.embeddingPreview?.map(v => v.toFixed(6)).join(', ') }}...]
                  </code>
                </DescriptionsItem>
              </Descriptions>
              <div v-else class="text-sm text-red-500">
                该分片尚未生成向量嵌入
              </div>
            </CollapsePanel>
          </Collapse>
        </div>
        <div v-else-if="!chunksLoading" class="py-8 text-center text-muted-foreground">
          暂无分片数据
        </div>
      </Spin>
    </Modal>
  </Page>
</template>
