import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import {
  Button,
  Empty,
  Form,
  Input,
  Modal,
  Select,
  Spin,
  Table,
  Tabs,
  Tag,
  Tooltip,
  message,
} from "antd";
import {
  ArrowLeftOutlined,
  CheckOutlined,
  CloudUploadOutlined,
  DatabaseOutlined,
  DeleteOutlined,
  DownloadOutlined,
  EditOutlined,
  FileAddOutlined,
  FileTextOutlined,
  PictureOutlined,
  PlusOutlined,
  ReloadOutlined,
  SearchOutlined,
  TeamOutlined,
  UploadOutlined,
} from "@ant-design/icons";
import type { ColumnsType } from "antd/es/table";
import ImageWithFallback from "../common/ImageWithFallback";
import { getCurrentAuth } from "../../services/core/auth";
import {
  AiAgentContext,
  AiManualComponent,
  addAiAgentKnowledgeComponent,
  enableAiAgentKnowledgeForChat,
  fetchAiAgentComponents,
  isAiKnowledgeChatSelectable,
  resolveAiAgentContext,
} from "../../services/core/aiChat";
import {
  fetchPublishedWorkflows,
  fetchSpaces,
  PublishedWorkflow,
  SpaceInfo,
} from "../../services/core/marketplace";
import {
  KnowledgeComponent,
  KnowledgeConfigSaveParams,
  KnowledgeDocumentInfo,
  KnowledgeInfo,
  KnowledgeModelOption,
  KnowledgeQaInfo,
  KnowledgeRawSegmentInfo,
  addCustomKnowledgeDocument,
  addKnowledgeDocuments,
  addKnowledgeQa,
  addKnowledgeRawSegment,
  createKnowledgeConfig,
  deleteKnowledgeConfig,
  deleteKnowledgeDocument,
  deleteKnowledgeQa,
  deleteKnowledgeRawSegment,
  downloadKnowledgeQaTemplate,
  fetchEmbeddingModels,
  fetchKnowledgeComponents,
  fetchKnowledgeDetail,
  fetchKnowledgeDocuments,
  fetchKnowledgeQaList,
  fetchKnowledgeRawSegments,
  generateKnowledgeDocumentEmbeddings,
  generateKnowledgeDocumentQa,
  getKnowledgeId,
  importKnowledgeQaExcel,
  queryKnowledgeDocumentStatus,
  retryKnowledgeDocumentTask,
  updateKnowledgeConfig,
  updateKnowledgeDocumentName,
  updateKnowledgeQa,
  updateKnowledgeRawSegment,
  uploadKnowledgeAsset,
  uploadKnowledgeFile,
  validateKnowledgeFile,
} from "../../services/core/knowledge";
import styles from "../../styles/components/KnowledgePage.module.css";

const DOCUMENT_PAGE_SIZE = 48;
const SEGMENT_PAGE_SIZE = 30;
const QA_PAGE_SIZE = 20;
const KNOWLEDGE_ICON_MAX_SIZE = 2 * 1024 * 1024;

type DetailTabKey = "documents" | "segments" | "qa" | "graph";

interface KnowledgeFormValues {
  name: string;
  description?: string;
  embeddingModelId: number;
  dataParsingMethod?: "default" | "workflow";
  workflowId?: number;
}

interface CustomDocumentValues {
  name: string;
  fileContent: string;
}

interface RenameDocumentValues {
  name: string;
}

interface SegmentFormValues {
  rawTxt: string;
  sortIndex?: number;
}

interface QaFormValues {
  question: string;
  answer: string;
}

function formatDateTime(value?: string): string {
  if (!value) return "-";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString("zh-CN", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
  });
}

function formatBytes(value?: number): string {
  if (!value) return "0 B";
  if (value >= 1024 * 1024 * 1024) {
    return `${(value / 1024 / 1024 / 1024).toFixed(1)} GB`;
  }
  if (value >= 1024 * 1024) {
    return `${(value / 1024 / 1024).toFixed(1)} MB`;
  }
  if (value >= 1024) return `${(value / 1024).toFixed(1)} KB`;
  return `${value} B`;
}

function getInitial(name?: string): string {
  const trimmed = (name || "").trim();
  return trimmed ? trimmed.slice(0, 1).toUpperCase() : "知";
}

function getDocumentStatus(doc: KnowledgeDocumentInfo): {
  color: string;
  text: string;
} {
  const code = Number(doc.docStatusCode || 0);
  if (code === 2) return { color: "success", text: "分析成功" };
  if (code === 10) return { color: "error", text: "分析失败" };
  if ([1, 3, 4, 5].includes(code)) {
    return { color: "processing", text: doc.docStatusDesc || "处理中" };
  }
  return {
    color: "default",
    text: doc.docStatusDesc || doc.docStatus || "未知",
  };
}

function isKnowledgeComponent(component: AiManualComponent): boolean {
  return String(component.type || "").toLowerCase() === "knowledge";
}

function getPublishedWorkflowId(workflow: PublishedWorkflow): number {
  return Number(workflow.targetId || workflow.id);
}

