import {
  StopOutlined,
  CloudUploadOutlined,
  DeleteOutlined,
  DownloadOutlined,
  EditOutlined,
  FileAddOutlined,
  FolderAddOutlined,
  PlusOutlined,
  ReloadOutlined,
  SearchOutlined,
} from '@ant-design/icons';
import {
  App,
  Badge,
  Button,
  Card,
  Descriptions,
  Drawer,
  Empty,
  Flex,
  Form,
  Input,
  InputNumber,
  List,
  Modal,
  Popconfirm,
  Progress,
  Radio,
  Select,
  Space,
  Splitter,
  Table,
  Tabs,
  Tag,
  Tree,
  Typography,
  Upload,
} from 'antd';
import type { UploadProps } from 'antd';
import type { DataNode } from 'antd/es/tree';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { platformRequest } from '../api/platform';
import type { components } from '../api/schema.generated';

type Bank = components['schemas']['PlatformQuestionBankItem'];
type BankNode = components['schemas']['PlatformQuestionBankNodeItem'];
type Question = components['schemas']['PlatformQuestionItem'];
type QuestionPage = components['schemas']['PlatformQuestionPage'];
type ImportResult = components['schemas']['PlatformQuestionImportResult'];
type UploadSignResult = components['schemas']['AssetUploadSignResult'];
type UploadConfirmResult = components['schemas']['AssetUploadConfirmResult'];
type UploadRequestOption = Parameters<NonNullable<UploadProps['customRequest']>>[0];

const nodeTypes = [
  { value: 0, label: '分类' },
  { value: 1, label: '科目' },
  { value: 2, label: '章节' },
  { value: 3, label: '试卷' },
  { value: 4, label: '院校' },
  { value: 5, label: '专业' },
  { value: 6, label: '考试方向' },
  { value: 7, label: '资源组' },
  { value: 8, label: '自定义' },
];
const questionTypes = [
  ['choice', '单选题'], ['multi_choice', '多选题'], ['true_false', '判断题'], ['short_answer', '简答题'],
  ['fill_blank', '填空题'], ['reading', '阅读理解'], ['case_analysis', '案例分析'], ['programming', '编程题'],
].map(([value, label]) => ({ value, label }));
const statusLabels: Record<string, string> = { '0': '草稿', '1': '已发布', '2': '已归档', draft: '草稿', published: '已发布', archived: '已归档' };

function toTree(nodes: BankNode[]): DataNode[] {
  const children = new Map<string | null, BankNode[]>();
  for (const node of nodes) {
    const key = node.parentId || null;
    children.set(key, [...(children.get(key) || []), node]);
  }
  const build = (parentId: string | null): DataNode[] => (children.get(parentId) || [])
    .sort((a, b) => Number(a.sortOrder) - Number(b.sortOrder))
    .map((node) => ({
      key: node.id,
      title: <Flex justify="space-between" gap={8}><span>{node.name}</span><Badge count={Number(node.questionCount)} showZero color="#b9c4cf" /></Flex>,
      children: build(node.id),
    }));
  return build(null);
}

function parseJson(value: string | undefined, fallback: unknown) {
  if (!value?.trim()) return fallback;
  return JSON.parse(value);
}

function downloadJson(name: string, value: unknown) {
  const url = URL.createObjectURL(new Blob([JSON.stringify(value, null, 2)], { type: 'application/json' }));
  const anchor = document.createElement('a');
  anchor.href = url;
  anchor.download = name;
  anchor.click();
  URL.revokeObjectURL(url);
}

