<script setup lang="ts">
import { computed, ref } from 'vue';
import { useRouter } from 'vue-router';

import { $t } from '@easyflow/locales';

import { CopyDocument } from '@element-plus/icons-vue';
import { ElButton, ElCard, ElIcon, ElInput, ElMessage } from 'element-plus';

import { api } from '#/api/request';
import { copyTextWithFeedback } from '#/utils/clipboard-feedback';
import { buildAbsoluteAppRouteUrl } from '#/utils/share-route-context';

type EndpointEnumValue = {
  description: string;
  value: string;
};

type EndpointParam = {
  enumValues?: readonly EndpointEnumValue[];
  location: 'body' | 'header' | 'metadata' | 'multipart' | 'query';
  name: string;
  note?: string;
  required?: boolean;
  type?: string;
};

type EndpointExample = {
  content: string;
  title: string;
};

type EndpointDoc = {
  contentType?: string;
  examples?: EndpointExample[];
  hint: string;
  method: 'GET' | 'POST';
  notes?: string[];
  openByDefault?: boolean;
  params: EndpointParam[];
  path: string;
  permission: '知识导入' | '知识库维护' | '知识库读取';
};

const props = defineProps({
  knowledgeId: {
    type: String,
    required: true,
  },
  collectionType: {
    type: String,
    default: 'DOCUMENT',
  },
  manageable: {
    type: Boolean,
    default: true,
  },
});

const router = useRouter();
const createLoading = ref(false);
const generatedUrl = ref('');
const generatedExpireAt = ref('');

const apiBaseUrl = computed(() => {
  const appBasePath = (import.meta.env.BASE_URL || '/').replace(/\/$/, '');
  if (typeof window === 'undefined') {
    return `${appBasePath}/public-api/knowledge-share`;
  }
  return `${window.location.origin}${appBasePath}/public-api/knowledge-share`;
});

const formatJson = (value: unknown) => JSON.stringify(value, null, 2);

const retrievalModeEnumValues: readonly EndpointEnumValue[] = [
  { value: 'VECTOR', description: '向量语义召回' },
  { value: 'KEYWORD', description: '关键词全文召回' },
  { value: 'HYBRID', description: '混合召回，默认值' },
];

const chunkStrategyEnumValues: readonly EndpointEnumValue[] = [
  { value: 'AUTO', description: '自动选择分块策略，默认值' },
  { value: 'MARKDOWN_SECTION', description: '按 Markdown 标题层级分块' },
  { value: 'OUTLINE_SECTION', description: '按文档大纲或章节分块' },
  { value: 'QA_PAIR', description: '按问答对分块' },
  { value: 'PARAGRAPH_LENGTH', description: '按段落和长度分块' },
  { value: 'CUSTOM_REGEX', description: '按自定义正则表达式分块' },
];

const duplicatePolicyEnumValues: readonly EndpointEnumValue[] = [
  { value: 'SKIP', description: '跳过历史重复文件，默认值' },
  { value: 'OVERWRITE', description: '导入成功后覆盖历史文档' },
  { value: 'REIMPORT', description: '保留历史文档并重新导入一份' },
];

const importItemStatusEnumValues: readonly EndpointEnumValue[] = [
  { value: 'PENDING', description: '等待处理' },
  { value: 'UPLOADING', description: '文件正在上传' },
  { value: 'RUNNING', description: '正在处理' },
  { value: 'UPLOADED', description: '文件已上传' },
  { value: 'FAILED', description: '处理失败' },
  { value: 'COMPLETED', description: '处理完成' },
  { value: 'SKIPPED', description: '因重复而跳过' },
  { value: 'CANCELLED', description: '文件随未启动批次一并取消' },
];

const parameterTypes: Record<string, string> = {
  answerHtml: 'string',
  categoryId: 'string (ID)',
  collectionId: 'string (ID)',
  content: 'string',
  documentId: 'string (ID)',
  file: 'File',
  fileKeys: 'string[]',
  files: 'File[]',
  id: 'string (ID)',
  itemStatus: 'enum string',
  keyword: 'string',
  knowledgeId: 'string (ID)',
  metadata: 'JSON',
  'metadata.chunkStrategy': 'object',
  'metadata.chunkStrategy.strategyCode': 'enum string',
  'metadata.duplicatePolicy': 'enum string',
  'metadata.files': 'object[]',
  'metadata.files[].clientFileKey': 'string',
  'metadata.files[].fileName': 'string',
  'metadata.files[].relativePath': 'string',
  'metadata.knowledgeId': 'string (ID)',
  pageNumber: 'integer',
  pageSize: 'integer',
  question: 'string',
  retrievalMode: 'enum string',
  taskId: 'string (ID)',
};

