import React, { useEffect, useState, useMemo, useCallback } from 'react';
import {
  Table,
  Button,
  Modal,
  Form,
  Select,
  DatePicker,
  InputNumber,
  Input,
  Space,
  Tag,
  Tabs,
  Popconfirm,
  Upload,
  Empty,
} from 'antd';
import {
  PlusOutlined,
  InboxOutlined,
  EditOutlined,
  UploadOutlined,
  DownloadOutlined,
  ExportOutlined,
} from '@ant-design/icons';
import dayjs from 'dayjs';
import api from '../../api';
import PermissionButton from '../../components/PermissionButton';
import EditableCell from '../../components/EditableCell';
import { downloadBlob } from '../../utils/download';
import { message } from '../../ui/app-message';

const { RangePicker } = DatePicker;

const isFormValidationError = (error: unknown) =>
  typeof error === 'object' &&
  error !== null &&
  Array.isArray((error as { errorFields?: unknown }).errorFields);

const ExpensesPage: React.FC = () => {
  const [roomExpenses, setRoomExpenses] = useState<any[]>([]);
  const [personalExpenses, setPersonalExpenses] = useState<any[]>([]);
  const [rooms, setRooms] = useState<any[]>([]);
  const [students, setStudents] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const [roomModal, setRoomModal] = useState(false);
  const [personalModal, setPersonalModal] = useState(false);
  const [utilityModal, setUtilityModal] = useState(false);
  const [editingRoom, setEditingRoom] = useState<any>(null);
  const [editingPersonal, setEditingPersonal] = useState<any>(null);
  const [roomForm] = Form.useForm();
  const [personalForm] = Form.useForm();
  const [utilityForm] = Form.useForm();
  const [roomSearch, setRoomSearch] = useState('');
  const [roomTypeFilter, setRoomTypeFilter] = useState<string | undefined>(undefined);
  const [personalSearch, setPersonalSearch] = useState('');
  const [personalTypeFilter, setPersonalTypeFilter] = useState<string | undefined>(undefined);
  const [selectedRoomKeys, setSelectedRoomKeys] = useState<number[]>([]);
  const [selectedPersonalKeys, setSelectedPersonalKeys] = useState<number[]>([]);
  const [saving, setSaving] = useState(false);
  const [batchLoading, setBatchLoading] = useState(false);

  // Dynamic expense type options from API
  const [typeOptions, setTypeOptions] = useState<{ value: string; label: string }[]>([]);
  const [personalTypeOptions, setPersonalTypeOptions] = useState<
    { value: string; label: string }[]
  >([]);
  const [typeMap, setTypeMap] = useState<Record<string, string>>({});

  useEffect(() => {
    api
      .get<Array<{ code: string; name: string; category: string }>>('/expense-types')
      .then((types) => {
        const roomTypes: { value: string; label: string }[] = [];
        const personalTypes: { value: string; label: string }[] = [];
        const map: Record<string, string> = {};
        for (const t of types) {
          map[t.code] = t.name;
          if (t.category === 'room' || t.category === 'both') {
            roomTypes.push({ value: t.code, label: t.name });
          }
          if (t.category === 'personal' || t.category === 'both') {
            personalTypes.push({ value: t.code, label: t.name });
          }
        }
        setTypeOptions(roomTypes);
        setPersonalTypeOptions(personalTypes);
        setTypeMap(map);
      })
      .catch(() => {});
  }, []);

  const handleBatchDeleteRoom = async () => {
    if (batchLoading) return;
    setBatchLoading(true);
    try {
      const res: any = await api.post('/expenses/room/batch-delete', { ids: selectedRoomKeys });
      message.success(res?.message || `已归档 ${selectedRoomKeys.length} 条`);
      setSelectedRoomKeys([]);
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '批量归档失败');
    } finally {
      setBatchLoading(false);
    }
  };

  const handleBatchDeletePersonal = async () => {
    if (batchLoading) return;
    setBatchLoading(true);
    try {
      const res: any = await api.post('/expenses/personal/batch-delete', {
        ids: selectedPersonalKeys,
      });
      message.success(res?.message || `已归档 ${selectedPersonalKeys.length} 条`);
      setSelectedPersonalKeys([]);
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '批量归档失败');
    } finally {
      setBatchLoading(false);
    }
  };

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const [re, pe, lookups]: any[] = await Promise.all([
        api.get('/expenses/room'),
        api.get('/expenses/personal'),
        api.get('/expenses/lookups').catch(() => ({ rooms: [], students: [] })),
      ]);
      setRoomExpenses(re);
      setPersonalExpenses(pe);
      setRooms(lookups.rooms || []);
      setStudents(lookups.students || []);
    } catch (e: any) {
      message.error(e?.message || '加载失败，请稍后重试');
    }
    setLoading(false);
  }, []);

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

  const filteredRoomExpenses = useMemo(() => {
    return roomExpenses.filter((r: any) => {
      if (roomSearch) {
        const s = roomSearch.toLowerCase();
        if (!r.room?.roomNumber?.toLowerCase().includes(s)) return false;
      }
      if (roomTypeFilter && r.expenseType !== roomTypeFilter) return false;
      return true;
    });
  }, [roomExpenses, roomSearch, roomTypeFilter]);

  const filteredPersonalExpenses = useMemo(() => {
    return personalExpenses.filter((p: any) => {
      if (personalSearch) {
        const s = personalSearch.toLowerCase();
        if (!p.student?.name?.toLowerCase().includes(s)) return false;
      }
      if (personalTypeFilter && p.expenseType !== personalTypeFilter) return false;
      return true;
    });
  }, [personalExpenses, personalSearch, personalTypeFilter]);

  const handleRoomExpense = async () => {
    setSaving(true);
    try {
      const values = await roomForm.validateFields();
      const payload = {
        roomId: values.roomId,
        expenseType: values.expenseType,
        amount: values.amount,
        periodStart: values.period[0].format('YYYY-MM-DD'),
        periodEnd: values.period[1].format('YYYY-MM-DD'),
        description: values.description,
      };
      if (editingRoom) {
        await api.put(`/expenses/room/${editingRoom.id}`, payload);
        message.success('更新成功');
      } else {
        await api.post('/expenses/room', payload);
        message.success('录入成功');
      }
      setRoomModal(false);
      setEditingRoom(null);
      roomForm.resetFields();
      fetchData();
    } catch (e: any) {
      if (!isFormValidationError(e)) {
        message.error(e?.message || '操作失败');
      }
    } finally {
      setSaving(false);
    }
  };

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

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

  const handleStudentUtility = async () => {
    const values = await utilityForm.validateFields();
    setSaving(true);
    try {
      const result: any = await api.post('/expenses/student-utility', {
        studentId: values.studentId,
        expenseType: values.expenseType,
        amount: values.amount,
        periodStart: values.period[0].format('YYYY-MM-DD'),
        periodEnd: values.period[1].format('YYYY-MM-DD'),
        description: values.description,
      });
      const bill = result.bill;
      message.success(
        `账单已生成，已从余额扣除 ¥${Number(bill.paidAmount || 0).toFixed(2)}，待补缴 ¥${Number(bill.outstandingAmount || 0).toFixed(2)}`,
      );
      setUtilityModal(false);
      utilityForm.resetFields();
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '水电费出账失败');
    } finally {
      setSaving(false);
    }
  };

  const handlePersonalExpense = async () => {
    setSaving(true);
    try {
      const values = await personalForm.validateFields();
      const payload = {
        studentId: values.studentId,
        roomId: values.roomId,
        expenseType: values.expenseType,
        amount: values.amount,
        expenseDate: values.expenseDate.format('YYYY-MM-DD'),
        description: values.description,
      };
      if (editingPersonal) {
        await api.put(`/expenses/personal/${editingPersonal.id}`, payload);
        message.success('更新成功');
      } else {
        await api.post('/expenses/personal', payload);
        message.success('录入成功');
      }
      setPersonalModal(false);
      setEditingPersonal(null);
      personalForm.resetFields();
      fetchData();
    } catch (e: any) {
      if (!isFormValidationError(e)) {
        message.error(e?.message || '操作失败');
      }
    } finally {
      setSaving(false);
    }
  };

  const roomColumns = useMemo(
    () => [
      {
        title: '宿舍',
        width: 120,
        render: (_: any, r: any) => (
          <EditableCell
            value={r.roomId}
            editor="select"
            options={rooms.map((item) => ({ value: item.id, label: item.roomNumber }))}
            permission="expense:edit"
            required
            onSave={(next) => saveRoomCell(r, 'roomId', next)}
          >
            {r.room?.roomNumber || '-'}
          </EditableCell>
        ),
      },
      {
        title: '费用类型',
        width: 100,
        dataIndex: 'expenseType',
        render: (v: string, r: any) => (
          <EditableCell
            value={v}
            editor="select"
            options={typeOptions}
            permission="expense:edit"
            required
            onSave={(next) => saveRoomCell(r, 'expenseType', next)}
          >
            <Tag>{typeMap[v] || v}</Tag>
          </EditableCell>
        ),
      },
      {
        title: '金额',
        dataIndex: 'amount',
        width: 100,
        render: (v: number, r: any) => (
          <EditableCell
            value={v}
            editor="money"
            min={0.01}
            permission="expense:edit"
            required
            onSave={(next) => saveRoomCell(r, 'amount', next)}
          >{`¥${Number(v).toFixed(2)}`}</EditableCell>
        ),
      },
      {
        title: '账单周期',
        width: 200,
        render: (_: any, r: any) => (
          <EditableCell
            value={[r.periodStart, r.periodEnd]}
            editor="date-range"
            permission="expense:edit"
            required
            onSave={async (next) => {
              const [periodStart, periodEnd] = next as unknown as [string, string];
              await api.put(`/expenses/room/${r.id}`, { periodStart, periodEnd });
              message.success('已保存');
              await fetchData();
            }}
          >{`${r.periodStart} ~ ${r.periodEnd}`}</EditableCell>
        ),
      },
      {
        title: '说明',
        dataIndex: 'description',
        width: 150,
        render: (v: string, r: any) => (
          <EditableCell
            value={v}
            editor="textarea"
            permission="expense:edit"
            onSave={(next) => saveRoomCell(r, 'description', next)}
          >
            {v || '-'}
          </EditableCell>
        ),
      },
      {
        title: '录入时间',
        width: 160,
        dataIndex: 'createdAt',
        render: (v: string) => dayjs(v).format('YYYY-MM-DD HH:mm'),
      },
      {
        title: '操作',
        width: 120,
        render: (_: any, record: any) => (
          <Space>
            <PermissionButton
              permission="expense:edit"
              size="small"
              icon={<EditOutlined />}
              onClick={() => {
                setEditingRoom(record);
                roomForm.setFieldsValue({
                  roomId: record.roomId,
                  expenseType: record.expenseType,
                  amount: Number(record.amount),
                  period: [dayjs(record.periodStart), dayjs(record.periodEnd)],
                  description: record.description,
                });
                setRoomModal(true);
              }}
            >
              编辑
            </PermissionButton>
            <Popconfirm
              title="确定归档？"
              onConfirm={async () => {
                await api.delete(`/expenses/room/${record.id}`);
                message.success('归档成功');
                fetchData();
              }}
            >
              <PermissionButton
                permission="expense:delete"
                size="small"
                danger
                icon={<InboxOutlined />}
              >
                归档
              </PermissionButton>
            </Popconfirm>
          </Space>
        ),
      },
    ],
    [rooms, typeOptions, typeMap, saveRoomCell, roomForm, fetchData],
  );

  const personalColumns = useMemo(
    () => [
      {
        title: '学生',
        width: 120,
        render: (_: any, r: any) => (
          <EditableCell
            value={r.studentId}
            editor="select"
            options={students.map((item) => ({ value: item.id, label: item.name }))}
            permission="expense:edit"
            required
            onSave={(next) => savePersonalCell(r, 'studentId', next)}
          >
            {r.student?.name || '-'}
          </EditableCell>
        ),
      },
      {
        title: '费用类型',
        width: 100,
        dataIndex: 'expenseType',
        render: (v: string, r: any) => (
          <EditableCell
            value={v}
            editor="select"
            options={personalTypeOptions}
            permission="expense:edit"
            required
            onSave={(next) => savePersonalCell(r, 'expenseType', next)}
          >
            <Tag color="orange">{typeMap[v] || v}</Tag>
          </EditableCell>
        ),
      },
      {
        title: '金额',
        dataIndex: 'amount',
        render: (v: number, r: any) => (
          <EditableCell
            value={v}
            editor="money"
            min={0.01}
            permission="expense:edit"
            required
            onSave={(next) => savePersonalCell(r, 'amount', next)}
          >{`¥${Number(v).toFixed(2)}`}</EditableCell>
        ),
      },
      {
        title: '日期',
        dataIndex: 'expenseDate',
        width: 110,
        render: (v: string, r: any) => (
          <EditableCell
            value={v}
            editor="date"
            permission="expense:edit"
            required
            onSave={(next) => savePersonalCell(r, 'expenseDate', next)}
          >
            {v}
          </EditableCell>
        ),
      },
      {
        title: '说明',
        dataIndex: 'description',
        width: 150,
        render: (v: string, r: any) => (
          <EditableCell
            value={v}
            editor="textarea"
            permission="expense:edit"
            onSave={(next) => savePersonalCell(r, 'description', next)}
          >
            {v || '-'}
          </EditableCell>
        ),
      },
      {
        title: '操作',
        width: 120,
        render: (_: any, record: any) => (
          <Space>
            <PermissionButton
              permission="expense:edit"
              size="small"
              icon={<EditOutlined />}
              onClick={() => {
                setEditingPersonal(record);
                personalForm.setFieldsValue({
                  studentId: record.studentId,
                  roomId: record.roomId,
                  expenseType: record.expenseType,
                  amount: Number(record.amount),
                  expenseDate: dayjs(record.expenseDate),
                  description: record.description,
                });
                setPersonalModal(true);
              }}
            >
              编辑
            </PermissionButton>
            <Popconfirm
              title="确定归档？"
              onConfirm={async () => {
                await api.delete(`/expenses/personal/${record.id}`);
                message.success('归档成功');
                fetchData();
              }}
            >
              <PermissionButton
                permission="expense:delete"
                size="small"
                danger
                icon={<InboxOutlined />}
              >
                归档
              </PermissionButton>
            </Popconfirm>
          </Space>
        ),
      },
    ],
    [students, personalTypeOptions, typeMap, savePersonalCell, personalForm, fetchData],
  );

  return (
    <div>
      <Tabs
        items={[
          {
            key: 'room',
            label: '宿舍费用',
            children: (
              <>
                <div
                  style={{
                    marginBottom: 16,
                    display: 'flex',
                    justifyContent: 'space-between',
                    flexWrap: 'wrap',
                    gap: 8,
                  }}
                >
                  <Space wrap>
                    <Input.Search
                      placeholder="搜索宿舍号"
                      allowClear
                      style={{ width: 160 }}
                      onSearch={(v) => setRoomSearch(v)}
                      onChange={(e) => {
                        if (!e.target.value) setRoomSearch('');
                      }}
                    />
                    <Select
                      placeholder="费用类型"
                      allowClear
                      style={{ width: 120 }}
                      value={roomTypeFilter}
                      onChange={(v) => setRoomTypeFilter(v)}
                      options={typeOptions}
                    />
                    <Upload
                      accept=".xlsx,.xls"
                      showUploadList={false}
                      customRequest={async ({ file, onSuccess, onError }: any) => {
                        const formData = new FormData();
                        formData.append('file', file);
                        try {
                          const res: any = await api.post('/expenses/utility/import', formData);
                          if (res.errors?.length > 0) {
                            Modal.warning({
                              title: res.message,
                              content: res.errors.join('\n'),
                              width: 500,
                            });
                          } else {
                            message.success(res.message);
                          }
                          onSuccess?.(res);
                          fetchData();
                        } catch (e: any) {
                          message.error(e?.message || '导入失败');
                          onError?.(e);
                        }
                      }}
                    >
                      <Button icon={<UploadOutlined />}>导入水电费Excel</Button>
                    </Upload>
                    <PermissionButton
                      permission="expense:view"
                      icon={<DownloadOutlined />}
                      onClick={() => {
                        downloadBlob('/expenses/utility/template', '水电费导入模板.xlsx').catch(
                          () => message.error('下载失败'),
                        );
                      }}
                    >
                      下载水电费模板
                    </PermissionButton>
                  </Space>
                  <Space>
                    <Popconfirm
                      title={`确定归档选中的 ${selectedRoomKeys.length} 条费用？`}
                      onConfirm={handleBatchDeleteRoom}
                      okText="归档"
                      cancelText="取消"
                      disabled={selectedRoomKeys.length === 0}
                    >
                      <PermissionButton
                        permission="expense:delete"
                        danger
                        icon={<InboxOutlined />}
                        disabled={selectedRoomKeys.length === 0}
                      >
                        批量归档
                      </PermissionButton>
                    </Popconfirm>
                    <PermissionButton
                      permission="expense:create"
                      type="primary"
                      icon={<PlusOutlined />}
                      onClick={() => {
                        setEditingRoom(null);
                        roomForm.resetFields();
                        setRoomModal(true);
                      }}
                    >
                      录入宿舍费用
                    </PermissionButton>
                  </Space>
                </div>
                <Table
                  columns={roomColumns}
                  dataSource={filteredRoomExpenses}
                  rowKey="id"
                  loading={loading}
                  scroll={{ x: 1200 }}
                  pagination={{
                    defaultPageSize: 15,
                    showSizeChanger: true,
                    pageSizeOptions: [15, 30, 50, 100],
                    showTotal: (total) => `共 ${total} 条`,
                  }}
                  locale={{ emptyText: <Empty description="暂无数据" /> }}
                  rowSelection={{
                    selectedRowKeys: selectedRoomKeys,
                    onChange: (keys) => setSelectedRoomKeys(keys as number[]),
                  }}
                />
              </>
            ),
          },
          {
            key: 'personal',
            label: '个人附加费',
            children: (
              <>
                <div
                  style={{
                    marginBottom: 16,
                    display: 'flex',
                    justifyContent: 'space-between',
                    flexWrap: 'wrap',
                    gap: 8,
                  }}
                >
                  <Space wrap>
                    <Input.Search
                      placeholder="搜索学生姓名"
                      allowClear
                      style={{ width: 160 }}
                      onSearch={(v) => setPersonalSearch(v)}
                      onChange={(e) => {
                        if (!e.target.value) setPersonalSearch('');
                      }}
                    />
                    <Select
                      placeholder="费用类型"
                      allowClear
                      style={{ width: 120 }}
                      value={personalTypeFilter}
                      onChange={(v) => setPersonalTypeFilter(v)}
                      options={personalTypeOptions}
                    />
                    <Upload
                      accept=".xlsx,.xls"
                      showUploadList={false}
                      customRequest={async ({ file, onSuccess, onError }: any) => {
                        try {
                          const formData = new FormData();
                          formData.append('file', file);
                          const res: any = await api.post('/expenses/personal/import', formData);
                          message.success(res.message || '导入完成');
                          if (res.errors?.length)
                            res.errors.forEach((e: string) => message.warning(e));
                          fetchData();
                          onSuccess?.(res);
                        } catch (e: any) {
                          message.error(e?.message || '导入失败');
                          onError?.(e);
                        }
                      }}
                    >
                      <Button icon={<UploadOutlined />}>导入个人附加费</Button>
                    </Upload>
                    <PermissionButton
                      permission="expense:view"
                      icon={<DownloadOutlined />}
                      onClick={() => {
                        downloadBlob(
                          '/expenses/personal/template',
                          '个人附加费导入模板.xlsx',
                        ).catch(() => message.error('下载失败'));
                      }}
                    >
                      下载模板
                    </PermissionButton>
                    <PermissionButton
                      permission="expense:view"
                      icon={<ExportOutlined />}
                      onClick={() => {
                        downloadBlob('/expenses/personal/export', '个人附加费导出.xlsx').catch(() =>
                          message.error('导出失败'),
                        );
                      }}
                    >
                      导出
                    </PermissionButton>
                  </Space>
                  <Space>
                    <Popconfirm
                      title={`确定归档选中的 ${selectedPersonalKeys.length} 条个人费用？`}
                      onConfirm={handleBatchDeletePersonal}
                      okText="归档"
                      cancelText="取消"
                      disabled={selectedPersonalKeys.length === 0}
                    >
                      <PermissionButton
                        permission="expense:delete"
                        danger
                        icon={<InboxOutlined />}
                        disabled={selectedPersonalKeys.length === 0}
                      >
                        批量归档
                      </PermissionButton>
                    </Popconfirm>
                    <PermissionButton
                      permission="expense:create"
                      icon={<PlusOutlined />}
                      onClick={() => {
                        utilityForm.resetFields();
                        setUtilityModal(true);
                      }}
                    >
                      添加学生水电费
                    </PermissionButton>
                    <PermissionButton
                      permission="expense:create"
                      type="primary"
                      icon={<PlusOutlined />}
                      onClick={() => {
                        setEditingPersonal(null);
                        personalForm.resetFields();
                        setPersonalModal(true);
                      }}
                    >
                      录入个人费用
                    </PermissionButton>
                  </Space>
                </div>
                <Table
                  columns={personalColumns}
                  dataSource={filteredPersonalExpenses}
                  rowKey="id"
                  loading={loading}
                  scroll={{ x: 1200 }}
                  pagination={{
                    defaultPageSize: 15,
                    showSizeChanger: true,
                    pageSizeOptions: [15, 30, 50, 100],
                    showTotal: (total) => `共 ${total} 条`,
                  }}
                  locale={{ emptyText: <Empty description="暂无数据" /> }}
                  rowSelection={{
                    selectedRowKeys: selectedPersonalKeys,
                    onChange: (keys) => setSelectedPersonalKeys(keys as number[]),
                  }}
                />
              </>
            ),
          },
        ]}
      />

      <Modal
        title={editingRoom ? '编辑宿舍费用' : '录入宿舍费用'}
        open={roomModal}
        onOk={handleRoomExpense}
        onCancel={() => {
          setRoomModal(false);
          setEditingRoom(null);
        }}
        okText={editingRoom ? '保存' : '确认录入'}
        confirmLoading={saving}
      >
        <Form form={roomForm} layout="vertical">
          <Form.Item name="roomId" label="宿舍" rules={[{ required: true }]}>
            <Select
              showSearch
              optionFilterProp="label"
              options={rooms.map((r: any) => ({
                value: r.id,
                label: `${r.roomNumber} (${r.building || ''})`,
              }))}
            />
          </Form.Item>
          <Form.Item name="expenseType" label="费用类型" rules={[{ required: true }]}>
            <Select options={typeOptions} />
          </Form.Item>
          <Form.Item name="amount" label="金额（元）" rules={[{ required: true }]}>
            <InputNumber min={0.01} precision={2} style={{ width: '100%' }} />
          </Form.Item>
          <Form.Item name="period" label="账单周期" rules={[{ required: true }]}>
            <RangePicker
              style={{ width: '100%' }}
              placeholder={['开始日期', '结束日期']}
              format="YYYY-MM-DD"
            />
          </Form.Item>
          <Form.Item name="description" label="说明">
            <Input.TextArea rows={2} />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        title="添加学生水电费并立即出账"
        open={utilityModal}
        onOk={handleStudentUtility}
        onCancel={() => setUtilityModal(false)}
        okText="生成账单并扣余额"
        confirmLoading={saving}
      >
        <Form form={utilityForm} layout="vertical">
          <Form.Item name="studentId" label="学生" rules={[{ required: true }]}>
            <Select
              showSearch
              optionFilterProp="label"
              options={students.map((student: any) => ({
                value: student.id,
                label: `${student.name} (${student.studentNo || `#${student.id}`})`,
              }))}
            />
          </Form.Item>
          <Form.Item name="expenseType" label="费用类型" rules={[{ required: true }]}>
            <Select
              options={[
                { value: 'water', label: '水费' },
                { value: 'electricity', label: '电费' },
              ]}
            />
          </Form.Item>
          <Form.Item name="amount" label="金额（元）" rules={[{ required: true }]}>
            <InputNumber min={0.01} precision={2} style={{ width: '100%' }} />
          </Form.Item>
          <Form.Item name="period" label="账单周期" rules={[{ required: true }]}>
            <RangePicker style={{ width: '100%' }} format="YYYY-MM-DD" />
          </Form.Item>
          <Form.Item name="description" label="说明">
            <Input.TextArea rows={2} maxLength={300} />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        title={editingPersonal ? '编辑个人费用' : '录入个人附加费'}
        open={personalModal}
        onOk={handlePersonalExpense}
        onCancel={() => {
          setPersonalModal(false);
          setEditingPersonal(null);
        }}
        okText={editingPersonal ? '保存' : '确认录入'}
        confirmLoading={saving}
      >
        <Form form={personalForm} layout="vertical">
          <Form.Item name="studentId" label="学生" rules={[{ required: true }]}>
            <Select
              showSearch
              optionFilterProp="label"
              options={students.map((s: any) => ({ value: s.id, label: s.name }))}
            />
          </Form.Item>
          <Form.Item name="roomId" label="关联宿舍">
            <Select
              allowClear
              showSearch
              optionFilterProp="label"
              options={rooms.map((r: any) => ({ value: r.id, label: r.roomNumber }))}
            />
          </Form.Item>
          <Form.Item name="expenseType" label="费用类型" rules={[{ required: true }]}>
            <Select options={personalTypeOptions} />
          </Form.Item>
          <Form.Item name="amount" label="金额（元）" rules={[{ required: true }]}>
            <InputNumber min={0.01} precision={2} style={{ width: '100%' }} />
          </Form.Item>
          <Form.Item name="expenseDate" label="费用日期" rules={[{ required: true }]}>
            <DatePicker style={{ width: '100%' }} placeholder="选择日期" format="YYYY-MM-DD" />
          </Form.Item>
          <Form.Item name="description" label="说明">
            <Input.TextArea rows={2} />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
};

export default ExpensesPage;
