import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Alert,
  App,
  Button,
  Card,
  Col,
  Descriptions,
  Drawer,
  Empty,
  Form,
  Input,
  Modal,
  Popconfirm,
  Row,
  Select,
  Space,
  Table,
  Tag,
  Upload,
} from 'antd';
import type { UploadProps } from 'antd';
import {
  CloudUploadOutlined,
  DownloadOutlined,
  ExportOutlined,
  EyeOutlined,
  InboxOutlined,
  PlusOutlined,
  SwapOutlined,
  UndoOutlined,
  UploadOutlined,
} from '@ant-design/icons';
import api from '../../api';
import PermissionButton from '../../components/PermissionButton';
import StudentProfileContent from '../../components/StudentProfileContent';
import EditableCell from '../../components/EditableCell';
import JinshujuMatchModal from '../../components/JinshujuMatchModal';
import { maskIdNumber, maskPhone } from '../../utils/sensitive';
import { message } from '../../ui/app-message';
import { usePermission } from '../../hooks/usePermission';

const statusMap: Record<string, { text: string; color: string }> = {
  active: { text: '在读', color: 'green' },
  graduated: { text: '已毕业', color: 'blue' },
  withdrawn: { text: '已退训', color: 'red' },
  archived: { text: '已归档', color: '#999' },
};

interface EnrollmentInfo {
  classId: number;
  className: string;
  classType: string;
  startDate: string;
  endDate: string;
  joinDate: string;
  leaveDate: string;
  status: string;
  attendanceStats: {
    total: number;
    present: number;
    absent: number;
    late: number;
    leave: number;
    rate: number;
  };
}

interface StudentCreateImportResult {
  message?: string;
  imported?: number;
  skipped?: number;
}

interface StudentUpdateImportResult {
  message?: string;
  matched?: number;
  skipped?: number;
}

interface StudentFilterLookups {
  classes: Array<{ id: number; name: string; code?: string }>;
  teachers: Array<{ id: number; name: string; username: string }>;
}