const parameterDescriptions: Record<string, string> = {
  answerHtml: 'FAQ 答案 HTML',
  categoryId: 'FAQ 分类 ID',
  collectionId: '知识库 ID',
  content: '分块正文',
  documentId: '文档 ID',
  file: '待上传文件',
  fileKeys: '需要重试的文件键',
  files: '待导入文件列表',
  id: '数据 ID',
  itemStatus: '文件处理状态筛选',
  keyword: '检索关键词',
  knowledgeId: '知识库 ID',
  metadata: '导入元数据与文件清单',
  'metadata.chunkStrategy': '分块策略，省略时默认 AUTO',
  'metadata.chunkStrategy.strategyCode': '分块策略编码',
  'metadata.duplicatePolicy': '重复策略，默认 SKIP',
  'metadata.files': '与文件 Part 一一对应的清单',
  'metadata.files[].clientFileKey': '批次内唯一的文件键，最长 64 字符',
  'metadata.files[].fileName': '文件名，须与对应文件 Part 一致',
  'metadata.files[].relativePath': '文件夹内相对路径',
  'metadata.knowledgeId': '目标知识库 ID',
  pageNumber: '页码，默认 1',
  pageSize: '每页条数',
  question: 'FAQ 问题',
  retrievalMode: '召回方式',
  taskId: '导入任务 ID',
};

const parameterLocationLabels: Record<EndpointParam['location'], string> = {
  body: 'JSON Body',
  header: 'Header',
  metadata: 'metadata JSON',
  multipart: 'Multipart',
  query: 'Query',
};

const buildJsonPostExample = (
  path: string,
  body: unknown,
  extraHeaders: string[] = [],
) => {
  const headers = [
    "  -H 'ApiKey: 你的访问令牌' \\",
    ...extraHeaders.map((header) => `  -H '${header}' \\`),
    "  -H 'Content-Type: application/json' \\",
  ];
  return [
    `curl -X POST '${apiBaseUrl.value}${path}' \\`,
    ...headers,
    `  --data '${formatJson(body)}'`,
  ].join('\n');
};

const detailExample = computed(() => {
  return [
    `curl -X GET '${apiBaseUrl.value}/detail?knowledgeId=${props.knowledgeId}&pageNumber=1&pageSize=50' \\`,
    "  -H 'ApiKey: 你的访问令牌'",
  ].join('\n');
});

const searchExample = computed(() => {
  return [
    `curl -G '${apiBaseUrl.value}/search' \\`,
    "  -H 'ApiKey: 你的访问令牌' \\",
    `  --data-urlencode 'knowledgeId=${props.knowledgeId}' \\`,
    "  --data-urlencode 'keyword=测试问题'",
  ].join('\n');
});