export default function KnowledgePage() {
  const [currentUserId, setCurrentUserId] = useState<number | null>(null);
  const [spaces, setSpaces] = useState<SpaceInfo[]>([]);
  const [selectedSpaceId, setSelectedSpaceId] = useState<number | null>(null);
  const [knowledges, setKnowledges] = useState<KnowledgeComponent[]>([]);
  const [loadingKnowledges, setLoadingKnowledges] = useState(false);
  const [knowledgeKeyword, setKnowledgeKeyword] = useState("");
  const [knowledgeError, setKnowledgeError] = useState<string | null>(null);

  const [selectedKnowledgeId, setSelectedKnowledgeId] = useState<number | null>(
    null,
  );
  const [knowledgeInfo, setKnowledgeInfo] = useState<KnowledgeInfo | null>(
    null,
  );
  const [loadingDetail, setLoadingDetail] = useState(false);
  const [activeTab, setActiveTab] = useState<DetailTabKey>("documents");

  const [documents, setDocuments] = useState<KnowledgeDocumentInfo[]>([]);
  const [documentTotal, setDocumentTotal] = useState(0);
  const [documentKeyword, setDocumentKeyword] = useState("");
  const [loadingDocuments, setLoadingDocuments] = useState(false);
  const [selectedDocument, setSelectedDocument] =
    useState<KnowledgeDocumentInfo | null>(null);
  const [uploadingDocs, setUploadingDocs] = useState(false);

  const [segments, setSegments] = useState<KnowledgeRawSegmentInfo[]>([]);
  const [segmentTotal, setSegmentTotal] = useState(0);
  const [loadingSegments, setLoadingSegments] = useState(false);
  const [segmentModalOpen, setSegmentModalOpen] = useState(false);
  const [editingSegment, setEditingSegment] =
    useState<KnowledgeRawSegmentInfo | null>(null);

  const [qaList, setQaList] = useState<KnowledgeQaInfo[]>([]);
  const [qaTotal, setQaTotal] = useState(0);
  const [qaKeyword, setQaKeyword] = useState("");
  const [loadingQa, setLoadingQa] = useState(false);
  const [qaModalOpen, setQaModalOpen] = useState(false);
  const [editingQa, setEditingQa] = useState<KnowledgeQaInfo | null>(null);

  const [models, setModels] = useState<KnowledgeModelOption[]>([]);
  const [loadingModels, setLoadingModels] = useState(false);
  const [parsingWorkflows, setParsingWorkflows] = useState<PublishedWorkflow[]>(
    [],
  );
  const [loadingParsingWorkflows, setLoadingParsingWorkflows] = useState(false);
  const [iconUrl, setIconUrl] = useState("");
  const [uploadingIcon, setUploadingIcon] = useState(false);
  const [knowledgeModalOpen, setKnowledgeModalOpen] = useState(false);
  const [editingKnowledge, setEditingKnowledge] =
    useState<KnowledgeInfo | null>(null);
  const [savingKnowledge, setSavingKnowledge] = useState(false);

  const [customDocModalOpen, setCustomDocModalOpen] = useState(false);
  const [savingCustomDoc, setSavingCustomDoc] = useState(false);
  const [renameDocModalOpen, setRenameDocModalOpen] = useState(false);
  const [renamingDoc, setRenamingDoc] = useState<KnowledgeDocumentInfo | null>(
    null,
  );
  const [savingRename, setSavingRename] = useState(false);

  const [agentContext, setAgentContext] = useState<AiAgentContext | null>(null);
  const [joinedKnowledgeMap, setJoinedKnowledgeMap] = useState<
    Map<number, AiManualComponent>
  >(new Map());
  const [joiningIds, setJoiningIds] = useState<Set<number>>(() => new Set());

  const [knowledgeForm] = Form.useForm<KnowledgeFormValues>();
  const [customDocForm] = Form.useForm<CustomDocumentValues>();
  const [renameDocForm] = Form.useForm<RenameDocumentValues>();
  const [segmentForm] = Form.useForm<SegmentFormValues>();
  const [qaForm] = Form.useForm<QaFormValues>();
  const dataParsingMethod =
    Form.useWatch("dataParsingMethod", knowledgeForm) || "default";

  const iconFileInputRef = useRef<HTMLInputElement | null>(null);
  const documentFileInputRef = useRef<HTMLInputElement | null>(null);
  const qaFileInputRef = useRef<HTMLInputElement | null>(null);

  const filteredKnowledges = useMemo(() => {
    const keyword = knowledgeKeyword.trim().toLowerCase();
    if (!keyword) return knowledges;
    return knowledges.filter((item) =>
      [item.name, item.description]
        .filter(Boolean)
        .some((value) => String(value).toLowerCase().includes(keyword)),
    );
  }, [knowledgeKeyword, knowledges]);

  const selectedKnowledgeComponent = useMemo(
    () =>
      selectedKnowledgeId
        ? knowledges.find(
            (item) => getKnowledgeId(item) === selectedKnowledgeId,
          ) || null
        : null,
    [knowledges, selectedKnowledgeId],
  );

  const isKnowledgeOwner = useCallback(
    (knowledge?: KnowledgeComponent | KnowledgeInfo | null) => {
      if (!knowledge) return false;
      const creator = (knowledge as KnowledgeComponent).creator;
      const creatorId = Number(knowledge.creatorId || creator?.id || 0);
      return Boolean(currentUserId && creatorId && currentUserId === creatorId);
    },
    [currentUserId],
  );

  const canManageSelectedKnowledge = isKnowledgeOwner(
    knowledgeInfo || selectedKnowledgeComponent,
  );

  const ensureCanManageSelectedKnowledge = useCallback(() => {
    if (canManageSelectedKnowledge) return true;
    message.warning("该知识库由其他用户创建，仅支持查看和加入对话");
    return false;
  }, [canManageSelectedKnowledge]);

  const loadAgentComponents = useCallback(async () => {
    try {
      const context = await resolveAiAgentContext();
      setAgentContext(context);
      const components = await fetchAiAgentComponents(context.agentId);
      const map = new Map<number, AiManualComponent>();
      components.filter(isKnowledgeComponent).forEach((component) => {
        const targetId = Number(component.targetId || 0);
        if (targetId) map.set(targetId, component);
      });
      setJoinedKnowledgeMap(map);
    } catch (error) {
      console.warn("[KnowledgePage] Failed to load agent components:", error);
      setAgentContext(null);
      setJoinedKnowledgeMap(new Map());
    }
  }, []);

  const loadSpaces = useCallback(async (): Promise<SpaceInfo[]> => {
    try {
      const result = await fetchSpaces();
      const nextSpaces = result || [];
      setSpaces(nextSpaces);
      setSelectedSpaceId((prev) => prev || nextSpaces[0]?.id || null);
      return nextSpaces;
    } catch (error) {
      console.warn("[KnowledgePage] Failed to load spaces:", error);
      return [];
    }
  }, []);

  const ensureDefaultSpaceId = useCallback(
    async (showError = true): Promise<number | null> => {
      if (selectedSpaceId) return selectedSpaceId;

      const list = spaces.length > 0 ? spaces : await loadSpaces();
      const defaultSpaceId = list[0]?.id || null;
      if (defaultSpaceId) {
        setSelectedSpaceId(defaultSpaceId);
        return defaultSpaceId;
      }

      if (showError) {
        message.error("无法获取默认工作区，暂时不能创建知识库");
      }
      return null;
    },
    [loadSpaces, selectedSpaceId, spaces],
  );

  const loadKnowledges = useCallback(async () => {
    if (!selectedSpaceId) {
      setKnowledges([]);
      return;
    }
    setLoadingKnowledges(true);
    setKnowledgeError(null);
    try {
      const list = await fetchKnowledgeComponents(selectedSpaceId);
      setKnowledges(list);
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : "知识库加载失败";
      setKnowledgeError(errorMessage);
      setKnowledges([]);
    } finally {
      setLoadingKnowledges(false);
    }
  }, [selectedSpaceId]);

  const loadKnowledgeDetail = useCallback(
    async (knowledgeId = selectedKnowledgeId) => {
      if (!knowledgeId) return;
      setLoadingDetail(true);
      try {
        const detail = await fetchKnowledgeDetail(knowledgeId);
        setKnowledgeInfo(detail);
      } catch (error) {
        message.error(
          error instanceof Error ? error.message : "知识库详情加载失败",
        );
      } finally {
        setLoadingDetail(false);
      }
    },
    [selectedKnowledgeId],
  );

  const loadDocuments = useCallback(
    async (keyword = documentKeyword) => {
      if (!selectedKnowledgeId) return;
      setLoadingDocuments(true);
      try {
        const result = await fetchKnowledgeDocuments({
          kbId: selectedKnowledgeId,
          name: keyword.trim() || undefined,
          current: 1,
          pageSize: DOCUMENT_PAGE_SIZE,
        });
        const records = result.records || [];
        setDocuments(records);
        setDocumentTotal(result.total || 0);
        setSelectedDocument((prev) => {
          if (prev && records.some((item) => item.id === prev.id)) return prev;
          return records[0] || null;
        });
      } catch (error) {
        message.error(
          error instanceof Error ? error.message : "文档列表加载失败",
        );
        setDocuments([]);
        setDocumentTotal(0);
        setSelectedDocument(null);
      } finally {
        setLoadingDocuments(false);
      }
    },
    [documentKeyword, selectedKnowledgeId],
  );

  const loadSegments = useCallback(async () => {
    if (!selectedDocument) {
      setSegments([]);
      setSegmentTotal(0);
      return;
    }
    setLoadingSegments(true);
    try {
      const result = await fetchKnowledgeRawSegments({
        docId: selectedDocument.id,
        current: 1,
        pageSize: SEGMENT_PAGE_SIZE,
      });
      setSegments(result.records || []);
      setSegmentTotal(result.total || 0);
    } catch (error) {
      message.error(error instanceof Error ? error.message : "分段加载失败");
      setSegments([]);
      setSegmentTotal(0);
    } finally {
      setLoadingSegments(false);
    }
  }, [selectedDocument]);

  const loadQaList = useCallback(
    async (keyword = qaKeyword) => {
      if (!selectedKnowledgeId) return;
      setLoadingQa(true);
      try {
        const result = await fetchKnowledgeQaList({
          kbId: selectedKnowledgeId,
          spaceId: selectedSpaceId || undefined,
          question: keyword.trim() || undefined,
          current: 1,
          pageSize: QA_PAGE_SIZE,
        });
        setQaList(result.records || []);
        setQaTotal(result.total || 0);
      } catch (error) {
        message.error(
          error instanceof Error ? error.message : "QA 列表加载失败",
        );
        setQaList([]);
        setQaTotal(0);
      } finally {
        setLoadingQa(false);
      }
    },
    [qaKeyword, selectedKnowledgeId, selectedSpaceId],
  );

  const loadEmbeddingModels = useCallback(async (spaceId?: number) => {
    setLoadingModels(true);
    try {
      const result = await fetchEmbeddingModels(spaceId);
      setModels(result || []);
    } catch (error) {
      message.error(
        error instanceof Error ? error.message : "嵌入模型加载失败",
      );
      setModels([]);
    } finally {
      setLoadingModels(false);
    }
  }, []);

  const loadParsingWorkflows = useCallback(async (spaceId?: number) => {
    setLoadingParsingWorkflows(true);
    try {
      const result = await fetchPublishedWorkflows({
        page: 1,
        pageSize: 80,
        category: "all",
        spaceId,
      });
      setParsingWorkflows(result.records || []);
    } catch (error) {
      message.error(
        error instanceof Error ? error.message : "解析工作流加载失败",
      );
      setParsingWorkflows([]);
    } finally {
      setLoadingParsingWorkflows(false);
    }
  }, []);

  useEffect(() => {
    loadSpaces();
    loadAgentComponents();
    void getCurrentAuth().then((auth) => {
      setCurrentUserId(auth.userInfo?.userId || null);
    });
  }, [loadAgentComponents, loadSpaces]);

  useEffect(() => {
    loadKnowledges();
  }, [loadKnowledges]);

  useEffect(() => {
    if (!selectedKnowledgeId) return;
    loadKnowledgeDetail(selectedKnowledgeId);
    loadDocuments("");
  }, [loadDocuments, loadKnowledgeDetail, selectedKnowledgeId]);

  useEffect(() => {
    if (activeTab === "segments") loadSegments();
  }, [activeTab, loadSegments]);

  useEffect(() => {
    if (activeTab === "qa") loadQaList();
  }, [activeTab, loadQaList]);

  useEffect(() => {
    if (!knowledgeModalOpen || dataParsingMethod !== "workflow") return;
    if (loadingParsingWorkflows || parsingWorkflows.length > 0) return;

    void (async () => {
      const spaceId = selectedSpaceId || (await ensureDefaultSpaceId(false));
      await loadParsingWorkflows(spaceId || undefined);
    })();
  }, [
    dataParsingMethod,
    ensureDefaultSpaceId,
    knowledgeModalOpen,
    loadParsingWorkflows,
    loadingParsingWorkflows,
    parsingWorkflows.length,
    selectedSpaceId,
  ]);

  const openKnowledgeForm = async (
    knowledge?: KnowledgeComponent | KnowledgeInfo,
  ) => {
    if (knowledge && !isKnowledgeOwner(knowledge)) {
      message.warning("该知识库由其他用户创建，不能编辑");
      return;
    }
    setKnowledgeModalOpen(true);
    void (async () => {
      const spaceId =
        (knowledge as KnowledgeInfo | undefined)?.spaceId ||
        selectedSpaceId ||
        (await ensureDefaultSpaceId(false));
      await loadEmbeddingModels(spaceId || undefined);
    })();
    if (knowledge) {
      try {
        const detail =
          "embeddingModelId" in knowledge && knowledge.embeddingModelId
            ? (knowledge as KnowledgeInfo)
            : await fetchKnowledgeDetail(getKnowledgeId(knowledge));
        setEditingKnowledge(detail);
        setIconUrl(detail.icon || "");
        knowledgeForm.setFieldsValue({
          name: detail.name,
          description: detail.description,
          embeddingModelId: detail.embeddingModelId,
          dataParsingMethod: detail.workflowId ? "workflow" : "default",
          workflowId: detail.workflowId ? Number(detail.workflowId) : undefined,
        });
        if (detail.workflowId) {
          await loadParsingWorkflows(
            detail.spaceId || selectedSpaceId || undefined,
          );
          setParsingWorkflows((prev) => {
            const workflowId = Number(detail.workflowId);
            if (
              prev.some((item) => getPublishedWorkflowId(item) === workflowId)
            ) {
              return prev;
            }
            return [
              {
                id: workflowId,
                targetId: workflowId,
                name: detail.workflowName || `工作流 ${workflowId}`,
                description: detail.workflowDescription,
                icon: detail.workflowIcon,
              } as PublishedWorkflow,
              ...prev,
            ];
          });
        }
      } catch (error) {
        message.error(
          error instanceof Error ? error.message : "知识库详情加载失败",
        );
        setKnowledgeModalOpen(false);
      }
    } else {
      setEditingKnowledge(null);
      setIconUrl("");
      knowledgeForm.resetFields();
      knowledgeForm.setFieldsValue({ dataParsingMethod: "default" });
    }
  };

  const saveKnowledge = async () => {
    if (editingKnowledge && !isKnowledgeOwner(editingKnowledge)) {
      message.warning("该知识库由其他用户创建，不能编辑");
      return;
    }
    let values: KnowledgeFormValues;
    try {
      values = await knowledgeForm.validateFields();
    } catch {
      return;
    }

    if (values.dataParsingMethod === "workflow" && !values.workflowId) {
      message.error("请选择解析工作流");
      return;
    }

    const spaceId =
      editingKnowledge?.spaceId ||
      selectedSpaceId ||
      (await ensureDefaultSpaceId());
    if (!spaceId) return;
    setSavingKnowledge(true);
    try {
      const params: KnowledgeConfigSaveParams = {
        id: editingKnowledge?.id,
        spaceId,
        name: values.name,
        description: values.description || "",
        embeddingModelId: values.embeddingModelId,
        icon: iconUrl || "",
        dataType: 1,
        workflowId:
          values.dataParsingMethod === "workflow" && values.workflowId
            ? values.workflowId
            : null,
      };
      if (editingKnowledge?.id) {
        await updateKnowledgeConfig(params);
        message.success("知识库已更新");
        await loadKnowledgeDetail(editingKnowledge.id);
      } else {
        const id = await createKnowledgeConfig(params);
        message.success("知识库已创建");
        setSelectedKnowledgeId(Number(id));
        setActiveTab("documents");
      }
      setKnowledgeModalOpen(false);
      await loadKnowledges();
    } catch (error) {
      if (error instanceof Error) message.error(error.message);
    } finally {
      setSavingKnowledge(false);
    }
  };

  const confirmDeleteKnowledge = (knowledge: KnowledgeComponent) => {
    if (!isKnowledgeOwner(knowledge)) {
      message.warning("该知识库由其他用户创建，不能删除");
      return;
    }
    const knowledgeId = getKnowledgeId(knowledge);
    Modal.confirm({
      title: "删除知识库",
      content: `确认删除「${knowledge.name}」吗？该操作不可恢复。`,
      okText: "删除",
      okButtonProps: { danger: true },
      cancelText: "取消",
      onOk: async () => {
        await deleteKnowledgeConfig(knowledgeId);
        message.success("知识库已删除");
        if (selectedKnowledgeId === knowledgeId) {
          setSelectedKnowledgeId(null);
          setKnowledgeInfo(null);
        }
        await loadKnowledges();
      },
    });
  };

  const joinKnowledgeToChat = async (
    knowledge: KnowledgeComponent | KnowledgeInfo,
  ) => {
    const knowledgeId = getKnowledgeId(knowledge);
    const joinedComponent = joinedKnowledgeMap.get(knowledgeId);
    if (joinedComponent && isAiKnowledgeChatSelectable(joinedComponent)) {
      message.info("该知识库已加入对话");
      return;
    }

    const context = agentContext || (await resolveAiAgentContext());
    setAgentContext(context);
    setJoiningIds((prev) => new Set(prev).add(knowledgeId));
    try {
      let componentId = joinedComponent?.id;
      if (!componentId) {
        componentId = await addAiAgentKnowledgeComponent({
          agentId: context.agentId,
          knowledgeId,
        });
      }
      const resolvedComponentId = componentId;
      const components = await fetchAiAgentComponents(context.agentId);
      const component =
        components.find((item) => item.id === resolvedComponentId) ||
        components.find(
          (item) =>
            String(item.type || "").toLowerCase() === "knowledge" &&
            Number(item.targetId || 0) === knowledgeId,
        ) ||
        ({
          id: resolvedComponentId,
          type: "Knowledge",
          targetId: knowledgeId,
          name: knowledge.name || "知识库",
          icon: knowledge.icon,
          description: knowledge.description,
        } as AiManualComponent);
      const enabledComponent = await enableAiAgentKnowledgeForChat(component);
      setJoinedKnowledgeMap((prev) => {
        const next = new Map(prev);
        next.set(knowledgeId, enabledComponent);
        return next;
      });
      message.success("知识库已加入 AI 对话");
      await loadAgentComponents();
    } catch (error) {
      message.error(error instanceof Error ? error.message : "加入对话失败");
    } finally {
      setJoiningIds((prev) => {
        const next = new Set(prev);
        next.delete(knowledgeId);
        return next;
      });
    }
  };

  const openKnowledgeDetail = (knowledge: KnowledgeComponent) => {
    setSelectedKnowledgeId(getKnowledgeId(knowledge));
    setKnowledgeInfo(null);
    setSelectedDocument(null);
    setDocuments([]);
    setSegments([]);
    setQaList([]);
    setDocumentKeyword("");
    setQaKeyword("");
    setActiveTab("documents");
  };

  const handleIconFile = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    event.target.value = "";
    if (!file) return;

    const isValidImage =
      file.type === "image/jpeg" ||
      file.type === "image/jpg" ||
      file.type === "image/png";
    if (!isValidImage) {
      message.error("图标仅支持 JPG、JPEG、PNG 格式");
      return;
    }
    if (file.size > KNOWLEDGE_ICON_MAX_SIZE) {
      message.error("图标不能超过 2MB");
      return;
    }

    setUploadingIcon(true);
    try {
      const url = await uploadKnowledgeAsset(file);
      setIconUrl(url);
      message.success("图标已上传");
    } catch (error) {
      message.error(error instanceof Error ? error.message : "图标上传失败");
    } finally {
      setUploadingIcon(false);
    }
  };

  const handleDocumentFiles = async (
    event: React.ChangeEvent<HTMLInputElement>,
  ) => {
    const files = Array.from(event.target.files || []);
    event.target.value = "";
    if (!files.length || !selectedKnowledgeId) return;
    if (!ensureCanManageSelectedKnowledge()) return;

    const validationError = files.map(validateKnowledgeFile).find(Boolean);
    if (validationError) {
      message.error(validationError);
      return;
    }

    setUploadingDocs(true);
    try {
      const uploaded = await Promise.all(files.map(uploadKnowledgeFile));
      await addKnowledgeDocuments({
        kbId: selectedKnowledgeId,
        files: uploaded,
      });
      message.success("文档已添加，后台将继续分析处理");
      await loadDocuments();
    } catch (error) {
      message.error(error instanceof Error ? error.message : "文档上传失败");
    } finally {
      setUploadingDocs(false);
    }
  };

  const saveCustomDocument = async () => {
    if (!selectedKnowledgeId) return;
    if (!ensureCanManageSelectedKnowledge()) return;
    const values = await customDocForm.validateFields();
    setSavingCustomDoc(true);
    try {
      await addCustomKnowledgeDocument({
        kbId: selectedKnowledgeId,
        name: values.name,
        fileContent: values.fileContent,
      });
      message.success("自定义文本已添加");
      setCustomDocModalOpen(false);
      customDocForm.resetFields();
      await loadDocuments();
    } catch (error) {
      message.error(error instanceof Error ? error.message : "添加文本失败");
    } finally {
      setSavingCustomDoc(false);
    }
  };

  const openRenameDocument = (doc: KnowledgeDocumentInfo) => {
    if (!ensureCanManageSelectedKnowledge()) return;
    setRenamingDoc(doc);
    renameDocForm.setFieldsValue({ name: doc.name });
    setRenameDocModalOpen(true);
  };

  const saveDocumentName = async () => {
    if (!renamingDoc) return;
    if (!ensureCanManageSelectedKnowledge()) return;
    const values = await renameDocForm.validateFields();
    setSavingRename(true);
    try {
      await updateKnowledgeDocumentName({
        docId: renamingDoc.id,
        name: values.name,
      });
      message.success("文档名称已更新");
      setRenameDocModalOpen(false);
      await loadDocuments();
    } catch (error) {
      message.error(error instanceof Error ? error.message : "文档重命名失败");
    } finally {
      setSavingRename(false);
    }
  };

  const refreshDocumentStatus = async () => {
    if (documents.length === 0) return;
    try {
      const statusList = await queryKnowledgeDocumentStatus(
        documents.map((doc) => doc.id),
      );
      const statusMap = new Map(statusList.map((item) => [item.id, item]));
      setDocuments((prev) =>
        prev.map((doc) => ({
          ...doc,
          ...(statusMap.get(doc.id) || {}),
        })),
      );
      message.success("文档状态已刷新");
    } catch {
      await loadDocuments();
    }
  };

  const confirmDeleteDocument = (doc: KnowledgeDocumentInfo) => {
    if (!ensureCanManageSelectedKnowledge()) return;
    Modal.confirm({
      title: "删除文档",
      content: `确认删除「${doc.name}」吗？`,
      okText: "删除",
      okButtonProps: { danger: true },
      cancelText: "取消",
      onOk: async () => {
        await deleteKnowledgeDocument(doc.id);
        message.success("文档已删除");
        await loadDocuments();
      },
    });
  };

  const runDocumentAction = async (
    doc: KnowledgeDocumentInfo,
    action: "qa" | "embedding" | "retry",
  ) => {
    if (!ensureCanManageSelectedKnowledge()) return;
    try {
      if (action === "qa") {
        await generateKnowledgeDocumentQa(doc.id);
        message.success("已提交生成 QA 任务");
      } else if (action === "embedding") {
        await generateKnowledgeDocumentEmbeddings(doc.id);
        message.success("已提交向量化任务");
      } else {
        await retryKnowledgeDocumentTask(doc.id);
        message.success("已提交重试任务");
      }
      await loadDocuments();
    } catch (error) {
      message.error(error instanceof Error ? error.message : "操作失败");
    }
  };

  const openSegmentModal = (segment?: KnowledgeRawSegmentInfo) => {
    if (!ensureCanManageSelectedKnowledge()) return;
    setEditingSegment(segment || null);
    segmentForm.setFieldsValue({
      rawTxt: segment?.rawTxt || "",
      sortIndex: segment?.sortIndex || segments.length,
    });
    setSegmentModalOpen(true);
  };

  const saveSegment = async () => {
    if (!ensureCanManageSelectedKnowledge()) return;
    const spaceId =
      selectedDocument?.spaceId || knowledgeInfo?.spaceId || selectedSpaceId;
    if (!selectedDocument || !spaceId) return;
    const values = await segmentForm.validateFields();
    try {
      if (editingSegment) {
        await updateKnowledgeRawSegment({
          spaceId,
          rawSegmentId: editingSegment.id,
          docId: selectedDocument.id,
          rawTxt: values.rawTxt,
          sortIndex: values.sortIndex,
        });
        message.success("分段已更新");
      } else {
        await addKnowledgeRawSegment({
          spaceId,
          docId: selectedDocument.id,
          rawTxt: values.rawTxt,
          sortIndex: values.sortIndex,
        });
        message.success("分段已新增");
      }
      setSegmentModalOpen(false);
      await loadSegments();
    } catch (error) {
      message.error(error instanceof Error ? error.message : "保存分段失败");
    }
  };

  const confirmDeleteSegment = (segment: KnowledgeRawSegmentInfo) => {
    if (!ensureCanManageSelectedKnowledge()) return;
    Modal.confirm({
      title: "删除分段",
      content: "确认删除该分段吗？",
      okText: "删除",
      okButtonProps: { danger: true },
      cancelText: "取消",
      onOk: async () => {
        await deleteKnowledgeRawSegment(segment.id);
        message.success("分段已删除");
        await loadSegments();
      },
    });
  };

  const openQaModal = (qa?: KnowledgeQaInfo) => {
    if (!ensureCanManageSelectedKnowledge()) return;
    setEditingQa(qa || null);
    qaForm.setFieldsValue({
      question: qa?.question || "",
      answer: qa?.answer || "",
    });
    setQaModalOpen(true);
  };

  const saveQa = async () => {
    if (!selectedKnowledgeId) return;
    if (!ensureCanManageSelectedKnowledge()) return;
    const values = await qaForm.validateFields();
    try {
      if (editingQa) {
        await updateKnowledgeQa({
          id: editingQa.id,
          question: values.question,
          answer: values.answer,
        });
        message.success("QA 已更新");
      } else {
        await addKnowledgeQa({
          kbId: selectedKnowledgeId,
          spaceId: selectedSpaceId || undefined,
          question: values.question,
          answer: values.answer,
        });
        message.success("QA 已新增");
      }
      setQaModalOpen(false);
      await loadQaList();
    } catch (error) {
      message.error(error instanceof Error ? error.message : "保存 QA 失败");
    }
  };

  const confirmDeleteQa = (qa: KnowledgeQaInfo) => {
    if (!ensureCanManageSelectedKnowledge()) return;
    Modal.confirm({
      title: "删除 QA",
      content: "确认删除该问答吗？",
      okText: "删除",
      okButtonProps: { danger: true },
      cancelText: "取消",
      onOk: async () => {
        await deleteKnowledgeQa(qa.id);
        message.success("QA 已删除");
        await loadQaList();
      },
    });
  };

  const handleQaImport = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    event.target.value = "";
    if (!file || !selectedKnowledgeId) return;
    if (!ensureCanManageSelectedKnowledge()) return;
    try {
      await importKnowledgeQaExcel({ kbId: selectedKnowledgeId, file });
      message.success("QA 已导入");
      await loadQaList();
    } catch (error) {
      message.error(error instanceof Error ? error.message : "QA 导入失败");
    }
  };

  const handleDownloadQaTemplate = async () => {
    try {
      const blob = await downloadKnowledgeQaTemplate();
      const url = URL.createObjectURL(blob);
      const anchor = document.createElement("a");
      anchor.href = url;
      anchor.download = "知识库QA导入模板.xlsx";
      anchor.click();
      URL.revokeObjectURL(url);
    } catch (error) {
      message.error(error instanceof Error ? error.message : "模板下载失败");
    }
  };

  const documentColumns: ColumnsType<KnowledgeDocumentInfo> = [
    {
      title: "文档",
      dataIndex: "name",
      ellipsis: true,
      render: (name: string, record) => (
        <button
          type="button"
          className={styles.linkButton}
          onClick={() => {
            setSelectedDocument(record);
            setActiveTab("segments");
          }}
        >
          <FileTextOutlined />
          <span>{name}</span>
        </button>
      ),
    },
    {
      title: "状态",
      width: 120,
      render: (_, record) => {
        const status = getDocumentStatus(record);
        return <Tag color={status.color}>{status.text}</Tag>;
      },
    },
    {
      title: "QA",
      width: 82,
      render: (_, record) => (record.hasQa ? "已生成" : "未生成"),
    },
    {
      title: "向量",
      width: 82,
      render: (_, record) => (record.hasEmbedding ? "已完成" : "未完成"),
    },
    {
      title: "更新时间",
      width: 170,
      render: (_, record) => formatDateTime(record.modified || record.created),
    },
    {
      title: "操作",
      width: canManageSelectedKnowledge ? 260 : 120,
      fixed: "right",
      render: (_, record) => (
        <div className={styles.tableActions}>
          <Button
            type="link"
            size="small"
            onClick={() => {
              setSelectedDocument(record);
              setActiveTab("segments");
            }}
          >
            分段
          </Button>
          {canManageSelectedKnowledge && (
            <>
              <Button
                type="link"
                size="small"
                onClick={() => runDocumentAction(record, "qa")}
              >
                生成 QA
              </Button>
              <Button
                type="link"
                size="small"
                onClick={() => runDocumentAction(record, "embedding")}
              >
                向量化
              </Button>
              <Button
                type="link"
                size="small"
                onClick={() => runDocumentAction(record, "retry")}
              >
                重试
              </Button>
              <Button
                type="link"
                size="small"
                onClick={() => openRenameDocument(record)}
              >
                重命名
              </Button>
            </>
          )}
          {record.docUrl && (
            <Button
              type="link"
              size="small"
              onClick={() => window.open(record.docUrl, "_blank")}
            >
              打开
            </Button>
          )}
          {canManageSelectedKnowledge && (
            <Button
              type="link"
              size="small"
              danger
              onClick={() => confirmDeleteDocument(record)}
            >
              删除
            </Button>
          )}
        </div>
      ),
    },
  ];

  const segmentColumns: ColumnsType<KnowledgeRawSegmentInfo> = [
    {
      title: "序号",
      dataIndex: "sortIndex",
      width: 90,
      render: (value, _, index) => value ?? index + 1,
    },
    {
      title: "分段内容",
      dataIndex: "rawTxt",
      render: (value: string) => <p className={styles.segmentText}>{value}</p>,
    },
    {
      title: "更新时间",
      width: 170,
      render: (_, record) => formatDateTime(record.modified || record.created),
    },
    ...(canManageSelectedKnowledge
      ? [
          {
            title: "操作",
            width: 120,
            render: (_: unknown, record: KnowledgeRawSegmentInfo) => (
              <div className={styles.tableActions}>
                <Button
                  type="link"
                  size="small"
                  onClick={() => openSegmentModal(record)}
                >
                  编辑
                </Button>
                <Button
                  type="link"
                  size="small"
                  danger
                  onClick={() => confirmDeleteSegment(record)}
                >
                  删除
                </Button>
              </div>
            ),
          },
        ]
      : []),
  ];

  const qaColumns: ColumnsType<KnowledgeQaInfo> = [
    {
      title: "问题",
      dataIndex: "question",
      width: "34%",
      render: (value: string) => <p className={styles.qaText}>{value}</p>,
    },
    {
      title: "答案",
      dataIndex: "answer",
      render: (value: string) => <p className={styles.qaText}>{value}</p>,
    },
    {
      title: "更新时间",
      width: 170,
      render: (_, record) => formatDateTime(record.modified || record.created),
    },
    ...(canManageSelectedKnowledge
      ? [
          {
            title: "操作",
            width: 120,
            render: (_: unknown, record: KnowledgeQaInfo) => (
              <div className={styles.tableActions}>
                <Button
                  type="link"
                  size="small"
                  onClick={() => openQaModal(record)}
                >
                  编辑
                </Button>
                <Button
                  type="link"
                  size="small"
                  danger
                  onClick={() => confirmDeleteQa(record)}
                >
                  删除
                </Button>
              </div>
            ),
          },
        ]
      : []),
  ];

  const renderKnowledgeIcon = (
    knowledge: KnowledgeComponent | KnowledgeInfo | null,
  ) => (
    <ImageWithFallback
      className={styles.knowledgeIconImage}
      src={knowledge?.icon}
      alt=""
      fallback={
        <span className={styles.knowledgeIconText}>
          {getInitial(knowledge?.name)}
        </span>
      }
    />
  );

  const renderCreateButton = (variant: "header" | "toolbar" | "empty") => (
    <Button
      type="primary"
      icon={<PlusOutlined />}
      className={variant === "toolbar" ? styles.toolbarCreateButton : undefined}
      onClick={() => openKnowledgeForm()}
    >
      新建知识库
    </Button>
  );

  const renderList = () => (
    <>
      <header className={styles.header}>
        <div>
          <div className={styles.breadcrumb}>
            工作台 <span>/</span> <strong>知识库</strong>
          </div>
          <div className={styles.titleRow}>
            <h1>知识库</h1>
            <p>管理文档、分段和 QA，让 AI 对话可检索企业知识。</p>
          </div>
        </div>
        {renderCreateButton("header")}
      </header>
      <main className={styles.content}>
        <div className={styles.toolbar}>
          <Input
            allowClear
            prefix={<SearchOutlined />}
            placeholder="搜索知识库"
            value={knowledgeKeyword}
            onChange={(event) => setKnowledgeKeyword(event.target.value)}
            className={styles.search}
          />
          {renderCreateButton("toolbar")}
          <div className={styles.count}>
            <span>{filteredKnowledges.length}</span> 个知识库
          </div>
        </div>
        <div className={styles.listArea}>
          {loadingKnowledges ? (
            <div className={styles.centerState}>
              <Spin />
              <span>知识库加载中...</span>
            </div>
          ) : knowledgeError ? (
            <div className={styles.centerState}>
              <Empty
                image={Empty.PRESENTED_IMAGE_SIMPLE}
                description={knowledgeError}
              />
              <Button icon={<ReloadOutlined />} onClick={loadKnowledges}>
                重新加载
              </Button>
            </div>
          ) : filteredKnowledges.length === 0 ? (
            <div className={styles.centerState}>
              <Empty
                image={Empty.PRESENTED_IMAGE_SIMPLE}
                description="暂无知识库"
              />
              {renderCreateButton("empty")}
            </div>
          ) : (
            <div className={styles.grid}>
              {filteredKnowledges.map((knowledge) => {
                const knowledgeId = getKnowledgeId(knowledge);
                const owned = isKnowledgeOwner(knowledge);
                const creatorName =
                  knowledge.creator?.nickName ||
                  knowledge.creator?.userName ||
                  knowledge.creatorName ||
                  "未知创建人";
                const joinedComponent = joinedKnowledgeMap.get(knowledgeId);
                const joined =
                  !!joinedComponent &&
                  isAiKnowledgeChatSelectable(joinedComponent);
                return (
                  <article
                    key={knowledgeId}
                    className={styles.card}
                    onClick={() => openKnowledgeDetail(knowledge)}
                  >
                    <div className={styles.cardHeader}>
                      <div className={styles.knowledgeIcon}>
                        {renderKnowledgeIcon(knowledge)}
                      </div>
                      <div className={styles.cardTitle}>
                        <h3>{knowledge.name}</h3>
                        <div className={styles.cardOwnerRow}>
                          <Tag
                            color={owned ? "cyan" : "default"}
                            className={styles.ownerTag}
                          >
                            {owned ? "我的知识库" : "只读"}
                          </Tag>
                          {!owned && (
                            <span title={creatorName}>
                              创建人：{creatorName}
                            </span>
                          )}
                        </div>
                      </div>
                    </div>
                    <p className={styles.cardDescription}>
                      {knowledge.description || "暂无描述"}
                    </p>
                    <div className={styles.cardMeta}>
                      <span>
                        容量 {formatBytes(Number(knowledge.fileSize || 0))}
                      </span>
                      <span
                        title={formatDateTime(
                          knowledge.modified || knowledge.created,
                        )}
                      >
                        更新{" "}
                        {formatDateTime(
                          knowledge.modified || knowledge.created,
                        )}
                      </span>
                    </div>
                    <div className={styles.cardActions}>
                      <Button
                        type="primary"
                        size="small"
                        icon={joined ? <CheckOutlined /> : <TeamOutlined />}
                        loading={joiningIds.has(knowledgeId)}
                        onClick={(event) => {
                          event.stopPropagation();
                          joinKnowledgeToChat(knowledge);
                        }}
                      >
                        {joined ? "已加入" : "加入对话"}
                      </Button>
                      {owned && (
                        <div className={styles.cardOwnerActions}>
                          <Tooltip title="编辑知识库">
                            <Button
                              size="small"
                              icon={<EditOutlined />}
                              aria-label="编辑知识库"
                              onClick={(event) => {
                                event.stopPropagation();
                                openKnowledgeForm(knowledge);
                              }}
                            />
                          </Tooltip>
                          <Tooltip title="删除知识库">
                            <Button
                              size="small"
                              danger
                              icon={<DeleteOutlined />}
                              aria-label="删除知识库"
                              onClick={(event) => {
                                event.stopPropagation();
                                confirmDeleteKnowledge(knowledge);
                              }}
                            />
                          </Tooltip>
                        </div>
                      )}
                    </div>
                  </article>
                );
              })}
            </div>
          )}
        </div>
      </main>
    </>
  );

  const renderDocuments = () => (
    <div className={styles.tabPane}>
      <div className={styles.tabToolbar}>
        <Input.Search
          allowClear
          placeholder="搜索文档"
          value={documentKeyword}
          onChange={(event) => {
            const value = event.target.value;
            setDocumentKeyword(value);
            if (!value) void loadDocuments("");
          }}
          onSearch={(value) => loadDocuments(value)}
          className={styles.innerSearch}
        />
        <input
          ref={documentFileInputRef}
          type="file"
          multiple
          className={styles.hiddenInput}
          onChange={handleDocumentFiles}
        />
        {canManageSelectedKnowledge && (
          <>
            <Button
              icon={<CloudUploadOutlined />}
              loading={uploadingDocs}
              onClick={() => documentFileInputRef.current?.click()}
            >
              上传文档
            </Button>
            <Button
              icon={<FileAddOutlined />}
              onClick={() => {
                customDocForm.resetFields();
                setCustomDocModalOpen(true);
              }}
            >
              自定义文本
            </Button>
          </>
        )}
        <Tooltip title="刷新文档状态">
          <Button icon={<ReloadOutlined />} onClick={refreshDocumentStatus} />
        </Tooltip>
      </div>
      <Table
        rowKey="id"
        size="middle"
        loading={loadingDocuments}
        columns={documentColumns}
        dataSource={documents}
        scroll={{ x: 980 }}
        pagination={{
          pageSize: DOCUMENT_PAGE_SIZE,
          total: documentTotal,
          showSizeChanger: false,
        }}
        locale={{
          emptyText: (
            <Empty
              image={Empty.PRESENTED_IMAGE_SIMPLE}
              description="暂无文档"
            />
          ),
        }}
      />
    </div>
  );

  const renderSegments = () => (
    <div className={styles.tabPane}>
      <div className={styles.tabToolbar}>
        <Select
          value={selectedDocument?.id}
          placeholder="选择文档查看分段"
          className={styles.documentSelect}
          onChange={(id) => {
            setSelectedDocument(documents.find((doc) => doc.id === id) || null);
          }}
          options={documents.map((doc) => ({ label: doc.name, value: doc.id }))}
        />
        {canManageSelectedKnowledge && (
          <Button
            icon={<PlusOutlined />}
            disabled={!selectedDocument}
            onClick={() => openSegmentModal()}
          >
            新增分段
          </Button>
        )}
        <Button
          icon={<ReloadOutlined />}
          disabled={!selectedDocument}
          onClick={loadSegments}
        >
          刷新
        </Button>
        <span className={styles.mutedText}>共 {segmentTotal} 个分段</span>
      </div>
      {!selectedDocument ? (
        <div className={styles.centerState}>
          <Empty
            image={Empty.PRESENTED_IMAGE_SIMPLE}
            description="请先选择文档"
          />
        </div>
      ) : (
        <Table
          rowKey="id"
          size="middle"
          loading={loadingSegments}
          columns={segmentColumns}
          dataSource={segments}
          pagination={{
            pageSize: SEGMENT_PAGE_SIZE,
            total: segmentTotal,
            showSizeChanger: false,
          }}
          locale={{
            emptyText: (
              <Empty
                image={Empty.PRESENTED_IMAGE_SIMPLE}
                description="暂无分段"
              />
            ),
          }}
        />
      )}
    </div>
  );

  const renderQa = () => (
    <div className={styles.tabPane}>
      <div className={styles.tabToolbar}>
        <Input.Search
          allowClear
          placeholder="搜索问题"
          value={qaKeyword}
          onChange={(event) => {
            const value = event.target.value;
            setQaKeyword(value);
            if (!value) void loadQaList("");
          }}
          onSearch={(value) => loadQaList(value)}
          className={styles.innerSearch}
        />
        {canManageSelectedKnowledge && (
          <Button icon={<PlusOutlined />} onClick={() => openQaModal()}>
            新增 QA
          </Button>
        )}
        <input
          ref={qaFileInputRef}
          type="file"
          accept=".xls,.xlsx"
          className={styles.hiddenInput}
          onChange={handleQaImport}
        />
        {canManageSelectedKnowledge && (
          <Button
            icon={<CloudUploadOutlined />}
            onClick={() => qaFileInputRef.current?.click()}
          >
            导入 Excel
          </Button>
        )}
        <Button icon={<DownloadOutlined />} onClick={handleDownloadQaTemplate}>
          下载模板
        </Button>
        <Button icon={<ReloadOutlined />} onClick={() => loadQaList()}>
          刷新
        </Button>
        <span className={styles.mutedText}>共 {qaTotal} 条 QA</span>
      </div>
      <Table
        rowKey="id"
        size="middle"
        loading={loadingQa}
        columns={qaColumns}
        dataSource={qaList}
        scroll={{ x: 900 }}
        pagination={{
          pageSize: QA_PAGE_SIZE,
          total: qaTotal,
          showSizeChanger: false,
        }}
        locale={{
          emptyText: (
            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无 QA" />
          ),
        }}
      />
    </div>
  );

  const renderGraphPlaceholder = () => (
    <div className={styles.graphPlaceholder}>
      <DatabaseOutlined />
      <h3>知识图谱后续接入</h3>
      <p>第一版先完成知识库核心管理。知识图谱和命中测试将在后续阶段迁移。</p>
    </div>
  );

  const renderDetail = () => {
    const joined =
      selectedKnowledgeId !== null &&
      !!joinedKnowledgeMap.get(selectedKnowledgeId) &&
      isAiKnowledgeChatSelectable(joinedKnowledgeMap.get(selectedKnowledgeId)!);
    const joining =
      selectedKnowledgeId !== null && joiningIds.has(selectedKnowledgeId);
    const knowledgeForAction = knowledgeInfo || selectedKnowledgeComponent;
    const owned = isKnowledgeOwner(knowledgeForAction);
    const creator = (knowledgeForAction as KnowledgeComponent | null)?.creator;
    const creatorName =
      creator?.nickName ||
      creator?.userName ||
      knowledgeForAction?.creatorName ||
      "未知创建人";

    return (
      <>
        <header className={styles.detailHeader}>
          <Button
            type="text"
            icon={<ArrowLeftOutlined />}
            onClick={() => setSelectedKnowledgeId(null)}
          >
            返回
          </Button>
          <div className={styles.detailTitleBlock}>
            <div className={styles.detailIcon}>
              {renderKnowledgeIcon(knowledgeForAction)}
            </div>
            <div>
              <div className={styles.breadcrumb}>
                知识库 <span>/</span>{" "}
                <strong>{knowledgeForAction?.name || "知识库详情"}</strong>
              </div>
              <h1>{knowledgeForAction?.name || "知识库详情"}</h1>
              <div className={styles.detailOwnerRow}>
                <Tag color={owned ? "cyan" : "default"}>
                  {owned ? "我的知识库" : "只读知识库"}
                </Tag>
                {!owned && <span>创建人：{creatorName}</span>}
              </div>
              <p>{knowledgeForAction?.description || "暂无描述"}</p>
            </div>
          </div>
          <div className={styles.detailActions}>
            <Button
              icon={joined ? <CheckOutlined /> : <TeamOutlined />}
              loading={joining}
              disabled={!knowledgeForAction}
              onClick={() =>
                knowledgeForAction && joinKnowledgeToChat(knowledgeForAction)
              }
            >
              {joined ? "已加入对话" : "加入对话"}
            </Button>
            {owned && (
              <Button
                icon={<EditOutlined />}
                disabled={!knowledgeForAction}
                onClick={() =>
                  knowledgeForAction && openKnowledgeForm(knowledgeForAction)
                }
              >
                编辑
              </Button>
            )}
          </div>
        </header>
        <main className={styles.detailContent}>
          {loadingDetail && !knowledgeInfo ? (
            <div className={styles.centerState}>
              <Spin />
              <span>详情加载中...</span>
            </div>
          ) : (
            <>
              <div className={styles.statRow}>
                <div className={styles.statCard}>
                  <span>文档数</span>
                  <strong>{documentTotal}</strong>
                </div>
                <div className={styles.statCard}>
                  <span>容量</span>
                  <strong>
                    {formatBytes(Number(knowledgeInfo?.fileSize || 0))}
                  </strong>
                </div>
                <div className={styles.statCard}>
                  <span>状态</span>
                  <strong>{knowledgeInfo?.pubStatus || "Published"}</strong>
                </div>
                <div className={styles.statCard}>
                  <span>更新时间</span>
                  <strong>
                    {formatDateTime(
                      knowledgeInfo?.modified || knowledgeInfo?.created,
                    )}
                  </strong>
                </div>
              </div>
              <Tabs
                activeKey={activeTab}
                onChange={(key) => setActiveTab(key as DetailTabKey)}
                items={[
                  {
                    key: "documents",
                    label: "文档",
                    children: renderDocuments(),
                  },
                  {
                    key: "segments",
                    label: "分段",
                    children: renderSegments(),
                  },
                  {
                    key: "qa",
                    label: "QA",
                    children: renderQa(),
                  },
                  {
                    key: "graph",
                    label: "知识图谱",
                    children: renderGraphPlaceholder(),
                  },
                ]}
              />
            </>
          )}
        </main>
      </>
    );
  };

  return (
    <div className={styles.page}>
      {selectedKnowledgeId ? renderDetail() : renderList()}

      <Modal
        open={knowledgeModalOpen}
        title={editingKnowledge ? "编辑知识库" : "新建知识库"}
        okText={editingKnowledge ? "保存" : "创建"}
        cancelText="取消"
        confirmLoading={savingKnowledge}
        onOk={saveKnowledge}
        onCancel={() => setKnowledgeModalOpen(false)}
        destroyOnClose
        width={620}
      >
        <input
          ref={iconFileInputRef}
          type="file"
          accept=".jpg,.jpeg,.png,image/jpeg,image/png"
          className={styles.hiddenInput}
          onChange={handleIconFile}
        />
        <Form
          form={knowledgeForm}
          layout="vertical"
          preserve={false}
          initialValues={{ dataParsingMethod: "default" }}
        >
          <Form.Item
            name="name"
            label="知识库名称"
            rules={[
              { required: true, message: "请输入知识库名称" },
              { max: 100, message: "知识库名称不能超过 100 个字符" },
            ]}
          >
            <Input placeholder="请输入知识库名称" showCount maxLength={100} />
          </Form.Item>
          <Form.Item name="description" label="描述">
            <Input.TextArea
              placeholder="请输入知识库描述"
              showCount
              maxLength={10000}
              autoSize={{ minRows: 3, maxRows: 5 }}
            />
          </Form.Item>
          <Form.Item
            name="embeddingModelId"
            label="嵌入模型"
            rules={[{ required: true, message: "请选择嵌入模型" }]}
            tooltip="用于文档向量化和检索召回，请选择 Embeddings 类型模型"
          >
            <Select
              loading={loadingModels}
              placeholder="请选择嵌入模型"
              allowClear
              showSearch
              optionFilterProp="label"
              notFoundContent={
                loadingModels ? (
                  <Spin size="small" />
                ) : (
                  "暂无向量模型，请先配置 Embeddings 模型"
                )
              }
              options={models.map((model) => ({
                label: model.name || model.model || `模型 ${model.id}`,
                value: model.id,
              }))}
            />
          </Form.Item>
          <Form.Item
            name="dataParsingMethod"
            label="文档解析方式"
            tooltip="系统默认解析适合常规文档；自定义工作流解析适合需要专门抽取、清洗或结构化处理的文档"
          >
            <Select
              placeholder="请选择文档解析方式"
              options={[
                { label: "系统默认", value: "default" },
                { label: "自定义工作流", value: "workflow" },
              ]}
              onChange={(value) => {
                if (value === "default") {
                  knowledgeForm.setFieldValue("workflowId", undefined);
                  return;
                }
                void (async () => {
                  const spaceId =
                    selectedSpaceId || (await ensureDefaultSpaceId(false));
                  await loadParsingWorkflows(spaceId || undefined);
                })();
              }}
            />
          </Form.Item>
          {dataParsingMethod === "workflow" && (
            <Form.Item
              name="workflowId"
              label="解析工作流"
              rules={[{ required: true, message: "请选择解析工作流" }]}
            >
              <Select
                loading={loadingParsingWorkflows}
                placeholder="请选择用于文档解析的工作流"
                allowClear
                showSearch
                optionFilterProp="label"
                notFoundContent={
                  loadingParsingWorkflows ? (
                    <Spin size="small" />
                  ) : (
                    "暂无可用工作流，请先发布工作流"
                  )
                }
                options={parsingWorkflows.map((workflow) => ({
                  label:
                    workflow.name ||
                    `工作流 ${getPublishedWorkflowId(workflow)}`,
                  value: getPublishedWorkflowId(workflow),
                }))}
              />
            </Form.Item>
          )}
          <Form.Item label="图标">
            <div className={styles.iconUploadRow}>
              <button
                type="button"
                className={styles.iconUploadCard}
                disabled={uploadingIcon}
                onClick={() => iconFileInputRef.current?.click()}
              >
                <span className={styles.iconPreview}>
                  <ImageWithFallback
                    src={iconUrl}
                    alt=""
                    fallback={<PictureOutlined />}
                  />
                </span>
                <span className={styles.iconUploadText}>
                  <strong>
                    {uploadingIcon
                      ? "图标上传中..."
                      : iconUrl
                        ? "已上传图标"
                        : "默认知识库图标"}
                  </strong>
                  <span>支持 JPG、PNG，最大 2MB</span>
                </span>
                <UploadOutlined />
              </button>
              <Button
                disabled={!iconUrl || uploadingIcon}
                onClick={() => setIconUrl("")}
              >
                清除
              </Button>
            </div>
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        open={customDocModalOpen}
        title="新增自定义文本"
        okText="添加"
        cancelText="取消"
        confirmLoading={savingCustomDoc}
        onOk={saveCustomDocument}
        onCancel={() => setCustomDocModalOpen(false)}
        destroyOnClose
      >
        <Form form={customDocForm} layout="vertical" preserve={false}>
          <Form.Item
            name="name"
            label="文档名称"
            rules={[{ required: true, message: "请输入文档名称" }]}
          >
            <Input placeholder="请输入文档名称" />
          </Form.Item>
          <Form.Item
            name="fileContent"
            label="文本内容"
            rules={[{ required: true, message: "请输入文本内容" }]}
          >
            <Input.TextArea
              placeholder="请输入文本内容"
              autoSize={{ minRows: 8, maxRows: 14 }}
            />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        open={renameDocModalOpen}
        title="重命名文档"
        okText="保存"
        cancelText="取消"
        confirmLoading={savingRename}
        onOk={saveDocumentName}
        onCancel={() => setRenameDocModalOpen(false)}
        destroyOnClose
      >
        <Form form={renameDocForm} layout="vertical" preserve={false}>
          <Form.Item
            name="name"
            label="文档名称"
            rules={[{ required: true, message: "请输入文档名称" }]}
          >
            <Input placeholder="请输入文档名称" />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        open={segmentModalOpen}
        title={editingSegment ? "编辑分段" : "新增分段"}
        okText="保存"
        cancelText="取消"
        onOk={saveSegment}
        onCancel={() => setSegmentModalOpen(false)}
        destroyOnClose
        width={720}
      >
        <Form form={segmentForm} layout="vertical" preserve={false}>
          <Form.Item name="sortIndex" label="排序">
            <Input type="number" placeholder="排序序号" />
          </Form.Item>
          <Form.Item
            name="rawTxt"
            label="分段内容"
            rules={[{ required: true, message: "请输入分段内容" }]}
          >
            <Input.TextArea
              placeholder="请输入分段内容"
              autoSize={{ minRows: 8, maxRows: 16 }}
            />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        open={qaModalOpen}
        title={editingQa ? "编辑 QA" : "新增 QA"}
        okText="保存"
        cancelText="取消"
        onOk={saveQa}
        onCancel={() => setQaModalOpen(false)}
        destroyOnClose
        width={720}
      >
        <Form form={qaForm} layout="vertical" preserve={false}>
          <Form.Item
            name="question"
            label="问题"
            rules={[{ required: true, message: "请输入问题" }]}
          >
            <Input.TextArea
              placeholder="请输入问题"
              autoSize={{ minRows: 3, maxRows: 6 }}
            />
          </Form.Item>
          <Form.Item
            name="answer"
            label="答案"
            rules={[{ required: true, message: "请输入答案" }]}
          >
            <Input.TextArea
              placeholder="请输入答案"
              autoSize={{ minRows: 6, maxRows: 12 }}
            />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