export function QuestionBankPage() {
  const { message, modal } = App.useApp();
  const [banks, setBanks] = useState<Bank[]>([]);
  const [bankKeyword, setBankKeyword] = useState('');
  const [bankStatus, setBankStatus] = useState('active');
  const [bankId, setBankId] = useState('');
  const [nodes, setNodes] = useState<BankNode[]>([]);
  const [nodeId, setNodeId] = useState('');
  const [questions, setQuestions] = useState<Question[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(20);
  const [filters, setFilters] = useState({ keyword: '', type: '', status: '' });
  const [selectedQuestionIds, setSelectedQuestionIds] = useState<React.Key[]>([]);
  const [loading, setLoading] = useState(false);
  const [bankDrawer, setBankDrawer] = useState<Bank | null | undefined>();
  const [nodeDrawer, setNodeDrawer] = useState<BankNode | null | undefined>();
  const [batchNodeOpen, setBatchNodeOpen] = useState(false);
  const [questionDrawer, setQuestionDrawer] = useState<Question | null | undefined>();
  const [importOpen, setImportOpen] = useState(false);
  const [importResult, setImportResult] = useState<ImportResult | null>(null);
  const [bankForm] = Form.useForm();
  const [nodeForm] = Form.useForm();
  const [batchForm] = Form.useForm();
  const [questionForm] = Form.useForm();
  const [importForm] = Form.useForm();

  const bank = banks.find((item) => item.id === bankId);
  const node = nodes.find((item) => item.id === nodeId);

  const loadBanks = useCallback(async (status = bankStatus, keyword = bankKeyword) => {
    setLoading(true);
    try {
      const result = await platformRequest<Bank[]>('GET', '/api/platform-admin/question-banks', { query: { keyword, status } });
      setBanks(result);
      setBankId((current) => result.some((item) => item.id === current) ? current : result[0]?.id || '');
    } catch (error) { message.error(error instanceof Error ? error.message : '题库加载失败'); }
    finally { setLoading(false); }
  }, [bankKeyword, bankStatus, message]);

  const loadNodes = useCallback(async () => {
    if (!bankId) { setNodes([]); setNodeId(''); return; }
    try {
      const result = await platformRequest<BankNode[]>('GET', '/api/platform-admin/question-banks/{bankId}/nodes', { path: { bankId } });
      setNodes(result);
      setNodeId((current) => result.some((item) => item.id === current) ? current : '');
    } catch (error) { message.error(error instanceof Error ? error.message : '目录加载失败'); }
  }, [bankId, message]);

  const loadQuestions = useCallback(async () => {
    if (!bankId) { setQuestions([]); setTotal(0); return; }
    setLoading(true);
    try {
      const result = await platformRequest<QuestionPage>('GET', '/api/platform-admin/question-banks/questions', {
        query: { questionBankId: bankId, contentNodeId: nodeId || undefined, ...filters, page, pageSize },
      });
      setQuestions(result.items);
      setTotal(Number(result.total));
      setSelectedQuestionIds([]);
    } catch (error) { message.error(error instanceof Error ? error.message : '题目加载失败'); }
    finally { setLoading(false); }
  }, [bankId, filters, message, nodeId, page, pageSize]);

  useEffect(() => { void loadBanks(); }, []);
  useEffect(() => { void loadNodes(); setPage(1); }, [bankId]);
  useEffect(() => { void loadQuestions(); }, [loadQuestions]);

  const openBank = (record?: Bank) => {
    setBankDrawer(record || null);
    queueMicrotask(() => bankForm.setFieldsValue({ id: record?.id, name: record?.name, metadata: JSON.stringify(record?.metadata || {}, null, 2) }));
  };
  const saveBank = async () => {
    const values = await bankForm.validateFields();
    try {
      const saved = await platformRequest<Bank>('PUT', '/api/platform-admin/question-banks', { body: { id: values.id || null, name: values.name, metadata: parseJson(values.metadata, {}) } });
      message.success('题库已保存'); setBankDrawer(undefined); await loadBanks(); setBankId(saved.id);
    } catch (error) { message.error(error instanceof Error ? error.message : '题库保存失败'); }
  };

  const openNode = (record?: BankNode) => {
    if (!bankId) return message.warning('请先创建题库');
    setNodeDrawer(record || null);
    queueMicrotask(() => nodeForm.setFieldsValue({
      id: record?.id, name: record?.name, parentId: record?.parentId || null, nodeKey: record?.nodeKey,
      nodeType: record?.nodeType ?? 2, sortOrder: Number(record?.sortOrder || 0), isSelectable: record?.isSelectable ?? true,
      metadata: JSON.stringify(record?.metadata || {}, null, 2),
    }));
  };
  const saveNode = async () => {
    const values = await nodeForm.validateFields();
    try {
      await platformRequest('PUT', '/api/platform-admin/question-banks/nodes', { body: { ...values, questionBankId: bankId, parentId: values.parentId || null, nodeKey: values.nodeKey || null, metadata: parseJson(values.metadata, {}) } });
      message.success('目录节点已保存'); setNodeDrawer(undefined); await loadNodes();
    } catch (error) { message.error(error instanceof Error ? error.message : '目录保存失败'); }
  };
  const saveBatchNodes = async () => {
    const values = await batchForm.validateFields();
    const names = String(values.names).split(/\n|,/).map((item) => item.trim()).filter(Boolean);
    if (names.length > 100) return message.error('一次最多创建 100 个节点');
    await platformRequest('POST', '/api/platform-admin/question-banks/nodes/batch', { body: { questionBankId: bankId, parentId: values.parentId || null, nodeType: values.nodeType, names } });
    message.success(`已创建 ${names.length} 个节点`); setBatchNodeOpen(false); batchForm.resetFields(); await loadNodes();
  };

  const openQuestion = (record?: Question) => {
    if (!bankId || (!nodeId && !record)) return message.warning('请先选择一个章节或试卷');
    setQuestionDrawer(record || null);
    queueMicrotask(() => questionForm.setFieldsValue({
      id: record?.id, type: record?.type || 'choice', typeLabel: record?.typeLabel, difficulty: record?.difficulty ? Number(record.difficulty) : 3,
      status: record ? String(record.status) : 'published', content: record?.content, answerText: record?.answerText, explanation: record?.explanation,
      options: JSON.stringify(record?.options || [], null, 2), correctOptionIndex: record?.correctOptionIndex == null ? null : Number(record.correctOptionIndex),
      correctOptionIndices: JSON.stringify(record?.correctOptionIndices || [], null, 2), tags: JSON.stringify(record?.tags || [], null, 2),
      subQuestions: JSON.stringify(record?.subQuestions || [], null, 2), codeLang: record?.codeLang, codeTemplate: record?.codeTemplate,
      mediaUrl: record?.mediaUrl,
    }));
  };
  const saveQuestion = async () => {
    const values = await questionForm.validateFields();
    try {
      await platformRequest('PUT', '/api/platform-admin/question-banks/questions', { body: {
        ...values, id: values.id || null, questionBankId: bankId, contentNodeId: questionDrawer?.contentNodeId || nodeId,
        legacyId: questionDrawer?.legacyId || null, options: parseJson(values.options, []), correctOptionIndices: parseJson(values.correctOptionIndices, []),
        tags: parseJson(values.tags, []), subQuestions: parseJson(values.subQuestions, []), examMarkers: {}, sourceHash: null,
      } });
      message.success(questionDrawer ? '题目已更新并生成新版本' : '题目已创建'); setQuestionDrawer(undefined); await Promise.all([loadQuestions(), loadNodes()]);
    } catch (error) { message.error(error instanceof Error ? error.message : '题目保存失败'); }
  };

  const archiveQuestions = () => modal.confirm({
    title: `归档 ${selectedQuestionIds.length} 道题目`, content: '归档后不会再作为正常题目展示。', okButtonProps: { danger: true },
    onOk: async () => { await platformRequest('POST', '/api/platform-admin/question-banks/questions/archive', { body: { questionIds: selectedQuestionIds } }); message.success('题目已归档'); await loadQuestions(); },
  });

  const runImport = async (preview: boolean) => {
    const values = await importForm.validateFields();
    try {
      const payload = parseJson(values.payload, []);
      const result = await platformRequest<ImportResult>('POST', preview ? '/api/platform-admin/question-banks/imports/preview' : '/api/platform-admin/question-banks/imports', {
        body: { questionBankId: bankId, contentNodeId: values.format === 'simple' ? (values.contentNodeId || nodeId || null) : null, format: values.format, sourceName: values.sourceName || null, payload },
      });
      setImportResult(result);
      message.success(preview ? '预检完成' : '导入完成');
      if (!preview) await Promise.all([loadQuestions(), loadNodes(), loadBanks()]);
    } catch (error) { message.error(error instanceof Error ? error.message : '导入处理失败'); }
  };

  const uploadAsset = async ({ file, onError, onSuccess, onProgress }: UploadRequestOption) => {
    const blob = file as File;
    try {
      onProgress?.({ percent: 10 });
      const sign = await platformRequest<UploadSignResult>('POST', '/api/platform-admin/question-banks/assets/upload-sign', { body: {
        contentNodeId: nodeId || null, fileName: blob.name, mimeType: blob.type || 'application/octet-stream', fileSizeBytes: blob.size,
        title: blob.name, category: 'question', assetType: 'image', visibility: 'public', isPublic: true, metadata: {},
      } });
      const headers = new Headers(sign.upload.headers);
      const uploaded = await fetch(sign.upload.url, { method: sign.upload.method || 'PUT', headers, body: blob });
      if (!uploaded.ok) throw new Error(`文件上传失败（HTTP ${uploaded.status}）`);
      onProgress?.({ percent: 80 });
      const confirmed = await platformRequest<UploadConfirmResult>('POST', '/api/platform-admin/question-banks/assets/upload-confirm', { body: { assetId: sign.item.id, mimeType: blob.type, fileSizeBytes: blob.size } });
      questionForm.setFieldValue('mediaUrl', confirmed.item.cdnUrl || sign.upload.url.split('?')[0]);
      onProgress?.({ percent: 100 }); onSuccess?.(confirmed); message.success('资源上传成功');
    } catch (error) { onError?.(error as Error); message.error(error instanceof Error ? error.message : '资源上传失败'); }
  };

  const columns = [
    { title: '题型', dataIndex: 'typeLabel', width: 100, render: (_: unknown, record: Question) => record.typeLabel || questionTypes.find((item) => item.value === record.type)?.label || record.type },
    { title: '题干', dataIndex: 'content', ellipsis: true, render: (value: string) => value || <Typography.Text type="secondary">无文字题干</Typography.Text> },
    { title: '难度', dataIndex: 'difficulty', width: 90, render: (value: number | string | null) => value ? `${value} 级` : '-' },
    { title: '状态', dataIndex: 'status', width: 90, render: (value: string | number) => <Tag color={String(value) === '1' || value === 'published' ? 'green' : 'default'}>{statusLabels[String(value)] || String(value)}</Tag> },
    { title: '版本', dataIndex: 'versionNo', width: 75, render: (value: number | string) => `v${value}` },
    { title: '操作', key: 'actions', width: 80, fixed: 'right' as const, render: (_: unknown, record: Question) => <Button type="link" icon={<EditOutlined />} onClick={() => openQuestion(record)}>编辑</Button> },
  ];

  const treeData = useMemo(() => toTree(nodes), [nodes]);
  return (
    <div className="question-bank-page">
      <Flex justify="space-between" align="end" gap={16} wrap>
        <div><Typography.Title level={2}>公共题库</Typography.Title><Typography.Text type="secondary">维护题库目录、题目版本、批量导入与图片资源</Typography.Text></div>
        <Space><Button icon={<CloudUploadOutlined />} disabled={!bankId} onClick={() => { setImportOpen(true); setImportResult(null); queueMicrotask(() => importForm.setFieldsValue({ format: 'simple', contentNodeId: nodeId, sourceName: '', payload: '[]' })); }}>导入题目</Button><Button type="primary" icon={<PlusOutlined />} onClick={() => openQuestion()}>录入题目</Button></Space>
      </Flex>
      <Splitter className="question-workspace">
        <Splitter.Panel defaultSize="22%" min="260px" max="360px">
          <div className="workspace-panel bank-panel">
            <Flex gap={8}><Input allowClear value={bankKeyword} onChange={(event) => setBankKeyword(event.target.value)} onPressEnter={() => void loadBanks()} prefix={<SearchOutlined />} placeholder="搜索题库" /><Button icon={<PlusOutlined />} onClick={() => openBank()} /></Flex>
            <Select value={bankStatus} onChange={(value) => { setBankStatus(value); void loadBanks(value); }} options={[{ value: 'active', label: '正常题库' }, { value: 'archived', label: '已归档' }, { value: 'all', label: '全部题库' }]} />
            <List loading={loading} dataSource={banks} locale={{ emptyText: '暂无题库' }} renderItem={(item) => <List.Item className={item.id === bankId ? 'selected-business-item' : ''} onClick={() => setBankId(item.id)} actions={[<Button key="edit" type="text" icon={<EditOutlined />} onClick={(event) => { event.stopPropagation(); openBank(item); }} />]}><List.Item.Meta title={item.name} description={`${item.nodeCount} 个节点 · ${item.questionCount} 道题`} /></List.Item>} />
          </div>
        </Splitter.Panel>
        <Splitter.Panel defaultSize="24%" min="270px" max="420px">
          <div className="workspace-panel node-panel">
            <Flex justify="space-between" align="center"><Typography.Title level={5}>内容目录</Typography.Title><Space size={2}><Button type="text" icon={<FolderAddOutlined />} disabled={!bankId} onClick={() => openNode()} /><Button type="text" icon={<FileAddOutlined />} disabled={!bankId} onClick={() => { setBatchNodeOpen(true); queueMicrotask(() => batchForm.setFieldsValue({ parentId: nodeId || null, nodeType: 2 })); }} /><Button type="text" icon={<ReloadOutlined />} onClick={() => void loadNodes()} /></Space></Flex>
            {treeData.length ? <Tree blockNode defaultExpandAll selectedKeys={nodeId ? [nodeId] : []} treeData={treeData} onSelect={(keys) => { setNodeId(String(keys[0] || '')); setPage(1); }} titleRender={(treeNode) => <div onDoubleClick={() => { const record = nodes.find((item) => item.id === treeNode.key); if (record) openNode(record); }}>{treeNode.title as React.ReactNode}</div>} /> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="选择题库后维护目录" />}
            {node && <Card size="small" className="node-detail"><Flex justify="space-between"><div><Typography.Text strong>{node.name}</Typography.Text><br /><Typography.Text type="secondary">{nodeTypes.find((item) => item.value === node.nodeType)?.label} · 排序 {node.sortOrder}</Typography.Text></div><Space><Button size="small" icon={<EditOutlined />} onClick={() => openNode(node)}>编辑</Button><Popconfirm title="确认归档此节点？" onConfirm={async () => { await platformRequest('POST', '/api/platform-admin/question-banks/nodes/{nodeId}/archive', { path: { nodeId } }); message.success('节点已归档'); await loadNodes(); }}><Button size="small" danger icon={<StopOutlined />} /></Popconfirm></Space></Flex></Card>}
          </div>
        </Splitter.Panel>
        <Splitter.Panel min="520px">
          <div className="workspace-panel question-panel">
            <Flex justify="space-between" gap={8} wrap><Space wrap><Input allowClear placeholder="搜索题干" value={filters.keyword} onChange={(event) => setFilters((value) => ({ ...value, keyword: event.target.value }))} onPressEnter={() => { setPage(1); void loadQuestions(); }} /><Select allowClear placeholder="题型" value={filters.type || undefined} options={questionTypes} onChange={(value) => { setFilters((old) => ({ ...old, type: value || '' })); setPage(1); }} /><Select allowClear placeholder="状态" value={filters.status || undefined} options={[{ value: 'draft', label: '草稿' }, { value: 'published', label: '已发布' }, { value: 'archived', label: '已归档' }]} onChange={(value) => { setFilters((old) => ({ ...old, status: value || '' })); setPage(1); }} /></Space><Space><Button icon={<DownloadOutlined />} disabled={!questions.length} onClick={() => downloadJson(`${bank?.name || '公共题库'}-${node?.name || '全部题目'}.json`, questions)}>导出本页</Button><Button danger icon={<DeleteOutlined />} disabled={!selectedQuestionIds.length} onClick={archiveQuestions}>批量归档</Button></Space></Flex>
            <Table<Question> rowKey="id" loading={loading} dataSource={questions} columns={columns} scroll={{ x: 760 }} rowSelection={{ selectedRowKeys: selectedQuestionIds, preserveSelectedRowKeys: true, onChange: setSelectedQuestionIds }} pagination={{ current: page, pageSize, total, showSizeChanger: true, showTotal: (value) => `共 ${value} 道题`, onChange: (next, size) => { setPage(next); setPageSize(size); } }} locale={{ emptyText: nodeId ? '当前节点暂无题目' : '当前题库暂无题目' }} />
          </div>
        </Splitter.Panel>
      </Splitter>

      <Drawer title={bankDrawer?.id ? '编辑题库' : '新建题库'} width={520} open={bankDrawer !== undefined} onClose={() => setBankDrawer(undefined)} extra={<Button type="primary" onClick={() => void saveBank()}>保存</Button>}>
        <Form form={bankForm} layout="vertical"><Form.Item name="id" hidden><Input /></Form.Item><Form.Item name="name" label="题库名称" rules={[{ required: true }]}><Input maxLength={200} /></Form.Item><Form.Item name="metadata" label="扩展配置（JSON）" rules={[{ validator: async (_, value) => { parseJson(value, {}); } }]}><Input.TextArea rows={8} /></Form.Item>{bankDrawer?.id && <Popconfirm title="确认归档此题库？" onConfirm={async () => { await platformRequest('POST', '/api/platform-admin/question-banks/{bankId}/archive', { path: { bankId: bankDrawer.id } }); setBankDrawer(undefined); await loadBanks(); }}><Button danger icon={<StopOutlined />}>归档题库</Button></Popconfirm>}</Form>
      </Drawer>
      <Drawer title={nodeDrawer?.id ? '编辑目录节点' : '新增目录节点'} width={560} open={nodeDrawer !== undefined} onClose={() => setNodeDrawer(undefined)} extra={<Button type="primary" onClick={() => void saveNode()}>保存</Button>}>
        <Form form={nodeForm} layout="vertical"><Form.Item name="id" hidden><Input /></Form.Item><Form.Item name="name" label="名称" rules={[{ required: true }]}><Input /></Form.Item><Form.Item name="parentId" label="上级节点"><Select allowClear options={nodes.filter((item) => item.id !== nodeDrawer?.id).map((item) => ({ value: item.id, label: item.name }))} /></Form.Item><Flex gap={12}><Form.Item name="nodeType" label="节点类型" rules={[{ required: true }]} className="flex-field"><Select options={nodeTypes} /></Form.Item><Form.Item name="sortOrder" label="排序" className="flex-field"><InputNumber min={0} /></Form.Item></Flex><Form.Item name="nodeKey" label="业务编码"><Input /></Form.Item><Form.Item name="isSelectable" label="可承载题目"><Radio.Group options={[{ value: true, label: '是' }, { value: false, label: '否' }]} /></Form.Item><Form.Item name="metadata" label="扩展配置（JSON）"><Input.TextArea rows={5} /></Form.Item></Form>
      </Drawer>
      <Modal title="批量创建章节或试卷" open={batchNodeOpen} onCancel={() => setBatchNodeOpen(false)} onOk={() => void saveBatchNodes()} okText="创建">
        <Form form={batchForm} layout="vertical"><Form.Item name="parentId" label="上级节点"><Select allowClear options={nodes.map((item) => ({ value: item.id, label: item.name }))} /></Form.Item><Form.Item name="nodeType" label="节点类型" rules={[{ required: true }]}><Select options={nodeTypes.filter((item) => [2, 3].includes(item.value))} /></Form.Item><Form.Item name="names" label="名称列表" extra="每行一个，最多 100 个" rules={[{ required: true }]}><Input.TextArea rows={9} placeholder={'第一章 基础知识\n第二章 核心方法'} /></Form.Item></Form>
      </Modal>
      <Drawer title={questionDrawer?.id ? `编辑题目 · v${questionDrawer.versionNo}` : '录入题目'} width={760} open={questionDrawer !== undefined} onClose={() => setQuestionDrawer(undefined)} extra={<Button type="primary" onClick={() => void saveQuestion()}>保存题目</Button>}>
        <Form form={questionForm} layout="vertical"><Form.Item name="id" hidden><Input /></Form.Item><Flex gap={12}><Form.Item name="type" label="题型" rules={[{ required: true }]} className="flex-field"><Select options={questionTypes} /></Form.Item><Form.Item name="difficulty" label="难度" className="flex-field"><Select options={[1,2,3,4,5].map((value) => ({ value, label: `${value} 级` }))} /></Form.Item><Form.Item name="status" label="状态" className="flex-field"><Select options={[{ value: 'draft', label: '草稿' }, { value: 'published', label: '已发布' }]} /></Form.Item></Flex><Form.Item name="typeLabel" label="题型显示名"><Input /></Form.Item><Form.Item name="content" label="题干" rules={[{ required: true }]}><Input.TextArea rows={5} /></Form.Item><Tabs items={[{ key: 'answer', label: '答案与解析', children: <><Form.Item name="options" label="选项（JSON 数组）"><Input.TextArea rows={5} /></Form.Item><Form.Item name="correctOptionIndex" label="单选答案索引"><InputNumber min={0} /></Form.Item><Form.Item name="correctOptionIndices" label="多选答案索引（JSON 数组）"><Input /></Form.Item><Form.Item name="answerText" label="文字答案"><Input.TextArea rows={3} /></Form.Item><Form.Item name="explanation" label="解析"><Input.TextArea rows={5} /></Form.Item></> }, { key: 'advanced', label: '扩展内容', children: <><Form.Item name="tags" label="标签（JSON 数组）"><Input /></Form.Item><Form.Item name="subQuestions" label="子题（JSON 数组）"><Input.TextArea rows={5} /></Form.Item><Flex gap={12}><Form.Item name="codeLang" label="代码语言" className="flex-field"><Input /></Form.Item><Form.Item name="mediaUrl" label="图片或视频地址" className="flex-field"><Input /></Form.Item></Flex><Form.Item name="codeTemplate" label="代码模板"><Input.TextArea rows={5} /></Form.Item><Upload customRequest={uploadAsset} showUploadList={false} accept="image/*"><Button icon={<CloudUploadOutlined />}>上传题目图片</Button></Upload></> }]} /></Form>
      </Drawer>
      <Modal title="题目 JSON 导入" width={900} open={importOpen} onCancel={() => setImportOpen(false)} footer={<Flex justify="space-between"><Upload beforeUpload={async (file) => { importForm.setFieldsValue({ sourceName: file.name, payload: await file.text() }); return false; }} showUploadList={false} accept=".json,application/json"><Button icon={<CloudUploadOutlined />}>读取 JSON 文件</Button></Upload><Space><Button onClick={() => void runImport(true)}>预检</Button><Button type="primary" onClick={() => void runImport(false)}>确认导入</Button></Space></Flex>}>
        <Form form={importForm} layout="vertical"><Flex gap={12}><Form.Item name="format" label="导入格式" className="flex-field"><Select options={[{ value: 'simple', label: '普通题目数组' }, { value: 'structured-v2', label: '科目/章节结构化数据' }]} /></Form.Item><Form.Item name="contentNodeId" label="目标章节或试卷" className="flex-field"><Select allowClear options={nodes.map((item) => ({ value: item.id, label: item.name }))} /></Form.Item><Form.Item name="sourceName" label="来源名称" className="flex-field"><Input /></Form.Item></Flex><Form.Item name="payload" label="JSON 内容" rules={[{ required: true }, { validator: async (_, value) => { parseJson(value, []); } }]}><Input.TextArea rows={14} className="code-editor" /></Form.Item></Form>
        {importResult && <Card size="small" title="处理结果"><Progress percent={importResult.detail.job.totalCount ? Math.round(Number(importResult.detail.job.validCount) / Number(importResult.detail.job.totalCount) * 100) : 0} status={Number(importResult.detail.job.errorCount) ? 'exception' : 'success'} /><Descriptions size="small" column={4} items={[{ key: 'total', label: '总数', children: importResult.detail.job.totalCount }, { key: 'valid', label: '有效', children: importResult.detail.job.validCount }, { key: 'errors', label: '错误', children: importResult.detail.job.errorCount }, { key: 'inserted', label: '新增', children: importResult.insertedQuestionCount }]} />{importResult.detail.issues.length > 0 && <Table size="small" pagination={false} dataSource={importResult.detail.issues} rowKey="id" columns={[{ title: '行号', dataIndex: 'rowNo' }, { title: '字段', dataIndex: 'fieldPath' }, { title: '级别', dataIndex: 'severity' }, { title: '问题', dataIndex: 'message' }]} />}</Card>}
      </Modal>
    </div>
  );
}