const endpointDocs = computed(() => {
  const documentRemoveBody = {
    knowledgeId: props.knowledgeId,
    id: '文档ID',
  };
  const chunkUpdateBody = {
    knowledgeId: props.knowledgeId,
    id: '分块ID',
    content: '更新后的分块内容',
  };
  const chunkRemoveBody = {
    knowledgeId: props.knowledgeId,
    id: '分块ID',
  };
  const faqSaveBody = {
    collectionId: props.knowledgeId,
    question: '如何申请账号？',
    answerHtml: '<p>请联系管理员开通账号。</p>',
  };
  const faqUpdateBody = {
    id: 'FAQ ID',
    collectionId: props.knowledgeId,
    question: '如何修改账号信息？',
    answerHtml: '<p>请在个人中心修改。</p>',
  };
  const faqRemoveBody = {
    id: 'FAQ ID',
  };
  const faqImportResponseExample = formatJson({
    errorCode: 0,
    message: '成功',
    data: {
      totalCount: 100,
      successCount: 98,
      errorCount: 2,
      errorRows: [
        {
          rowNumber: 12,
          categoryPath: '默认分类',
          question: '示例问题',
          reason: '问题不能为空或格式不正确',
        },
      ],
    },
  });
  const detailDocumentRecords =
    props.collectionType === 'FAQ'
      ? []
      : [
          {
            id: '文档ID',
            title: 'manual.pdf',
            documentType: 'pdf',
            contentType: 'application/pdf',
            processStatus: 'INDEXED',
            chunkCount: 12,
            progressPercent: 100,
            created: '2026-08-02 16:30:00',
            modified: '2026-08-02 16:31:00',
          },
        ];
  const detailResponseExample = formatJson({
    errorCode: 0,
    message: '成功',
    data: {
      id: props.knowledgeId,
      title: '示例知识库',
      collectionType: props.collectionType,
      documents: {
        pageNumber: 1,
        pageSize: 50,
        totalPage: detailDocumentRecords.length > 0 ? 1 : 0,
        totalRow: detailDocumentRecords.length,
        records: detailDocumentRecords,
      },
    },
  });
  const searchResponseExample = formatJson({
    errorCode: 0,
    message: '成功',
    data:
      props.collectionType === 'FAQ'
        ? [
            {
              resultType: 'FAQ',
              faqId: 'FAQ ID',
              question: '如何申请账号？',
              answerText: '请联系管理员开通账号。',
              categoryId: 'FAQ 分类 ID',
              content: '问题：如何申请账号？\n答案：请联系管理员开通账号。',
              score: 0.8732,
              hitSource: 'HYBRID',
            },
          ]
        : [
            {
              resultType: 'DOCUMENT',
              documentId: '文档ID',
              documentName: 'manual.pdf',
              sourceFileName: 'manual.pdf',
              content: '命中的文档分块内容',
              score: 0.8732,
              hitSource: 'HYBRID',
            },
          ],
  });
  const retryBody = {
    taskId: '导入接口返回的 taskId',
    fileKeys: ['file-1'],
  };
  const importMetadata = {
    knowledgeId: props.knowledgeId,
    chunkStrategy: {
      strategyCode: 'AUTO',
    },
    duplicatePolicy: 'SKIP',
    files: [
      {
        clientFileKey: 'file-1',
        fileName: 'manual.pdf',
        relativePath: 'docs/manual.pdf',
      },
    ],
  };
  const importCurlExample = [
    "FILE='./docs/manual.pdf'",
    `KNOWLEDGE_ID='${props.knowledgeId}'`,
    'FILE_NAME=$(basename "$FILE")',
    'METADATA=$(printf \'{"knowledgeId":"%s","chunkStrategy":{"strategyCode":"AUTO"},"duplicatePolicy":"SKIP","files":[{"clientFileKey":"file-1","fileName":"%s","relativePath":"%s"}]}\' "$KNOWLEDGE_ID" "$FILE_NAME" "$FILE_NAME")',
    '',
    `curl -X POST '${apiBaseUrl.value}/document/import/batch' \\`,
    "  -H 'ApiKey: 你的访问令牌' \\",
    '  -F "metadata=$METADATA;type=application/json" \\',
    '  -F "files=@$FILE"',
  ].join('\n');
  const importResponseExample = formatJson({
    errorCode: 0,
    message: '成功',
    data: {
      taskId: '异步任务ID',
      status: 'RUNNING',
      totalCount: 1,
      totalBytes: 123_456,
      createdAt: '2026-08-02T16:30:00+08:00',
    },
  });
  const importStatusExample = [
    `curl -G '${apiBaseUrl.value}/document/import/batch/status' \\`,
    "  -H 'ApiKey: 你的访问令牌' \\",
    "  --data-urlencode 'taskId=导入接口返回的 taskId' \\",
    "  --data-urlencode 'pageNumber=1' \\",
    "  --data-urlencode 'pageSize=20'",
  ].join('\n');
  const importStatusResponseExample = formatJson({
    errorCode: 0,
    message: '成功',
    data: {
      taskId: '异步任务ID',
      knowledgeId: props.knowledgeId,
      status: 'PARTIAL_SUCCEEDED',
      progressPercent: 100,
      counts: {
        total: 2,
        completed: 1,
        processing: 0,
        pending: 0,
        failed: 1,
        skipped: 0,
        retryableFailed: 1,
      },
      canRetry: true,
      items: {
        pageNumber: 1,
        pageSize: 20,
        total: 2,
        records: [
          {
            fileKey: 'file-1',
            relativePath: 'docs/manual.pdf',
            documentId: '文档ID',
            stage: 'PARSE',
            status: 'FAILED',
            attemptCount: 1,
            retryable: true,
            error: {
              code: 'parse_service_unavailable',
              message: '文档解析服务暂时不可用',
            },
          },
        ],
      },
    },
  });
  const retryResponseExample = formatJson({
    errorCode: 0,
    message: '成功',
    data: {
      taskId: '异步任务ID',
      status: 'RUNNING',
      retriedCount: 1,
    },
  });

  const commonEndpoints: EndpointDoc[] = [
    {
      method: 'GET',
      path: '/detail',
      hint: '获取知识库详情',
      permission: '知识库读取',
      params: [
        { name: 'knowledgeId', location: 'query', required: true },
        { name: 'pageNumber', location: 'query', note: '默认 1' },
        { name: 'pageSize', location: 'query', note: '默认 50，最大 100' },
      ],
      notes: [
        '知识库原有字段保持在 data 顶层；documents 返回已上传文档的分页摘要。',
        '文档摘要包含 ID、标题、类型、处理状态、分块数、处理进度和时间；FAQ 知识库返回空文档页。',
      ],
      examples: [
        { title: 'cURL 示例', content: detailExample.value },
        { title: '响应示例', content: detailResponseExample },
      ],
    },
    {
      method: 'GET',
      path: '/search',
      hint: '知识检索',
      permission: '知识库读取',
      params: [
        { name: 'knowledgeId', location: 'query', required: true },
        { name: 'keyword', location: 'query', required: true },
        {
          name: 'retrievalMode',
          location: 'query',
          enumValues: retrievalModeEnumValues,
          note: '召回方式，不传时默认 HYBRID',
        },
      ],
      notes: [
        'resultType 用于区分 DOCUMENT 与 FAQ。',
        '文档命中返回 documentId、documentName；FAQ 命中返回 faqId、question、answerText、categoryId。',
        'sourceFileName 作为文档名称兼容字段继续保留；FAQ 完整 HTML 可通过 /faq/detail 查询。',
      ],
      examples: [
        { title: 'cURL 示例', content: searchExample.value },
        { title: '响应示例', content: searchResponseExample },
      ],
    },
  ];
  const typeEndpoints: EndpointDoc[] =
    props.collectionType === 'FAQ'
      ? [
          {
            method: 'GET',
            path: '/faq/page',
            hint: 'FAQ 分页',
            permission: '知识库读取',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
              { name: 'question', location: 'query', note: '问题关键字' },
              { name: 'categoryId', location: 'query', note: '分类 ID' },
              { name: 'pageNumber', location: 'query', note: '默认 1' },
              { name: 'pageSize', location: 'query', note: '默认 10' },
            ],
          },
          {
            method: 'GET',
            path: '/faq/detail',
            hint: 'FAQ 详情',
            permission: '知识库读取',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
              { name: 'id', location: 'query', required: true, note: 'FAQ ID' },
            ],
          },
          {
            method: 'POST',
            path: '/faq/save',
            hint: '新增 FAQ',
            permission: '知识库维护',
            contentType: 'application/json',
            params: [
              { name: 'collectionId', location: 'body', required: true },
              { name: 'question', location: 'body', required: true },
              { name: 'answerHtml', location: 'body', required: true },
              { name: 'categoryId', location: 'body', note: '分类 ID' },
            ],
            examples: [
              { title: '请求体示例', content: formatJson(faqSaveBody) },
              {
                title: 'cURL 示例',
                content: buildJsonPostExample('/faq/save', faqSaveBody),
              },
            ],
          },
          {
            method: 'POST',
            path: '/faq/update',
            hint: '修改 FAQ',
            permission: '知识库维护',
            contentType: 'application/json',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
              { name: 'id', location: 'body', required: true, note: 'FAQ ID' },
              {
                name: 'collectionId',
                location: 'body',
                note: '不传时保持原知识库 ID',
              },
              { name: 'question', location: 'body', required: true },
              { name: 'answerHtml', location: 'body', required: true },
              { name: 'categoryId', location: 'body', note: '分类 ID' },
            ],
            examples: [
              { title: '请求体示例', content: formatJson(faqUpdateBody) },
              {
                title: 'cURL 示例',
                content: buildJsonPostExample(
                  `/faq/update?knowledgeId=${props.knowledgeId}`,
                  faqUpdateBody,
                ),
              },
            ],
          },
          {
            method: 'POST',
            path: '/faq/remove',
            hint: '删除 FAQ',
            permission: '知识库维护',
            contentType: 'application/json',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
              { name: 'id', location: 'body', required: true, note: 'FAQ ID' },
            ],
            examples: [
              { title: '请求体示例', content: formatJson(faqRemoveBody) },
              {
                title: 'cURL 示例',
                content: buildJsonPostExample(
                  `/faq/remove?knowledgeId=${props.knowledgeId}`,
                  faqRemoveBody,
                ),
              },
            ],
          },
          {
            method: 'POST',
            path: '/faq/importExcel',
            hint: '导入 FAQ Excel',
            permission: '知识导入',
            contentType: 'multipart/form-data',
            params: [
              {
                name: 'collectionId',
                location: 'multipart',
                required: true,
              },
              { name: 'file', location: 'multipart', required: true },
            ],
            notes: [
              '仅支持 xlsx、xls 文件，单个文件不超过 10 MB，最多导入 5000 条。',
              '请先下载导入模板并保持模板列结构。',
              '由调用端自动生成 multipart boundary，不要手动设置 Content-Type 请求头。',
            ],
            examples: [
              {
                title: 'cURL 示例',
                content: [
                  `curl -X POST '${apiBaseUrl.value}/faq/importExcel' \\`,
                  "  -H 'ApiKey: 你的访问令牌' \\",
                  `  -F 'collectionId=${props.knowledgeId}' \\`,
                  "  -F 'file=@./faq_import.xlsx'",
                ].join('\n'),
              },
              {
                title: '响应示例',
                content: faqImportResponseExample,
              },
            ],
          },
          {
            method: 'GET',
            path: '/faq/downloadImportTemplate',
            hint: '下载 FAQ 导入模板',
            permission: '知识导入',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
            ],
          },
          {
            method: 'GET',
            path: '/faq/exportExcel',
            hint: '导出 FAQ Excel',
            permission: '知识库读取',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
            ],
          },
        ]
      : [
          {
            method: 'GET',
            path: '/document/page',
            hint: '文档分页',
            permission: '知识库读取',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
              { name: 'documentId', location: 'query', note: '文档 ID' },
              { name: 'pageNumber', location: 'query', note: '默认 1' },
              { name: 'pageSize', location: 'query', note: '默认 10' },
            ],
          },
          {
            method: 'GET',
            path: '/document/download',
            hint: '下载文档',
            permission: '知识库读取',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
              { name: 'documentId', location: 'query', required: true },
            ],
          },
          {
            method: 'GET',
            path: '/documentChunk/page',
            hint: '文档分块分页',
            permission: '知识库读取',
            params: [
              { name: 'knowledgeId', location: 'query', required: true },
              { name: 'documentId', location: 'query', required: true },
              { name: 'pageNumber', location: 'query', note: '默认 1' },
              { name: 'pageSize', location: 'query', note: '默认 10' },
            ],
          },
          {
            method: 'POST',
            path: '/document/import/batch',
            hint: '批量异步导入',
            permission: '知识导入',
            contentType: 'multipart/form-data',
            openByDefault: true,
            params: [
              {
                name: 'metadata',
                location: 'multipart',
                type: 'JSON',
                required: true,
                note: 'application/json，含知识库 ID、文件清单和可选分块策略',
              },
              {
                name: 'metadata.knowledgeId',
                location: 'metadata',
                required: true,
              },
              {
                name: 'metadata.chunkStrategy',
                location: 'metadata',
              },
              {
                name: 'metadata.chunkStrategy.strategyCode',
                location: 'metadata',
                enumValues: chunkStrategyEnumValues,
                note: '分块策略编码，不传时默认 AUTO',
              },
              {
                name: 'metadata.duplicatePolicy',
                location: 'metadata',
                enumValues: duplicatePolicyEnumValues,
                note: '重复文件处理策略，不传时默认 SKIP',
              },
              {
                name: 'metadata.files',
                location: 'metadata',
                required: true,
              },
              {
                name: 'metadata.files[].clientFileKey',
                location: 'metadata',
                required: true,
              },
              {
                name: 'metadata.files[].fileName',
                location: 'metadata',
                required: true,
              },
              {
                name: 'metadata.files[].relativePath',
                location: 'metadata',
                note: '可省略，默认使用 fileName',
              },
              {
                name: 'files',
                location: 'multipart',
                type: 'File[]',
                required: true,
                note: '同名多文件 Part，总计不超过 200 MiB',
              },
            ],
            notes: [
              'metadata 是 Content-Type 为 application/json 的 multipart Part，不是普通表单字符串。',
              'metadata.knowledgeId 填当前知识库 ID；chunkStrategy 可省略；duplicatePolicy 默认 SKIP。',
              'metadata.files 中每项填写 clientFileKey、fileName 和可选 relativePath；文件大小由服务端实际读取并统计。',
              '支持 txt、md、pdf、docx、pptx、xlsx、csv；单文件不超过 100 MiB，单批不超过 200 MiB，最多 200 个文件。',
              'metadata 最大 1 MiB；metadata.files 必须与 files Part 数量、顺序和文件名一致。',
              'chunkStrategy 可不传，默认 AUTO；duplicatePolicy 支持 SKIP、OVERWRITE、REIMPORT。',
              '服务端会按调用者、元数据和文件内容生成请求指纹，任务完成后 10 分钟内的重复提交会返回原 taskId。',
              '由调用端自动生成 multipart boundary，不要手动设置 Content-Type 请求头。',
            ],
            examples: [
              {
                title: 'metadata Part 填写示例',
                content: formatJson(importMetadata),
              },
              { title: '可执行 cURL 示例', content: importCurlExample },
              {
                title: 'HTTP 202 响应示例',
                content: importResponseExample,
              },
            ],
          },
          {
            method: 'GET',
            path: '/document/import/batch/status',
            hint: '查询导入状态',
            permission: '知识导入',
            params: [
              { name: 'taskId', location: 'query', required: true },
              {
                name: 'itemStatus',
                location: 'query',
                enumValues: importItemStatusEnumValues,
                note: '文件处理状态筛选，不传时查询全部状态',
              },
              { name: 'pageNumber', location: 'query', note: '默认 1' },
              {
                name: 'pageSize',
                location: 'query',
                note: '默认 20，最大 100',
              },
            ],
            notes: [
              '公开状态包括 QUEUED、RUNNING、SUCCEEDED、FAILED、PARTIAL_SUCCEEDED、INTERRUPTED、CANCELLED；进入终态后停止轮询。',
              '只有 canRetry=true 的任务允许重试。',
            ],
            examples: [
              { title: 'cURL 示例', content: importStatusExample },
              {
                title: '响应示例',
                content: importStatusResponseExample,
              },
            ],
          },
          {
            method: 'POST',
            path: '/document/import/batch/retry',
            hint: '重试异常文件',
            permission: '知识导入',
            contentType: 'application/json',
            params: [
              { name: 'taskId', location: 'body', required: true },
              {
                name: 'fileKeys',
                location: 'body',
                type: 'string[]',
                note: '省略时重试全部；最多 200 个，每项最长 64 字符',
              },
            ],
            notes: [
              '省略 fileKeys 时重试全部可恢复失败项；指定时只重试对应文件。',
              'fileKeys 不允许传空数组、空值、重复值或超过 64 字符的值，最多 200 个。',
              '任务正在运行时不能重复领取重试，请继续使用 taskId 查询状态。',
            ],
            examples: [
              { title: '请求体示例', content: formatJson(retryBody) },
              {
                title: 'cURL 示例',
                content: buildJsonPostExample(
                  '/document/import/batch/retry',
                  retryBody,
                ),
              },
              { title: '响应示例', content: retryResponseExample },
            ],
          },
          {
            method: 'POST',
            path: '/document/remove',
            hint: '删除文档',
            permission: '知识库维护',
            contentType: 'application/json',
            params: [
              { name: 'knowledgeId', location: 'body', required: true },
              { name: 'id', location: 'body', required: true, note: '文档 ID' },
            ],
            examples: [
              { title: '请求体示例', content: formatJson(documentRemoveBody) },
              {
                title: 'cURL 示例',
                content: buildJsonPostExample(
                  '/document/remove',
                  documentRemoveBody,
                ),
              },
            ],
          },
          {
            method: 'POST',
            path: '/documentChunk/update',
            hint: '更新文档分块',
            permission: '知识库维护',
            contentType: 'application/json',
            params: [
              { name: 'knowledgeId', location: 'body', required: true },
              { name: 'id', location: 'body', required: true, note: '分块 ID' },
              { name: 'content', location: 'body', required: true },
            ],
            examples: [
              { title: '请求体示例', content: formatJson(chunkUpdateBody) },
              {
                title: 'cURL 示例',
                content: buildJsonPostExample(
                  '/documentChunk/update',
                  chunkUpdateBody,
                ),
              },
            ],
          },
          {
            method: 'POST',
            path: '/documentChunk/remove',
            hint: '删除文档分块',
            permission: '知识库维护',
            contentType: 'application/json',
            params: [
              { name: 'knowledgeId', location: 'body', required: true },
              { name: 'id', location: 'body', required: true, note: '分块 ID' },
            ],
            examples: [
              { title: '请求体示例', content: formatJson(chunkRemoveBody) },
              {
                title: 'cURL 示例',
                content: buildJsonPostExample(
                  '/documentChunk/remove',
                  chunkRemoveBody,
                ),
              },
            ],
          },
        ];
  return [...commonEndpoints, ...typeEndpoints].map((item) => ({
    ...item,
    url: `${apiBaseUrl.value}${item.path}`,
  }));
});

