import React, { useEffect, useState, useMemo, useCallback } from 'react';
import {
  Table,
  Button,
  Modal,
  Form,
  Select,
  DatePicker,
  Input,
  InputNumber,
  Space,
  Tag,
  Popconfirm,
  Upload,
  Switch,
  Tooltip,
  Empty,
  Alert,
} from 'antd';
import {
  PlusOutlined,
  SwapOutlined,
  LogoutOutlined,
  DeleteOutlined,
  UploadOutlined,
  DownloadOutlined,
  ExportOutlined,
} from '@ant-design/icons';
import dayjs from 'dayjs';
import api from '../../api';
import { downloadBlob } from '../../utils/download';
import { maskPhone, maskIdNumber } from '../../utils/sensitive';
import PermissionButton from '../../components/PermissionButton';
import { message } from '../../ui/app-message';
import { buildTransferPayload } from './occupancy-form';

const { RangePicker } = DatePicker;

const OccupanciesPage: React.FC = () => {
  const [data, setData] = useState<any[]>([]);
  const [students, setStudents] = useState<any[]>([]);
  const [rooms, setRooms] = useState<any[]>([]);
  const [organizations, setOrganizations] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const [checkInModal, setCheckInModal] = useState(false);
  const [checkOutModal, setCheckOutModal] = useState<any>(null);
  const [transferModal, setTransferModal] = useState<any>(null);
  const [showActive, setShowActive] = useState(true);
  const [autoDeposit, setAutoDeposit] = useState(true);
  const [depositAmount, setDepositAmount] = useState(500);
  const [searchText, setSearchText] = useState('');
  const [dateRange, setDateRange] = useState<[dayjs.Dayjs | null, dayjs.Dayjs | null] | null>(null);
  const [batchCheckOutModal, setBatchCheckOutModal] = useState(false);
  const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
  const [saving, setSaving] = useState(false);
  const [batchLoading, setBatchLoading] = useState(false);
  const [checkInForm] = Form.useForm();
  const [checkOutForm] = Form.useForm();
  const [transferForm] = Form.useForm();
  const [batchCheckOutForm] = Form.useForm();
  const [availableBeds, setAvailableBeds] = useState<any[]>([]);
  const [availableLockers, setAvailableLockers] = useState<any[]>([]);
  const [transferAvailableBeds, setTransferAvailableBeds] = useState<any[]>([]);
  const [transferAvailableLockers, setTransferAvailableLockers] = useState<any[]>([]);

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const [occRes, stuRes, rmRes, tnRes] = (await Promise.allSettled([
        api.get('/occupancies', { params: { active: showActive ? 'true' : undefined, dateFrom: dateRange?.[0]?.format('YYYY-MM-DD'), dateTo: dateRange?.[1]?.format('YYYY-MM-DD') } }),
        api.get('/students/basic-lookups'),
        api.get('/rooms/overview'),
        api.get('/organizations'),
      ])) as PromiseSettledResult<any>[];
      const labels = ['入住数据', '学生列表', '房间列表', '机构列表'];
      [occRes, stuRes, rmRes, tnRes].forEach((res, i) => {
        if (res.status === 'rejected') {
          message.warning(`${labels[i]}加载失败`);
        }
      });
      setData(occRes.status === 'fulfilled' ? occRes.value : []);
      setStudents(stuRes.status === 'fulfilled' ? stuRes.value : []);
      setRooms(rmRes.status === 'fulfilled' ? rmRes.value : []);
      setOrganizations(tnRes.status === 'fulfilled' ? tnRes.value : []);
    } catch (e) {
      console.error(e);
      message.error('数据加载异常');
    }
    setLoading(false);
  }, [showActive, dateRange]);

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

  const handleRoomChange = async (roomId: number) => {
    checkInForm.setFieldValue('bedId', undefined);
    checkInForm.setFieldValue('lockerId', undefined);
    if (!roomId) {
      setAvailableBeds([]);
      setAvailableLockers([]);
      return;
    }
    try {
      const [beds, lockers] = await Promise.all([
        api.get<any[]>(`/rooms/${roomId}/beds/available`),
        api.get<any[]>(`/rooms/${roomId}/lockers/available`),
      ]);
      setAvailableBeds(beds);
      setAvailableLockers(lockers);
      if (beds.length === 1) checkInForm.setFieldValue('bedId', beds[0].id);
    } catch (e) { console.error(e); }
  };

  const handleTransferRoomChange = async (roomId: number) => {
    transferForm.setFieldValue('newBedId', undefined);
    transferForm.setFieldValue('newLockerId', undefined);
    if (!roomId) {
      setTransferAvailableBeds([]);
      setTransferAvailableLockers([]);
      return;
    }
    try {
      const [beds, lockers] = await Promise.all([
        api.get<any[]>(`/rooms/${roomId}/beds/available`),
        api.get<any[]>(`/rooms/${roomId}/lockers/available`),
      ]);
      setTransferAvailableBeds(beds);
      setTransferAvailableLockers(lockers);
      if (beds.length === 1) transferForm.setFieldValue('newBedId', beds[0].id);
    } catch (e) {
      console.error(e);
      setTransferAvailableBeds([]);
      setTransferAvailableLockers([]);
      message.error('目标宿舍床位和柜子加载失败');
    }
  };

  const filteredData = useMemo(() => {
    if (!searchText) return data;
    const keyword = searchText.toLowerCase();
    return data.filter(
      (r: any) =>
        r.student?.name?.toLowerCase().includes(keyword) ||
        r.room?.roomNumber?.toLowerCase().includes(keyword),
    );
  }, [data, searchText]);

  const handleCheckIn = async () => {
    const values = await checkInForm.validateFields();
    setSaving(true);
    try {
      await api.post('/occupancies/check-in', {
        studentId: values.studentId,
        roomId: values.roomId,
        checkInDate: values.checkInDate.format('YYYY-MM-DD'),
        billingStartDate: values.billingStartDate?.format('YYYY-MM-DD'),
        stayType: values.stayType,
        responsibleOrganizationId: values.responsibleOrganizationId,
        notes: values.notes,
        bedId: values.bedId,
        lockerId: values.lockerId || undefined,
      });
      message.success('入住登记成功');
      setCheckInModal(false);
      checkInForm.resetFields();
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '操作失败');
    } finally {
      setSaving(false);
    }
  };

  const handleCheckOut = async () => {
    const values = await checkOutForm.validateFields();
    setSaving(true);
    try {
      await api.put(`/occupancies/${checkOutModal.id}/check-out`, {
        checkOutDate: values.checkOutDate.format('YYYY-MM-DD'),
        billingEndDate: values.billingEndDate?.format('YYYY-MM-DD'),
        checkOutReason: values.checkOutReason,
      });
      message.success('退宿成功');
      setCheckOutModal(null);
      checkOutForm.resetFields();
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '操作失败');
    } finally {
      setSaving(false);
    }
  };

  const handleTransfer = async () => {
    const values = await transferForm.validateFields();
    setSaving(true);
    try {
      await api.put(
        `/occupancies/${transferModal.id}/transfer`,
        buildTransferPayload(values),
      );
      message.success('换房成功');
      setTransferModal(null);
      transferForm.resetFields();
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '操作失败');
    } finally {
      setSaving(false);
    }
  };

  const handleBatchCheckOut = async () => {
    const values = await batchCheckOutForm.validateFields();
    setBatchLoading(true);
    try {
      const res: any = await api.post('/occupancies/batch-check-out', {
        ids: selectedRowKeys,
        checkOutDate: values.checkOutDate.format('YYYY-MM-DD'),
        billingEndDate: values.billingEndDate?.format('YYYY-MM-DD'),
        checkOutReason: values.checkOutReason,
      });
      message.success(res.message || `已成功退宿 ${res.success} 人`);
      setBatchCheckOutModal(false);
      batchCheckOutForm.resetFields();
      setSelectedRowKeys([]);
      fetchData();
    } catch (e: any) {
      message.error(e?.message || '批量退宿失败');
    } finally {
      setBatchLoading(false);
    }
  };

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

  const columns = useMemo(() => [
    { title: '学生', width: 120, render: (_: any, r: any) => r.student?.name || '-' },
    { title: '宿舍', width: 120, render: (_: any, r: any) => r.room?.roomNumber || '-' },
    { title: '床位', width: 80, render: (_: unknown, r: Record<string, unknown>) => (r.bed as Record<string, string> | undefined)?.bedNumber || '-' },
    { title: '柜子', width: 80, render: (_: unknown, r: Record<string, unknown>) => (r.locker as Record<string, string> | undefined)?.lockerNumber || '-' },
    { title: '入住日期', dataIndex: 'checkInDate', width: 110 },
    { title: '计费起始', dataIndex: 'billingStartDate', width: 110 },
    {
      title: '退宿日期',
      dataIndex: 'checkOutDate',
      width: 110,
      render: (v: any) => v || <Tag color="green">在住</Tag>,
    },
    { title: '计费截止', dataIndex: 'billingEndDate', render: (v: any) => v || '-' },
    { title: '退宿原因', dataIndex: 'checkOutReason', render: (v: any) => v || '-' },
    {
      title: '操作',
      width: 220,
      render: (_: any, record: any) =>
        !record.checkOutDate ? (
          <Space>
            <PermissionButton
              permission="occupancy:checkout"
              size="small"
              icon={<LogoutOutlined />}
              onClick={() => {
                setCheckOutModal(record);
                checkOutForm.setFieldsValue({ checkOutDate: dayjs() });
              }}
            >
              退宿
            </PermissionButton>
            <PermissionButton
              permission="occupancy:transfer"
              size="small"
              icon={<SwapOutlined />}
              onClick={() => {
                setTransferAvailableBeds([]);
                setTransferAvailableLockers([]);
                transferForm.resetFields();
                setTransferModal(record);
                transferForm.setFieldsValue({ transferDate: dayjs() });
              }}
            >
              换房
            </PermissionButton>
          </Space>
        ) : (
          <Space>
            <Tag>已退宿</Tag>
            <Popconfirm
              title="确定删除此记录？"
              onConfirm={async () => {
                try {
                  await api.delete(`/occupancies/${record.id}`);
                  message.success('删除成功');
                  fetchData();
                } catch (e: any) {
                  message.error(e?.message || '删除失败');
                }
              }}
            >
              <PermissionButton permission="occupancy:delete" size="small" danger icon={<DeleteOutlined />}>
                删除
              </PermissionButton>
            </Popconfirm>
          </Space>
        ),
    },
  ], [fetchData, setCheckOutModal, checkOutForm, setTransferModal, transferForm]);

  const rowSelection = useMemo(() => ({
    selectedRowKeys,
    onChange: (keys: any[]) => setSelectedRowKeys(keys),
    // 「在住记录」Tab：禁用已退宿（防止误选用于批量退宿）；「全部记录」Tab：均可选用于批量删除
    getCheckboxProps: (record: any) => (showActive ? { disabled: !!record.checkOutDate } : {}),
  }), [selectedRowKeys, showActive]);

  return (
    <div>
      <Alert
        title="一站式导入"
        description="导入入住名单时会自动创建学生和宿舍，无需单独在「学生管理」或「宿舍管理」中手动添加。后续仅需在此页面处理换房/退宿等日常操作即可。"
        type="info"
        showIcon
        closable
        style={{ marginBottom: 16 }}
      />
      <div
        style={{
          marginBottom: 16,
          display: 'flex',
          justifyContent: 'space-between',
          flexWrap: 'wrap',
          gap: 8,
        }}
      >
        <Space wrap>
          <Button type={showActive ? 'primary' : 'default'} onClick={() => setShowActive(true)}>
            在住记录
          </Button>
          <Button type={!showActive ? 'primary' : 'default'} onClick={() => setShowActive(false)}>
            全部记录
          </Button>
          <Input.Search
            placeholder="搜索学生姓名或房间号"
            onSearch={setSearchText}
            allowClear
            style={{ width: 200 }}
          />
          <RangePicker value={dateRange} onChange={(dates) => { setDateRange(dates ? [dates[0], dates[1]] : null); }} placeholder={['入住开始', '入住结束']} style={{ width: 240 }} />
        </Space>
        <Space wrap>
          <PermissionButton
            permission="occupancy:checkin"
            type="primary"
            icon={<PlusOutlined />}
            onClick={() => {
              checkInForm.resetFields();
              checkInForm.setFieldsValue({ checkInDate: dayjs() });
              setCheckInModal(true);
            }}
          >
            入住登记
          </PermissionButton>
          <Upload
            accept=".xlsx,.xls"
            showUploadList={false}
            customRequest={async ({ file, onSuccess, onError }: any) => {
              const formData = new FormData();
              formData.append('file', file);
              const params = new URLSearchParams();
              if (autoDeposit) {
                params.set('autoDeposit', 'true');
                params.set('depositAmount', String(depositAmount));
              }
              try {
                const res: any = await api.post(
                  `/occupancies/import?${params.toString()}`,
                  formData,
                  { headers: { 'Content-Type': 'multipart/form-data' } },
                );
                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);
              }
            }}
          >
            <Tooltip title="导入时自动创建学生、宿舍和入住记录">
              <Button type="primary" ghost icon={<UploadOutlined />}>
                导入入住名单
              </Button>
            </Tooltip>
          </Upload>
          <PermissionButton
            permission="occupancy:view"
            icon={<DownloadOutlined />}
            onClick={() => {
              downloadBlob('/occupancies/template', '入住名单导入模板.xlsx').catch(() =>
                message.error('下载失败'),
              );
            }}
          >
            下载模板
          </PermissionButton>
          <PermissionButton
            permission="occupancy:view"
            icon={<ExportOutlined />}
            onClick={() => {
              const params = showActive ? '?active=true' : '';
              const filename = showActive ? '在住记录.xlsx' : '全部入住记录.xlsx';
              downloadBlob('/occupancies/export' + params, filename).catch(() =>
                message.error('导出失败'),
              );
            }}
          >
            导出记录
          </PermissionButton>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 13 }}>
            <Switch size="small" checked={autoDeposit} onChange={setAutoDeposit} />
            导入时自动收押金
            {autoDeposit && (
              <Space.Compact>
              <InputNumber
                size="small"
                min={0}
                value={depositAmount}
                onChange={(v) => setDepositAmount(v || 500)}
                style={{ width: 60 }}
              />
              <span
                style={{
                  padding: '0 8px',
                  display: 'flex',
                  alignItems: 'center',
                  border: '1px solid #d9d9d9',
                  backgroundColor: '#fafafa',
                  fontSize: 12,
                }}
              >
                元
              </span>
            </Space.Compact>
            )}
          </span>
        </Space>
      </div>
      {selectedRowKeys.length > 0 && (
        <Alert
          title={
            <span>
              已选 <strong>{selectedRowKeys.length}</strong> 条记录
              {showActive ? (
                <PermissionButton
                  permission="occupancy:checkout"
                  type="primary"
                  size="small"
                  icon={<LogoutOutlined />}
                  onClick={() => {
                    batchCheckOutForm.resetFields();
                    batchCheckOutForm.setFieldsValue({ checkOutDate: dayjs() });
                    setBatchCheckOutModal(true);
                  }}
                  style={{ marginLeft: 12 }}
                  loading={batchLoading}
                >
                  批量退宿
                </PermissionButton>
              ) : (
                <Popconfirm
                  title={`确定删除选中的 ${selectedRowKeys.length} 条入住记录？在住记录会自动跳过`}
                  onConfirm={handleBatchDelete}
                  okText="删除"
                  cancelText="取消"
                >
                  <PermissionButton
                    permission="occupancy:delete"
                    danger
                    size="small"
                    icon={<DeleteOutlined />}
                    style={{ marginLeft: 12 }}
                    loading={batchLoading}
                  >
                    批量删除
                  </PermissionButton>
                </Popconfirm>
              )}
              <Button size="small" onClick={() => setSelectedRowKeys([])} style={{ marginLeft: 8 }}>
                取消选择
              </Button>
            </span>
          }
          type="info"
          style={{ marginBottom: 12 }}
        />
      )}
      <Table
        columns={columns}
        dataSource={filteredData}
        rowKey="id"
        loading={loading}
        locale={{ emptyText: <Empty description="暂无数据" /> }}
        scroll={{ x: 1300 }}
        pagination={{
          defaultPageSize: 15,
          showSizeChanger: true,
          pageSizeOptions: [15, 30, 50, 100],
          showTotal: (total) => `共 ${total} 条`,
        }}
        rowSelection={rowSelection}
      />
      <Modal
        title="入住登记"
        open={checkInModal}
        onOk={handleCheckIn}
        onCancel={() => setCheckInModal(false)}
        okText="确认入住"
        confirmLoading={saving}
        width={500}
      >
        <Form form={checkInForm} layout="vertical">
          <Form.Item
            name="studentId"
            label="选择学生"
            rules={[{ required: true, message: '请选择学生' }]}
          >
            <Select
              showSearch
              optionFilterProp="label"
              placeholder="搜索并选择学生"
              options={students
                .filter((s: any) => s.status === 'active')
                .map((s: any) => ({
                  value: s.id,
                  label: `${s.name} (${s.idNumber ? maskIdNumber(s.idNumber) : (s.phone ? maskPhone(s.phone) : '')})`,
                }))}
            />
          </Form.Item>
          <Form.Item
            name="roomId"
            label="选择宿舍"
            rules={[{ required: true, message: '请选择宿舍' }]}
          >
            <Select
              showSearch
              optionFilterProp="label"
              placeholder="搜索并选择宿舍"
              onChange={handleRoomChange}
              options={rooms.map((r) => ({
                value: r.id,
                label: `${r.roomNumber} (${r.building || ''}) [${r.currentCount}/${r.capacity}]`,
                disabled: r.currentCount >= r.capacity,
              }))}
            />
          </Form.Item>
          <Form.Item name="checkInDate" label="入住日期" rules={[{ required: true }]}>
            <DatePicker style={{ width: '100%' }} placeholder="选择入住日期" format="YYYY-MM-DD" />
          </Form.Item>
          <Form.Item
            name="billingStartDate"
            label="计费起始日"
            extra="默认与入住日期相同，可调整（如学生要求从次日开始计费）"
          >
            <DatePicker
              style={{ width: '100%' }}
              placeholder="选择计费起始日"
              format="YYYY-MM-DD"
            />
          </Form.Item>
          <Form.Item name="stayType" label="入住类型">
            <Select
              allowClear
              options={[
                { value: 'short', label: '短租' },
                { value: 'long', label: '长租' },
              ]}
              placeholder="默认为短租"
            />
          </Form.Item>
          <Form.Item name="responsibleOrganizationId" label="负责机构">
            <Select
              showSearch
              allowClear
              optionFilterProp="label"
              placeholder="默认取学生所属机构"
              options={organizations.map((t: { id: number; name: string }) => ({
                value: t.id,
                label: t.name,
              }))}
            />
          </Form.Item>
          <Form.Item
            name="bedId"
            label="床位"
            rules={[{ required: true, message: '请选择床位' }]}
          >
            <Select
              placeholder="请先选择房间"
              disabled={availableBeds.length === 0}
              options={availableBeds.map((b) => ({
                value: b.id,
                label: b.bedNumber,
              }))}
              notFoundContent="该房间暂无可用床位"
            />
          </Form.Item>
          {availableBeds.length > 0 && (
            <div style={{ marginTop: -16, marginBottom: 16, color: '#888', fontSize: 12 }}>
              空闲 {availableBeds.length} 张床位
            </div>
          )}
          <Form.Item name="lockerId" label="柜子（可选）">
            <Select
              allowClear
              placeholder="可选分配柜子"
              disabled={availableLockers.length === 0}
              options={availableLockers.map((l) => ({
                value: l.id,
                label: l.lockerNumber,
              }))}
            />
          </Form.Item>
          <Form.Item name="notes" label="备注">
            <Input.TextArea rows={2} />
          </Form.Item>
        </Form>
      </Modal>

      {/* 退宿弹窗 */}
      <Modal
        title={`退宿 - ${checkOutModal?.student?.name}`}
        open={!!checkOutModal}
        onOk={handleCheckOut}
        onCancel={() => setCheckOutModal(null)}
        okText="确认退宿"
        confirmLoading={saving}
      >
        <Form form={checkOutForm} layout="vertical">
          <Form.Item name="checkOutDate" label="退宿日期" rules={[{ required: true }]}>
            <DatePicker style={{ width: '100%' }} placeholder="选择退宿日期" format="YYYY-MM-DD" />
          </Form.Item>
          <Form.Item name="billingEndDate" label="计费截止日" extra="默认与退宿日期相同">
            <DatePicker
              style={{ width: '100%' }}
              placeholder="选择计费截止日"
              format="YYYY-MM-DD"
            />
          </Form.Item>
          <Form.Item name="checkOutReason" label="退宿原因">
            <Select
              allowClear
              options={[
                { value: '换房', label: '换房' },
                { value: '退训', label: '退训' },
                { value: '结业', label: '结业' },
                { value: '毕业', label: '毕业' },
                { value: '其他', label: '其他' },
              ]}
            />
          </Form.Item>
        </Form>
      </Modal>

      {/* 批量退宿弹窗 */}
      <Modal
        title={`批量退宿（${selectedRowKeys.length} 人）`}
        open={batchCheckOutModal}
        onOk={handleBatchCheckOut}
        onCancel={() => setBatchCheckOutModal(false)}
        okText="确认批量退宿"
        width={500}
      >
        <Form form={batchCheckOutForm} layout="vertical">
          <Form.Item name="checkOutDate" label="退宿日期" rules={[{ required: true }]}>
            <DatePicker style={{ width: '100%' }} placeholder="选择退宿日期" format="YYYY-MM-DD" />
          </Form.Item>
          <Form.Item name="billingEndDate" label="计费截止日" extra="默认与退宿日期相同">
            <DatePicker
              style={{ width: '100%' }}
              placeholder="选择计费截止日"
              format="YYYY-MM-DD"
            />
          </Form.Item>
          <Form.Item name="checkOutReason" label="退宿原因">
            <Select
              allowClear
              options={[
                { value: '结业', label: '结业' },
                { value: '退训', label: '退训' },
                { value: '毕业', label: '毕业' },
                { value: '其他', label: '其他' },
              ]}
            />
          </Form.Item>
        </Form>
        <div
          style={{
            marginTop: 12,
            padding: '8px 12px',
            background: '#f5f5f5',
            borderRadius: 6,
            maxHeight: 150,
            overflow: 'auto',
          }}
        >
          <div style={{ fontSize: 12, color: '#666', marginBottom: 4 }}>即将退宿的学生：</div>
          {data
            .filter((r: any) => selectedRowKeys.includes(r.id))
            .map((r: any) => (
              <Tag key={r.id} style={{ marginBottom: 4 }}>
                {r.student?.name} ({r.room?.roomNumber})
              </Tag>
            ))}
        </div>
      </Modal>

      {/* 换房弹窗 */}
      <Modal
        title={`换房 - ${transferModal?.student?.name}`}
        open={!!transferModal}
        onOk={handleTransfer}
        onCancel={() => {
          setTransferModal(null);
          transferForm.resetFields();
          setTransferAvailableBeds([]);
          setTransferAvailableLockers([]);
        }}
        okText="确认换房"
        confirmLoading={saving}
        width={500}
      >
        <Form form={transferForm} layout="vertical">
          <Form.Item name="newRoomId" label="目标宿舍" rules={[{ required: true }]}>
            <Select
              showSearch
              optionFilterProp="label"
              placeholder="选择目标宿舍"
              onChange={handleTransferRoomChange}
              options={rooms
                .filter((r: any) => r.id !== transferModal?.roomId)
                .map((r: any) => ({
                  value: r.id,
                  label: `${r.roomNumber} (${r.building || ''}) [${r.currentCount}/${r.capacity}]`,
                  disabled: r.currentCount >= r.capacity,
                }))}
            />
          </Form.Item>
          <Form.Item
            name="newBedId"
            label="目标床位"
            rules={[{ required: true, message: '请选择目标床位' }]}
          >
            <Select
              placeholder="请先选择目标宿舍"
              disabled={transferAvailableBeds.length === 0}
              options={transferAvailableBeds.map((bed) => ({
                value: bed.id,
                label: bed.bedNumber,
              }))}
              notFoundContent="目标宿舍暂无可用床位"
            />
          </Form.Item>
          {transferAvailableBeds.length > 0 && (
            <div style={{ marginTop: -16, marginBottom: 16, color: '#888', fontSize: 12 }}>
              空闲 {transferAvailableBeds.length} 张床位
            </div>
          )}
          <Form.Item name="newLockerId" label="目标柜子（可选）">
            <Select
              allowClear
              placeholder="可选分配目标宿舍柜子"
              disabled={transferAvailableLockers.length === 0}
              options={transferAvailableLockers.map((locker) => ({
                value: locker.id,
                label: locker.lockerNumber,
              }))}
              notFoundContent="目标宿舍暂无可用柜子"
            />
          </Form.Item>
          <Form.Item name="transferDate" label="换房日期" rules={[{ required: true }]}>
            <DatePicker style={{ width: '100%' }} placeholder="选择换房日期" format="YYYY-MM-DD" />
          </Form.Item>
          <Form.Item name="oldBillingEndDate" label="旧房计费截止日" extra="默认为换房当天">
            <DatePicker
              style={{ width: '100%' }}
              placeholder="选择旧房计费截止日"
              format="YYYY-MM-DD"
            />
          </Form.Item>
          <Form.Item name="newBillingStartDate" label="新房计费起始日" extra="默认为换房次日">
            <DatePicker
              style={{ width: '100%' }}
              placeholder="选择新房计费起始日"
              format="YYYY-MM-DD"
            />
          </Form.Item>
          <Form.Item name="reason" label="换房原因">
            <Input />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
};

export default OccupanciesPage;