const StudentsPage: React.FC = () => {
  const { modal } = App.useApp();
  const { hasPermission, hasAnyPermission } = usePermission();
  const canViewOrganizations = hasPermission('organization:view');
  const canChooseOrganization =
    canViewOrganizations && hasAnyPermission('student:create', 'student:edit');
  const [data, setData] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const [modalOpen, setModalOpen] = useState(false);
  const [organizations, setOrganizations] = useState<any[]>([]);
  const [editing, setEditing] = useState<any>(null);
  const [searchName, setSearchName] = useState('');
  const [filterStatus, setFilterStatus] = useState<string | undefined>(undefined);
  const [filterOrganizationId, setFilterOrganizationId] = useState<number | undefined>(undefined);
  const [filterClassId, setFilterClassId] = useState<number | undefined>(undefined);
  const [filterTeacherId, setFilterTeacherId] = useState<number | undefined>(undefined);
  const [classOptions, setClassOptions] = useState<StudentFilterLookups['classes']>([]);
  const [teacherOptions, setTeacherOptions] = useState<StudentFilterLookups['teachers']>([]);
  const [showArchived, setShowArchived] = useState(false);
  const [archivedCount, setArchivedCount] = useState(0);
  const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
  const [batchLoading, setBatchLoading] = useState(false);
  const [enrollmentData, setEnrollmentData] = useState<Record<number, EnrollmentInfo[]>>({});
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [drawerStudentId, setDrawerStudentId] = useState<number | undefined>(undefined);
  const [form] = Form.useForm();
  const [saving, setSaving] = useState(false);

  const openDrawer = (studentId: number) => {
    setDrawerStudentId(studentId);
    setDrawerOpen(true);
  };

  const [jinshujuOpen, setJinshujuOpen] = useState(false);

  const handleViewSensitive = (studentId: number, field: string, value: string) => {
    modal.confirm({
      title: '查看敏感信息',
      content: `您即将查看 "${field}" 的完整信息。此操作将被记录。`,
      okText: '确认查看',
      cancelText: '取消',
      onOk: async () => {
        try {
          await api.post('/operation-logs/audit', {
            module: '学生管理',
            action: '查看敏感信息',
            targetId: studentId,
            targetType: 'student',
            detail: `查看${field}`,
          });
          modal.info({
            title: field,
            content: value,
            okText: '关闭',
          });
        } catch {
          message.error('审计日志记录失败，请稍后重试');
        }
      },
    });
  };

  const handleBatchDelete = async () => {
    setBatchLoading(true);
    try {
      const res: any = await api.post('/students/batch-delete', { ids: selectedRowKeys });
      message.success(res?.message || `已批量归档 ${selectedRowKeys.length} 人`);
      setSelectedRowKeys([]);
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '批量归档失败');
    } finally {
      setBatchLoading(false);
    }
  };

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const params: Record<string, unknown> = {
        name: searchName || undefined,
        includeArchived: 'true',
      };
      if (filterStatus) params.status = filterStatus;
      if (filterOrganizationId) params.organizationId = filterOrganizationId;
      if (filterClassId) params.classId = filterClassId;
      if (filterTeacherId) params.teacherId = filterTeacherId;
      const res = (await api.get('/students', { params })) as Array<Record<string, unknown>>;
      const list = res as Array<Record<string, unknown>>;
      const archived = list.filter((r) => r.status === 'archived');
      setArchivedCount(archived.length);
      setData(showArchived ? list : list.filter((r) => r.status !== 'archived'));
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '加载失败，请稍后重试');
    }
    setLoading(false);
  }, [
    searchName,
    showArchived,
    filterStatus,
    filterOrganizationId,
    filterClassId,
    filterTeacherId,
  ]);

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

  useEffect(() => {
    if (canViewOrganizations) {
      api
        .get('/organizations', { params: { includeArchived: 'false' } })
        .then((res: unknown) => {
          setOrganizations(res as Array<{ id: number; name: string }>);
        })
        .catch(() => {});
    } else {
      setOrganizations([]);
      setFilterOrganizationId(undefined);
    }
    api
      .get<StudentFilterLookups>('/students/filter-lookups')
      .then((res) => {
        setClassOptions(res.classes || []);
        setTeacherOptions(res.teachers || []);
      })
      .catch(() => {});
  }, [canViewOrganizations]);
  const handleSave = async () => {
    const values = await form.validateFields();
    setSaving(true);
    try {
      if (editing) {
        await api.put(`/students/${editing.id}`, values);
        message.success('更新成功');
      } else {
        await api.post('/students', values);
        message.success('创建成功');
      }
      setModalOpen(false);
      form.resetFields();
      setEditing(null);
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '操作失败');
    } finally {
      setSaving(false);
    }
  };

  const saveCell = useCallback(
    async (record: any, field: string, value: unknown) => {
      await api.put(`/students/${record.id}`, { [field]: value });
      message.success('已保存');
      await fetchData();
    },
    [fetchData],
  );

  const handleArchive = async (id: number) => {
    try {
      await api.delete(`/students/${id}`);
      message.success('已归档');
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '归档失败');
    }
  };

  const handleRestore = async (id: number) => {
    try {
      await api.put(`/students/${id}/restore`);
      message.success('已恢复');
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '恢复失败');
    }
  };

  const handleDownloadTemplate = () => {
    const baseURL = import.meta.env.PROD
      ? '/api'
      : `http://localhost:${import.meta.env.VITE_API_PORT || 3002}/api`;
    const token = localStorage.getItem('token');
    fetch(`${baseURL}/students/template`, { headers: { Authorization: `Bearer ${token}` } })
      .then((res) => res.blob())
      .then((blob) => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = '学生导入模板.xlsx';
        a.click();
        URL.revokeObjectURL(url);
      })
      .catch(() => message.error('下载失败'));
  };

  const showCreateImportResult = (result: StudentCreateImportResult) => {
    const imported = result.imported ?? 0;
    const skipped = result.skipped ?? 0;

    modal.success({
      title: '导入完成',
      okText: '知道了',
      content: (
        <div>
          <Descriptions column={1} size="small">
            <Descriptions.Item label="成功新增">{imported} 人</Descriptions.Item>
            <Descriptions.Item label="跳过">{skipped} 人</Descriptions.Item>
          </Descriptions>
          <div style={{ marginTop: 12, fontWeight: 600 }}>跳过原因：</div>
          <ul style={{ marginBottom: 0, paddingLeft: 20 }}>
            <li>姓名为空</li>
            <li>已存在同名学生</li>
          </ul>
          <div style={{ marginTop: 8, color: '#8c8c8c', fontSize: 12 }}>
            当前后端只返回统计汇总，暂时无法列出具体哪几行被跳过。
          </div>
        </div>
      ),
    });
  };

  const showUpdateImportResult = (result: StudentUpdateImportResult) => {
    const matched = result.matched ?? 0;
    const skipped = result.skipped ?? 0;

    modal.success({
      title: '更新完成',
      okText: '知道了',
      content: (
        <div>
          <Descriptions column={1} size="small">
            <Descriptions.Item label="成功更新">{matched} 人</Descriptions.Item>
            <Descriptions.Item label="未匹配">{skipped} 人</Descriptions.Item>
          </Descriptions>
          <div style={{ marginTop: 12, fontWeight: 600 }}>匹配规则：</div>
          <div>手机号优先，身份证号其次</div>
          <div style={{ marginTop: 8, color: '#8c8c8c', fontSize: 12 }}>
            当前后端只返回统计汇总，暂时无法列出具体哪几行未匹配。
          </div>
        </div>
      ),
    });
  };

  const handleCreateStudentsImport: UploadProps['customRequest'] = async ({
    file,
    onSuccess,
    onError,
  }) => {
    const formData = new FormData();
    formData.append('file', file as File);
    try {
      const res = (await api.post('/students/import', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
      })) as StudentCreateImportResult;
      showCreateImportResult(res);
      onSuccess?.(res);
      fetchData();
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '导入失败');
      onError?.(e instanceof Error ? e : new Error(err?.message || '导入失败'));
    }
  };

  const handleUpdateExistingStudentsImport: UploadProps['customRequest'] = async ({
    file,
    onSuccess,
    onError,
  }) => {
    const formData = new FormData();
    formData.append('file', file as File);
    try {
      const res = (await api.post('/students/import-match', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
      })) as StudentUpdateImportResult;
      showUpdateImportResult(res);
      onSuccess?.(res);
      fetchData();
    } catch (e: unknown) {
      const err = e as { message?: string };
      message.error(err?.message || '更新已有学生资料失败');
      onError?.(e instanceof Error ? e : new Error(err?.message || '更新已有学生资料失败'));
    }
  };

  const handleExport = () => {
    const baseURL = import.meta.env.PROD
      ? '/api'
      : `http://localhost:${import.meta.env.VITE_API_PORT || 3002}/api`;
    const token = localStorage.getItem('token');
    const params = new URLSearchParams();
    if (searchName) params.set('name', searchName);
    if (filterStatus) params.set('status', filterStatus);
    if (filterOrganizationId) params.set('organizationId', String(filterOrganizationId));
    if (showArchived) params.set('includeArchived', 'true');
    if (filterClassId) params.set('classId', String(filterClassId));
    if (filterTeacherId) params.set('teacherId', String(filterTeacherId));
    const query = params.toString() ? `?${params.toString()}` : '';
    fetch(`${baseURL}/students/export${query}`, { headers: { Authorization: `Bearer ${token}` } })
      .then((res) => res.blob())
      .then((blob) => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = '学生名单.xlsx';
        a.click();
        URL.revokeObjectURL(url);
      })
      .catch(() => message.error('导出失败'));
  };

  const columns = useMemo(
    () => [
      { title: 'ID', dataIndex: 'id', width: 70 },
      {
        title: '姓名',
        dataIndex: 'name',
        width: 120,
        render: (v: string, record: any) => (
          <EditableCell
            value={v}
            required
            permission="student:edit"
            disabled={record.status === 'archived'}
            onSave={(next) => saveCell(record, 'name', next)}
          >
            {v}
          </EditableCell>
        ),
      },
      {
        title: '电话',
        dataIndex: 'phone',
        width: 140,
        render: (v: string, record: any) => {
          if (!v) return '-';
          return (
            <span style={{ display: 'inline-flex', alignItems: 'center', whiteSpace: 'nowrap' }}>
              <span style={{ marginRight: 4 }}>{maskPhone(v)}</span>
              {hasPermission('log:create') ? (
                <Button
                  type="link"
                  size="small"
                  style={{ padding: '8px 4px', flex: 'none' }}
                  onClick={() => handleViewSensitive(record.id, '电话', v)}
                  title="点击查看完整号码"
                >
                  <EyeOutlined style={{ fontSize: 12, color: '#999' }} />
                </Button>
              ) : null}
            </span>
          );
        },
      },
      {
        title: '学号',
        dataIndex: 'studentNo',
        width: 120,
        render: (v: string, record: any) => (
          <EditableCell
            value={v}
            permission="student:edit"
            disabled={record.status === 'archived'}
            onSave={(next) => saveCell(record, 'studentNo', next)}
          >
            {v || '-'}
          </EditableCell>
        ),
      },
      {
        title: '身份证',
        dataIndex: 'idNumber',
        width: 180,
        render: (v: string, record: any) => {
          if (!v) return '-';
          return (
            <span style={{ display: 'inline-flex', alignItems: 'center', whiteSpace: 'nowrap' }}>
              <span style={{ marginRight: 4 }}>{maskIdNumber(v)}</span>
              {hasPermission('log:create') ? (
                <Button
                  type="link"
                  size="small"
                  style={{ padding: '8px 4px', flex: 'none' }}
                  onClick={() => handleViewSensitive(record.id, '身份证号', v)}
                  title="点击查看完整号码"
                >
                  <EyeOutlined style={{ fontSize: 12, color: '#999' }} />
                </Button>
              ) : null}
            </span>
          );
        },
      },
      {
        title: '民族',
        dataIndex: 'ethnicity',
        width: 90,
        render: (v: string, record: any) => (
          <EditableCell
            value={v}
            permission="student:edit"
            disabled={record.status === 'archived'}
            onSave={(next) => saveCell(record, 'ethnicity', next)}
          >
            {v || '-'}
          </EditableCell>
        ),
      },
      {
        title: '紧急联系人',
        dataIndex: 'emergencyContact',
        width: 100,
        render: (v: string, record: any) => (
          <EditableCell
            value={v}
            permission="student:edit"
            disabled={record.status === 'archived'}
            onSave={(next) => saveCell(record, 'emergencyContact', next)}
          >
            {v || '-'}
          </EditableCell>
        ),
      },
      {
        title: '紧急联系人电话',
        dataIndex: 'emergencyPhone',
        width: 150,
        render: (v: string, record: any) => {
          if (!v) return '-';
          return (
            <span style={{ display: 'inline-flex', alignItems: 'center', whiteSpace: 'nowrap' }}>
              <span style={{ marginRight: 4 }}>{maskPhone(v)}</span>
              {hasPermission('log:create') ? (
                <Button
                  type="link"
                  size="small"
                  style={{ padding: '8px 4px', flex: 'none' }}
                  onClick={() => handleViewSensitive(record.id, '紧急联系人电话', v)}
                  title="点击查看完整号码"
                >
                  <EyeOutlined style={{ fontSize: 12, color: '#999' }} />
                </Button>
              ) : null}
            </span>
          );
        },
      },
      {
        title: '所属机构',
        dataIndex: 'organization',
        width: 100,
        render: (organization: { name?: string } | null, record: any) =>
          canChooseOrganization ? (
            <EditableCell
              value={record.organizationId}
              editor="select"
              options={organizations.map((item) => ({ value: item.id, label: item.name }))}
              permission="student:edit"
              disabled={record.status === 'archived'}
              required
              onSave={(next) => saveCell(record, 'organizationId', next)}
            >
              {organization?.name ? (
                <Tag
                  color="purple"
                  style={{ maxWidth: '100%', overflow: 'hidden', textOverflow: 'ellipsis' }}
                >
                  {organization.name}
                </Tag>
              ) : (
                '-'
              )}
            </EditableCell>
          ) : organization?.name ? (
            <Tag color="purple">{organization.name}</Tag>
          ) : (
            '-'
          ),
      },
      {
        title: '负责人',
        dataIndex: 'supervisor',
        width: 100,
        render: (v: string, record: any) => (
          <EditableCell
            value={v}
            permission="student:edit"
            disabled={record.status === 'archived'}
            onSave={(next) => saveCell(record, 'supervisor', next)}
          >
            {v || '-'}
          </EditableCell>
        ),
      },
      {
        title: '状态',
        dataIndex: 'status',
        width: 80,
        render: (s: string, record: any) => (
          <EditableCell
            value={s}
            editor="select"
            options={[
              { value: 'active', label: '在读' },
              { value: 'graduated', label: '已毕业' },
              { value: 'withdrawn', label: '已退训' },
            ]}
            permission="student:edit"
            disabled={record.status === 'archived'}
            onSave={(next) => saveCell(record, 'status', next)}
          >
            <Tag
              color={statusMap[s]?.color}
              style={{ maxWidth: '100%', overflow: 'hidden', textOverflow: 'ellipsis' }}
            >
              {statusMap[s]?.text || s}
            </Tag>
          </EditableCell>
        ),
      },
      {
        title: '操作',
        width: 180,
        render: (_: any, record: any) => (
          <Space>
            {record.status === 'archived' ? (
              <Popconfirm
                title="确定恢复此学生？恢复后将重新出现在学生列表中。"
                onConfirm={() => handleRestore(record.id)}
                okText="恢复"
                cancelText="取消"
              >
                <PermissionButton
                  permission="student:edit"
                  size="small"
                  icon={<UndoOutlined />}
                  type="link"
                >
                  恢复
                </PermissionButton>
              </Popconfirm>
            ) : (
              <>
                <PermissionButton
                  permission="student:view"
                  size="small"
                  type="link"
                  onClick={() => openDrawer(record.id)}
                >
                  档案
                </PermissionButton>
                <PermissionButton
                  permission="student:edit"
                  size="small"
                  onClick={() => {
                    setEditing(record);
                    form.setFieldsValue(record);
                    setModalOpen(true);
                  }}
                >
                  编辑
                </PermissionButton>
                <Popconfirm
                  title="归档后不会删除数据，可随时恢复。确定归档？"
                  onConfirm={() => handleArchive(record.id)}
                  okText="归档"
                  cancelText="取消"
                >
                  <PermissionButton
                    permission="student:delete"
                    size="small"
                    icon={<InboxOutlined />}
                  >
                    归档
                  </PermissionButton>
                </Popconfirm>
              </>
            )}
          </Space>
        ),
      },
    ],
    [
      handleViewSensitive,
      openDrawer,
      showArchived,
      organizations,
      saveCell,
      hasPermission,
      canChooseOrganization,
    ],
  );

  return (
    <div>
      <div className="responsive-toolbar">
        <Space wrap className="responsive-toolbar__group">
          <Input.Search
            placeholder="搜索学生姓名"
            onSearch={setSearchName}
            allowClear
            style={{ width: 250 }}
          />
          <Select
            placeholder="状态筛选"
            allowClear
            style={{ width: 120 }}
            value={filterStatus}
            onChange={(v) => {
              setFilterStatus(v);
            }}
          >
            {Object.entries(statusMap)
              .filter(([k]) => k !== 'archived')
              .map(([k, v]) => (
                <Select.Option key={k} value={k}>
                  {v.text}
                </Select.Option>
              ))}
          </Select>
          {canViewOrganizations ? (
            <Select
              placeholder="所属机构"
              allowClear
              style={{ width: 140 }}
              value={filterOrganizationId}
              onChange={(v) => {
                setFilterOrganizationId(v);
              }}
            >
              {organizations.map((t: { id: number; name: string }) => (
                <Select.Option key={t.id} value={t.id}>
                  {t.name}
                </Select.Option>
              ))}
            </Select>
          ) : null}
          <Select
            placeholder="所属班级"
            allowClear
            showSearch
            optionFilterProp="label"
            style={{ width: 160 }}
            value={filterClassId}
            onChange={(v) => {
              setFilterClassId(v);
            }}
            options={classOptions.map((item) => ({
              value: item.id,
              label: item.code ? `${item.name}（${item.code}）` : item.name,
            }))}
          />
          <Select
            placeholder="所属老师"
            allowClear
            showSearch
            optionFilterProp="label"
            style={{ width: 160 }}
            value={filterTeacherId}
            onChange={(v) => {
              setFilterTeacherId(v);
            }}
            options={teacherOptions.map((item) => ({
              value: item.id,
              label: item.name === item.username ? item.name : `${item.name}（${item.username}）`,
            }))}
          />
          <Button
            type={showArchived ? 'primary' : 'default'}
            onClick={() => setShowArchived(!showArchived)}
          >
            {showArchived
              ? '隐藏已归档'
              : `显示已归档${archivedCount > 0 ? ` (${archivedCount})` : ''}`}
          </Button>
        </Space>
        <Space wrap className="responsive-toolbar__group">
          <Popconfirm
            title={`确定批量归档选中的 ${selectedRowKeys.length} 名学生？（数据保留，可恢复）`}
            onConfirm={handleBatchDelete}
            okText="归档"
            cancelText="取消"
            disabled={selectedRowKeys.length === 0}
          >
            <PermissionButton
              permission="student:delete"
              danger
              icon={<InboxOutlined />}
              disabled={selectedRowKeys.length === 0}
              loading={batchLoading}
            >
              批量归档
            </PermissionButton>
          </Popconfirm>
          <PermissionButton
            permission="student:create"
            type="primary"
            icon={<PlusOutlined />}
            onClick={() => {
              setEditing(null);
              form.resetFields();
              const host = organizations.find((organization) => organization.isHost);
              if (host) form.setFieldValue('organizationId', host.id);
              setModalOpen(true);
            }}
          >
            添加学生
          </PermissionButton>
          {hasPermission('student:import') ? (
            <>
              <Upload
                accept=".xlsx,.xls"
                showUploadList={false}
                customRequest={handleCreateStudentsImport}
              >
                <Button icon={<UploadOutlined />}>导入Excel</Button>
              </Upload>
              <Upload
                accept=".xlsx,.xls"
                showUploadList={false}
                customRequest={handleUpdateExistingStudentsImport}
              >
                <Button icon={<SwapOutlined />}>更新已有学生资料</Button>
              </Upload>
            </>
          ) : null}
          <PermissionButton
            permission="sync:read"
            icon={<CloudUploadOutlined />}
            onClick={() => setJinshujuOpen(true)}
          >
            同步金数据
          </PermissionButton>
          <PermissionButton
            permission="student:view"
            icon={<DownloadOutlined />}
            onClick={handleDownloadTemplate}
          >
            下载模板
          </PermissionButton>
          <PermissionButton
            permission="student:export"
            icon={<ExportOutlined />}
            onClick={handleExport}
          >
            导出名单
          </PermissionButton>
        </Space>
      </div>
      <Alert
        showIcon
        type="warning"
        style={{ marginBottom: 12 }}
        message={
          <span>
            <strong>更新已有学生资料：</strong>先按手机号、再按身份证号匹配；Excel
            中填写的非空字段会覆盖原资料，未匹配的学生不会新增。请确认姓名、手机号、身份证号、所属机构和联系人等内容无误。
          </span>
        }
      />
      <Table
        columns={columns}
        dataSource={data}
        rowKey="id"
        loading={loading}
        locale={{ emptyText: <Empty description="暂无数据" /> }}
        scroll={{ x: 1410 }}
        pagination={{
          defaultPageSize: 15,
          showSizeChanger: true,
          pageSizeOptions: [15, 30, 50, 100],
          showTotal: (total) => `共 ${total} 人`,
        }}
        rowClassName={(record: any) => (record.status === 'archived' ? 'archived-row' : '')}
        rowSelection={{
          selectedRowKeys,
          onChange: (keys) => setSelectedRowKeys(keys as number[]),
          getCheckboxProps: (record: any) => ({ disabled: record.status === 'archived' }),
        }}
        expandable={{
          rowExpandable: () => true,
          expandedRowRender: (record) => {
            const enrollments = enrollmentData[record.id];
            if (!enrollments) return null;
            if (enrollments.length < 2) {
              return (
                <div style={{ padding: 8, color: '#999', fontSize: 13 }}>
                  当前仅 {enrollments.length} 个班型，无可对比数据
                </div>
              );
            }
            return (
              <Card title="多班型对比" size="small" style={{ margin: '8px 0' }}>
                <Row gutter={[16, 16]}>
                  {enrollments.map((enr, idx) => (
                    <Col xs={24} md={12} key={enr.classId}>
                      <Card
                        size="small"
                        title={enr.classType || `班型 ${idx + 1}`}
                        style={{ background: idx === 0 ? '#f0f5ff' : '#f6ffed' }}
                      >
                        <Descriptions column={1} size="small">
                          <Descriptions.Item label="班级">{enr.className || '-'}</Descriptions.Item>
                          <Descriptions.Item label="开班日期">
                            {enr.startDate || enr.joinDate || '-'}
                          </Descriptions.Item>
                          <Descriptions.Item label="结课日期">
                            {enr.endDate || enr.leaveDate || '-'}
                          </Descriptions.Item>
                          <Descriptions.Item label="状态">
                            <Tag color={enr.status === 'active' ? 'green' : 'default'}>
                              {enr.status || '-'}
                            </Tag>
                          </Descriptions.Item>
                        </Descriptions>
                      </Card>
                    </Col>
                  ))}
                </Row>
              </Card>
            );
          },
          onExpand: async (expanded, record) => {
            if (expanded && !enrollmentData[record.id]) {
              try {
                const res = await api.get<{ enrollments: EnrollmentInfo[] }>(
                  `/students/${record.id}/compare-classes`,
                );
                setEnrollmentData((prev) => ({ ...prev, [record.id]: res.enrollments }));
              } catch {
                setEnrollmentData((prev) => ({ ...prev, [record.id]: [] }));
              }
            }
          },
        }}
      />
      <style>{`.archived-row { opacity: 0.6; background: #fafafa !important; }`}</style>
      <Modal
        title={editing ? '编辑学生' : '添加学生'}
        className="student-form-modal"
        width={720}
        open={modalOpen}
        onOk={handleSave}
        onCancel={() => {
          setModalOpen(false);
          setEditing(null);
        }}
        okText="保存"
        confirmLoading={saving}
      >
        <Form form={form} layout="vertical" className="student-form-grid">
          <Form.Item name="name" label="姓名" rules={[{ required: true }]}>
            <Input />
          </Form.Item>
          <Form.Item name="studentNo" label="学号">
            <Input placeholder="学生的学号" />
          </Form.Item>
          <Form.Item name="gender" label="性别">
            <Select
              allowClear
              options={[
                { value: '男', label: '男' },
                { value: '女', label: '女' },
              ]}
            />
          </Form.Item>
          <Form.Item name="phone" label="电话">
            <Input />
          </Form.Item>
          <Form.Item name="idNumber" label="身份证">
            <Input />
          </Form.Item>
          <Form.Item name="ethnicity" label="民族">
            <Input placeholder="如：汉族" />
          </Form.Item>
          <Form.Item name="emergencyContact" label="紧急联系人">
            <Input />
          </Form.Item>
          <Form.Item name="emergencyPhone" label="紧急联系人电话">
            <Input />
          </Form.Item>
          {canChooseOrganization ? (
            <Form.Item
              name="organizationId"
              label="所属机构"
              rules={[{ required: true, message: '请选择所属机构' }]}
            >
              <Select
                showSearch
                optionFilterProp="label"
                placeholder="选择所属机构"
                options={organizations.map(
                  (organization: { id: number; name: string; isHost?: boolean }) => ({
                    value: organization.id,
                    label: organization.isHost
                      ? `${organization.name}（本机构）`
                      : organization.name,
                  }),
                )}
              />
            </Form.Item>
          ) : null}
          <Form.Item name="supervisor" label="负责人/班主任">
            <Input />
          </Form.Item>
          {editing && (
            <Form.Item name="status" label="状态">
              <Select
                options={[
                  { value: 'active', label: '在读' },
                  { value: 'graduated', label: '已毕业' },
                  { value: 'withdrawn', label: '已退训' },
                ]}
              />
            </Form.Item>
          )}
        </Form>
      </Modal>

      {hasPermission('sync:read') ? (
        <JinshujuMatchModal
          open={jinshujuOpen}
          onClose={() => setJinshujuOpen(false)}
          onApplied={() => {
            setJinshujuOpen(false);
            fetchData();
          }}
        />
      ) : null}
      <Drawer
        title={null}
        open={drawerOpen}
        onClose={() => {
          setDrawerOpen(false);
        }}
        size={720}
      >
        {drawerStudentId && (
          <StudentProfileContent
            studentId={drawerStudentId}
            inDrawer
            onClose={() => {
              setDrawerOpen(false);
            }}
          />
        )}
      </Drawer>
    </div>
  );
};

export default StudentsPage;