const getParameterType = (param: EndpointParam) =>
  param.type || parameterTypes[param.name] || 'string';

const getParameterDescription = (param: EndpointParam) =>
  param.note || parameterDescriptions[param.name] || '接口参数';

const createShare = async () => {
  if (!props.manageable) {
    ElMessage.warning($t('documentCollection.managePermissionHint'));
    return;
  }
  createLoading.value = true;
  try {
    const res = await api.post('/api/v1/knowledgeShare/url/create', {
      knowledgeId: props.knowledgeId,
    });
    if (res.errorCode === 0) {
      const shareKey = String(res.data?.shareKey || '').trim();
      generatedUrl.value = shareKey
        ? buildAbsoluteAppRouteUrl(
            router.resolve({
              name: 'KnowledgeShare',
              query: { shareKey },
            }).href,
          )
        : '';
      generatedExpireAt.value = res.data?.expiresAt || '';
      ElMessage.success('已创建分享链接');
    }
  } finally {
    createLoading.value = false;
  }
};

const copyGeneratedUrl = async () => {
  if (!generatedUrl.value) {
    ElMessage.warning('请先生成分享链接');
    return;
  }
  await copyTextWithFeedback(generatedUrl.value, '已复制分享链接');
};

const copyApiExample = async (content: string) => {
  await copyTextWithFeedback(content, '已复制调用示例');
};

const copyEndpointUrl = async (url: string) => {
  await copyTextWithFeedback(url, '已复制接口地址');
};
</script>

<template>
  <div class="share-management">
    <ElCard shadow="never" class="share-card">
      <template #header>
        <div class="share-card__header">
          <div>
            <div class="share-card__title">当前分享链接</div>
            <div class="share-card__desc">
              默认有效期 30 分钟。重新生成后旧链接立即失效。
            </div>
          </div>
          <ElButton
            type="primary"
            :loading="createLoading"
            :disabled="!props.manageable"
            @click="createShare"
          >
            {{ generatedUrl ? '重新生成链接' : '生成分享链接' }}
          </ElButton>
        </div>
      </template>

      <div v-if="generatedUrl" class="share-result">
        <div class="share-result__row">
          <ElInput v-model="generatedUrl" readonly />
          <ElButton
            text
            circle
            :icon="CopyDocument"
            aria-label="复制分享链接"
            title="复制分享链接"
            @click="copyGeneratedUrl"
          />
        </div>
        <div class="share-result__meta">过期时间：{{ generatedExpireAt }}</div>
      </div>
      <div v-else class="share-empty">暂未生成分享链接</div>
    </ElCard>

    <ElCard shadow="never" class="share-card">
      <template #header>
        <div class="share-card__header share-card__header--stack">
          <div>
            <div class="share-card__title">API 调用方式</div>
            <div class="share-card__desc">
              使用已开通对应知识库权限的访问令牌，通过
              <code>ApiKey</code> 请求头调用。示例已自动带入当前知识库 ID。
            </div>
          </div>
        </div>
      </template>

      <div class="api-doc">
        <div class="api-doc__meta">
          <div class="api-doc__item">
            <span class="api-doc__label">接口前缀</span>
            <code class="api-doc__value">{{ apiBaseUrl }}</code>
          </div>
          <div class="api-doc__item">
            <span class="api-doc__label">请求头</span>
            <code class="api-doc__value">ApiKey: 你的访问令牌</code>
          </div>
          <div class="api-doc__item">
            <span class="api-doc__label">JSON 请求</span>
            <code class="api-doc__value">Content-Type: application/json</code>
          </div>
          <div class="api-doc__item">
            <span class="api-doc__label">文件上传</span>
            <code class="api-doc__value">multipart/form-data</code>
            <span class="api-doc__helper">由调用端自动生成 boundary</span>
          </div>
          <div class="api-doc__item">
            <span class="api-doc__label">当前知识库 ID</span>
            <code class="api-doc__value">{{ props.knowledgeId }}</code>
          </div>
        </div>

        <div
          v-if="props.collectionType === 'DOCUMENT'"
          class="api-doc__section api-doc__import-flow"
        >
          <div class="api-doc__section-title">批量导入调用流程</div>
          <ol class="api-doc__steps">
            <li>提交 multipart 请求，保存 HTTP 202 响应中的 taskId。</li>
            <li>使用 taskId 查询任务状态，按需分页查看每个文件的结果。</li>
            <li>
              当 canRetry=true 时，使用 taskId 重试全部异常文件，或通过 fileKeys
              指定部分文件。
            </li>
          </ol>
        </div>

        <div class="api-doc__section">
          <div class="api-doc__section-title">接口列表</div>
          <div class="api-doc__endpoint-list">
            <div
              v-for="endpoint in endpointDocs"
              :key="endpoint.path"
              class="api-doc__endpoint"
            >
              <div class="api-doc__endpoint-main">
                <span class="api-doc__method">{{ endpoint.method }}</span>
                <code>{{ endpoint.path }}</code>
                <span class="api-doc__hint">{{ endpoint.hint }}</span>
                <span class="api-doc__permission">{{
                  endpoint.permission
                }}</span>
                <ElButton
                  text
                  circle
                  :icon="CopyDocument"
                  class="api-doc__copy"
                  :aria-label="`复制 ${endpoint.path}`"
                  :title="`复制 ${endpoint.url}`"
                  @click="copyEndpointUrl(endpoint.url)"
                />
              </div>
              <div class="api-doc__parameter-table-wrap">
                <table
                  class="api-doc__parameter-table"
                  :aria-label="`${endpoint.hint}参数说明`"
                >
                  <thead>
                    <tr>
                      <th scope="col">参数</th>
                      <th scope="col">位置</th>
                      <th scope="col">类型</th>
                      <th scope="col">必填</th>
                      <th scope="col">说明</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr
                      v-for="param in endpoint.params"
                      :key="`${endpoint.path}-${param.location}-${param.name}`"
                    >
                      <td>
                        <code>{{ param.name }}</code>
                      </td>
                      <td>{{ parameterLocationLabels[param.location] }}</td>
                      <td>{{ getParameterType(param) }}</td>
                      <td>{{ param.required ? '是' : '否' }}</td>
                      <td>
                        <div>{{ getParameterDescription(param) }}</div>
                        <ul
                          v-if="param.enumValues?.length"
                          class="api-doc__enum-list"
                        >
                          <li
                            v-for="enumValue in param.enumValues"
                            :key="enumValue.value"
                          >
                            <code>{{ enumValue.value }}</code>
                            <span>{{ enumValue.description }}</span>
                          </li>
                        </ul>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
              <details
                v-if="
                  endpoint.contentType ||
                  endpoint.notes?.length ||
                  endpoint.examples?.length
                "
                class="api-doc__endpoint-details"
                :open="endpoint.openByDefault"
              >
                <summary>
                  {{
                    endpoint.openByDefault
                      ? '必看：metadata、文件 Part 与完整示例'
                      : '查看请求与响应说明'
                  }}
                </summary>
                <div class="api-doc__endpoint-details-content">
                  <div
                    v-if="endpoint.contentType"
                    class="api-doc__content-type"
                  >
                    <span>Content-Type</span>
                    <code>{{ endpoint.contentType }}</code>
                  </div>
                  <ul v-if="endpoint.notes?.length" class="api-doc__notes">
                    <li v-for="note in endpoint.notes" :key="note">
                      {{ note }}
                    </li>
                  </ul>
                  <div
                    v-for="example in endpoint.examples"
                    :key="`${endpoint.path}-${example.title}`"
                    class="api-doc__example"
                  >
                    <div class="api-doc__example-title">
                      {{ example.title }}
                    </div>
                    <div class="api-doc__code-wrap">
                      <button
                        type="button"
                        class="api-doc__code-copy"
                        :title="`复制${example.title}`"
                        :aria-label="`复制${endpoint.hint}${example.title}`"
                        @click="copyApiExample(example.content)"
                      >
                        <ElIcon><CopyDocument /></ElIcon>
                      </button>
                      <pre class="api-doc__code">{{ example.content }}</pre>
                    </div>
                  </div>
                </div>
              </details>
            </div>
          </div>
        </div>

        <div class="api-doc__section">
          <div class="api-doc__section-title">详情示例</div>
          <div class="api-doc__code-wrap">
            <button
              type="button"
              class="api-doc__code-copy"
              title="复制详情示例"
              aria-label="复制详情示例"
              @click="copyApiExample(detailExample)"
            >
              <ElIcon><CopyDocument /></ElIcon>
            </button>
            <pre class="api-doc__code">{{ detailExample }}</pre>
          </div>
        </div>

        <div class="api-doc__section">
          <div class="api-doc__section-title">检索示例</div>
          <div class="api-doc__code-wrap">
            <button
              type="button"
              class="api-doc__code-copy"
              title="复制检索示例"
              aria-label="复制检索示例"
              @click="copyApiExample(searchExample)"
            >
              <ElIcon><CopyDocument /></ElIcon>
            </button>
            <pre class="api-doc__code">{{ searchExample }}</pre>
          </div>
        </div>
      </div>
    </ElCard>
  </div>
</template>

<style scoped>
.share-management {
  display: grid;
  gap: 16px;
}

.share-card {
  border-radius: 16px;
}

.share-card__header {
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
}

.share-card__header--stack {
  align-items: flex-start;
}

.share-card__title {
  font-size: 16px;
  font-weight: 600;
}

.share-card__desc,
.share-result__meta {
  margin-top: 6px;
  font-size: 13px;
  color: var(--el-text-color-secondary);
}

.share-result {
  display: grid;
  gap: 8px;
  margin-bottom: 16px;
}

.share-result__row {
  display: flex;
  gap: 12px;
  align-items: center;
}

.share-empty {
  font-size: 13px;
  color: var(--el-text-color-secondary);
}

.api-doc {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
}

.api-doc__meta {
  display: grid;
  gap: 10px;
}

.api-doc__item {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}

.api-doc__label {
  min-width: 84px;
  font-size: 13px;
  color: var(--el-text-color-secondary);
}

.api-doc__value {
  padding: 4px 10px;
  font-size: 13px;
  color: var(--el-text-color-primary);
  background: var(--el-fill-color-light);
  border-radius: 10px;
}

.api-doc__helper {
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.api-doc__section {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  min-width: 0;
}

.api-doc__import-flow {
  padding: 16px;
  background: var(--el-fill-color-extra-light);
  border-radius: var(--el-border-radius-base);
}

.api-doc__steps {
  display: grid;
  gap: 8px;
  padding-left: 24px;
  margin: 0;
  font-size: 13px;
  line-height: 1.7;
  color: var(--el-text-color-regular);
}

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

.api-doc__endpoint-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
  min-width: 0;
}

.api-doc__endpoint {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
  min-width: 0;
  padding: 8px 0;
}

.api-doc__endpoint-main {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  font-size: 13px;
}

.api-doc__copy {
  flex: 0 0 auto;
}

.api-doc__method {
  min-width: 42px;
  font-weight: 600;
  color: var(--el-color-primary);
}

.api-doc__hint {
  color: var(--el-text-color-secondary);
}

.api-doc__permission {
  padding: 2px 8px;
  font-size: 12px;
  color: var(--el-color-primary);
  background: var(--el-color-primary-light-9);
  border-radius: 999px;
}

.api-doc__parameter-table-wrap {
  width: 100%;
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
}

.api-doc__parameter-table {
  width: 100%;
  min-width: 640px;
  font-size: 12px;
  color: var(--el-text-color-regular);
  table-layout: fixed;
  border-spacing: 0;
  border-collapse: separate;
  border: 1px solid var(--el-border-color-lighter);
  border-radius: var(--el-border-radius-base);
}

.api-doc__parameter-table th,
.api-doc__parameter-table td {
  padding: 8px 12px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.api-doc__parameter-table th {
  font-weight: 500;
  color: var(--el-text-color-secondary);
  white-space: nowrap;
  background: var(--el-fill-color-extra-light);
}

.api-doc__parameter-table th:first-child,
.api-doc__parameter-table td:first-child {
  width: 28%;
}

.api-doc__parameter-table th:nth-child(2),
.api-doc__parameter-table td:nth-child(2) {
  width: 14%;
  white-space: nowrap;
}

.api-doc__parameter-table th:nth-child(3),
.api-doc__parameter-table td:nth-child(3) {
  width: 12%;
  white-space: nowrap;
}

.api-doc__parameter-table th:nth-child(4),
.api-doc__parameter-table td:nth-child(4) {
  width: 8%;
  white-space: nowrap;
}

.api-doc__parameter-table tbody tr:last-child td {
  border-bottom: none;
}

.api-doc__parameter-table td:last-child {
  overflow-wrap: anywhere;
}

.api-doc__parameter-table code {
  white-space: normal;
  overflow-wrap: anywhere;
}

.api-doc__enum-list {
  display: grid;
  gap: 4px;
  padding: 0;
  margin: 6px 0 0;
  list-style: none;
}

.api-doc__enum-list li {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}

.api-doc__enum-list code {
  flex: 0 0 auto;
  color: var(--el-text-color-primary);
}

.api-doc__endpoint-details {
  margin-top: 4px;
  font-size: 13px;
}

.api-doc__endpoint-details > summary {
  width: fit-content;
  color: var(--el-color-primary);
  cursor: pointer;
}

.api-doc__endpoint-details > summary:focus-visible {
  border-radius: var(--el-border-radius-small);
  outline: 2px solid var(--el-color-primary-light-5);
  outline-offset: 2px;
}

.api-doc__endpoint-details-content {
  display: grid;
  gap: 16px;
  padding-top: 16px;
}

.api-doc__content-type {
  display: flex;
  gap: 8px;
  align-items: center;
  color: var(--el-text-color-secondary);
}

.api-doc__content-type code {
  color: var(--el-text-color-primary);
}

.api-doc__notes {
  display: grid;
  gap: 8px;
  padding-left: 24px;
  margin: 0;
  line-height: 1.6;
  color: var(--el-text-color-regular);
}

.api-doc__example {
  display: grid;
  gap: 8px;
}

.api-doc__example-title {
  font-weight: 500;
  color: var(--el-text-color-primary);
}

.api-doc__code {
  margin: 0;
  padding: 14px 16px;
  overflow-x: auto;
  font-size: 12px;
  line-height: 1.7;
  color: var(--el-text-color-primary);
  white-space: pre;
  background: var(--el-fill-color-light);
  border-radius: 14px;
}

.api-doc__code-wrap {
  position: relative;
}

.api-doc__code-copy {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  color: var(--el-text-color-secondary);
  cursor: pointer;
  background: transparent;
  border: none;
  border-radius: 8px;
}

.api-doc__code-copy:hover {
  color: var(--el-color-primary);
  background: var(--el-fill-color);
}

.api-doc__code-copy:focus-visible {
  outline: 2px solid var(--el-color-primary-light-5);
  outline-offset: 2px;
}

.api-doc__code-wrap .api-doc__code {
  padding-top: 40px;
}
</style>
