// aislop-ignore-file: duplicate-block -- 退宿/换房表单结构相似且字段不同，已共享 DateFormItem
import React from 'react';
import {
  DatePicker,
  Form,
  Input,
  InputNumber,
  Modal,
  Select,
  Switch,
  Tag,
} from 'antd';
import type { Dayjs } from 'dayjs';
import { maskIdNumber, maskPhone } from '../../utils/sensitive';
import type { OccupancyRow } from './OccupancyColumns';

export type FormRule = React.ComponentProps<typeof Form.Item>['rules'];

export const DateFormItem: React.FC<{
  name: string;
  label: string;
  placeholder: string;
  required?: boolean;
  dependencies?: string[];
  extra?: string;
  rules?: FormRule;
}> = ({ name, label, placeholder, required, dependencies, extra, rules }) => (
  <Form.Item
    name={name}
    label={label}
    dependencies={dependencies}
    extra={extra}
    rules={[
      ...(required ? [{ required: true, message: `请选择${label}` }] : []),
      ...(rules ?? []),
    ]}
  >
    <DatePicker style={{ width: '100%' }} placeholder={placeholder} format="YYYY-MM-DD" />
  </Form.Item>
);

export const CheckInModal: React.FC<{
  open: boolean;
  canCheckIn: boolean;
  saving: boolean;
  form: ReturnType<typeof Form.useForm>[0];
  students: any[];
  activeOccupancyByStudentId: Map<number, OccupancyRow>;
  rooms: any[];
  roomOptionLabel: (room: any) => string;
  isRoomSelectable: (room: any) => boolean;
  onRoomChange: (roomId: number) => void;
  availableBeds: any[];
  availableLockers: any[];
  availableResourcesLoading: boolean;
  selectedCheckInRoomId?: number;
  dateNotBefore: (start: string | Dayjs | null | undefined, messageText: string) => unknown;
  onOk: () => void;
  onCancel: () => void;
}> = ({
  open,
  canCheckIn,
  saving,
  form,
  students,
  activeOccupancyByStudentId,
  rooms,
  roomOptionLabel,
  isRoomSelectable,
  onRoomChange,
  availableBeds,
  availableLockers,
  availableResourcesLoading,
  selectedCheckInRoomId,
  dateNotBefore,
  onOk,
  onCancel,
}) => {
  return (
    <Modal
      title="入住登记"
      open={open && canCheckIn}
      onOk={canCheckIn ? onOk : undefined}
      onCancel={onCancel}
      okText="确认入住"
      confirmLoading={saving}
      width={500}
    >
      <Form form={form} layout="vertical">
        <Form.Item name="studentId" label="选择学生" rules={[{ required: true, message: '请选择学生' }]}>
          <Select
            showSearch
            optionFilterProp="label"
            placeholder="搜索并选择学生"
            options={students
              .filter((s) => s.status === 'active')
              .map((s) => {
                const activeOccupancy = activeOccupancyByStudentId.get(s.id);
                const identifier = s.idNumber
                  ? maskIdNumber(s.idNumber)
                  : s.phone
                    ? maskPhone(s.phone)
                    : '';
                return {
                  value: s.id,
                  label: `${s.name} (${identifier})${
                    activeOccupancy
                      ? ` · 已入住${activeOccupancy.room?.roomNumber ? ` ${activeOccupancy.room.roomNumber}` : ''}`
                      : ''
                  }`,
                  disabled: !!activeOccupancy,
                };
              })}
          />
        </Form.Item>
        <Form.Item name="roomId" label="选择宿舍" rules={[{ required: true, message: '请选择宿舍' }]}>
          <Select
            showSearch
            optionFilterProp="label"
            placeholder="搜索并选择宿舍"
            onChange={onRoomChange}
            options={rooms.map((r) => ({
              value: r.id,
              label: roomOptionLabel(r),
              disabled: !isRoomSelectable(r),
            }))}
          />
        </Form.Item>
        <DateFormItem name="checkInDate" label="入住日期" placeholder="选择入住日期" required />
        <DateFormItem
          name="billingStartDate"
          label="计费起始日"
          placeholder="选择计费起始日"
          required
          dependencies={['checkInDate']}
          extra="默认与入住日期相同，可调整（如学生要求从次日开始计费）"
          rules={[
            ({ getFieldValue }) => ({
              validator: dateNotBefore(
                getFieldValue('checkInDate'),
                '计费起始日不能早于入住日期',
              ) as never,
            }),
          ]}
        />
        <Form.Item name="stayType" label="入住类型" rules={[{ required: true, message: '请选择入住类型' }]}>
          <Select
            options={[
              { value: 'short', label: '短租' },
              { value: 'long', label: '长租' },
            ]}
            placeholder="默认为短租"
          />
        </Form.Item>
        <Form.Item
          name="bedId"
          label="床位"
          rules={[
            { required: true, message: '请选择床位' },
            {
              validator: (_: unknown, value?: number) =>
                !value || availableBeds.some((bed) => bed.id === value)
                  ? Promise.resolve()
                  : Promise.reject(new Error('请选择当前宿舍下的可用床位')),
            },
          ]}
        >
          <Select
            placeholder={selectedCheckInRoomId ? '请选择床位' : '请先选择房间'}
            loading={availableResourcesLoading}
            disabled={!selectedCheckInRoomId || availableResourcesLoading || availableBeds.length === 0}
            options={availableBeds.map((b) => ({
              value: b.id,
              label: b.bedNumber,
            }))}
            notFoundContent={selectedCheckInRoomId ? '该房间暂无可用床位' : '请先选择房间'}
          />
        </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="可选分配柜子"
            loading={availableResourcesLoading}
            disabled={!selectedCheckInRoomId || availableResourcesLoading || availableLockers.length === 0}
            options={availableLockers.map((l) => ({
              value: l.id,
              label: l.lockerNumber,
            }))}
          />
        </Form.Item>
        <Form.Item
          name="collectDeposit"
          label="押金缴纳"
          valuePropName="checked"
          extra="开启后，确认入住时同步生成已缴押金记录；已有已缴押金时不会重复创建"
        >
          <Switch checkedChildren="已缴" unCheckedChildren="不缴" />
        </Form.Item>
        <Form.Item
          noStyle
          shouldUpdate={(prev, current) => prev.collectDeposit !== current.collectDeposit}
        >
          {({ getFieldValue }) =>
            getFieldValue('collectDeposit') ? (
              <Form.Item
                name="depositAmount"
                label="押金金额"
                rules={[{ required: true, message: '请输入押金金额' }]}
              >
                <InputNumber min={0.01} precision={2} suffix="元" style={{ width: '100%' }} />
              </Form.Item>
            ) : null
          }
        </Form.Item>
        <Form.Item name="notes" label="备注">
          <Input.TextArea rows={2} />
        </Form.Item>
      </Form>
    </Modal>
  );
};

export const CheckOutModal: React.FC<{
  record: OccupancyRow | null;
  canCheckOut: boolean;
  saving: boolean;
  form: ReturnType<typeof Form.useForm>[0];
  dateNotBefore: (start: string | Dayjs | null | undefined, messageText: string) => unknown;
  onOk: () => void;
  onCancel: () => void;
}> = ({ record, canCheckOut, saving, form, dateNotBefore, onOk, onCancel }) => {
  return (
    <Modal
      title={`退宿 - ${record?.student?.name}`}
      open={!!record && canCheckOut}
      onOk={canCheckOut ? onOk : undefined}
      onCancel={onCancel}
      okText="确认退宿"
      confirmLoading={saving}
    >
      <Form form={form} layout="vertical">
        <DateFormItem
          name="checkOutDate"
          label="退宿日期"
          placeholder="选择退宿日期"
          required
          rules={[
            { validator: dateNotBefore(record?.checkInDate, '退宿日期不能早于入住日期') as never },
          ]}
        />
        <DateFormItem
          name="billingEndDate"
          label="计费截止日"
          placeholder="选择计费截止日"
          dependencies={['checkOutDate']}
          extra="默认与退宿日期相同"
          rules={[
            ({ getFieldValue }) => ({
              validator: dateNotBefore(
                record?.billingStartDate || record?.checkInDate || getFieldValue('checkOutDate'),
                '计费截止日不能早于计费起始日',
              ) as never,
            }),
          ]}
        />
        <Form.Item name="checkOutReason" label="退宿原因">
          <Select
            allowClear
            options={[
              { value: '换房', label: '换房' },
              { value: '退训', label: '退训' },
              { value: '结业', label: '结业' },
              { value: '毕业', label: '毕业' },
              { value: '其他', label: '其他' },
            ]}
          />
        </Form.Item>
      </Form>
    </Modal>
  );
};

export const BatchCheckOutModal: React.FC<{
  open: boolean;
  canCheckOut: boolean;
  selectedRowKeys: number[];
  latestSelectedCheckInDate?: string;
  latestSelectedBillingStartDate?: string;
  data: any[];
  form: ReturnType<typeof Form.useForm>[0];
  dateNotBefore: (start: string | Dayjs | null | undefined, messageText: string) => unknown;
  onOk: () => void;
  onCancel: () => void;
}> = ({
  open,
  canCheckOut,
  selectedRowKeys,
  latestSelectedCheckInDate,
  latestSelectedBillingStartDate,
  data,
  form,
  dateNotBefore,
  onOk,
  onCancel,
}) => {
  return (
    <Modal
      title={`批量退宿（${selectedRowKeys.length} 人）`}
      open={open && canCheckOut}
      onOk={canCheckOut ? onOk : undefined}
      onCancel={onCancel}
      okText="确认批量退宿"
      width={500}
    >
      <Form form={form} layout="vertical">
        <DateFormItem
          name="checkOutDate"
          label="退宿日期"
          placeholder="选择退宿日期"
          required
          rules={[
            {
              validator: dateNotBefore(
                latestSelectedCheckInDate,
                '退宿日期不能早于所选记录中最晚的入住日期',
              ) as never,
            },
          ]}
        />
        <DateFormItem
          name="billingEndDate"
          label="计费截止日"
          placeholder="选择计费截止日"
          extra="默认与退宿日期相同"
          rules={[
            {
              validator: dateNotBefore(
                latestSelectedBillingStartDate,
                '计费截止日不能早于所选记录中最晚的计费起始日',
              ) as never,
            },
          ]}
        />
        <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>
  );
};

export const TransferModal: React.FC<{
  record: OccupancyRow | null;
  canTransfer: boolean;
  saving: boolean;
  form: ReturnType<typeof Form.useForm>[0];
  rooms: any[];
  roomOptionLabel: (room: any) => string;
  isRoomSelectable: (room: any) => boolean;
  onRoomChange: (roomId: number) => void;
  transferAvailableBeds: any[];
  transferAvailableLockers: any[];
  transferResourcesLoading: boolean;
  selectedTransferRoomId?: number;
  dateNotBefore: (start: string | Dayjs | null | undefined, messageText: string) => unknown;
  onOk: () => void;
  onCancel: () => void;
}> = ({
  record,
  canTransfer,
  saving,
  form,
  rooms,
  roomOptionLabel,
  isRoomSelectable,
  onRoomChange,
  transferAvailableBeds,
  transferAvailableLockers,
  transferResourcesLoading,
  selectedTransferRoomId,
  dateNotBefore,
  onOk,
  onCancel,
}) => {
  return (
    <Modal
      title={`换房 - ${record?.student?.name}`}
      open={!!record && canTransfer}
      onOk={onOk}
      onCancel={onCancel}
      okText="确认换房"
      confirmLoading={saving}
      width={500}
    >
      <Form form={form} layout="vertical">
        <Form.Item name="newRoomId" label="目标宿舍" rules={[{ required: true }]}>
          <Select
            showSearch
            optionFilterProp="label"
            placeholder="选择目标宿舍"
            onChange={onRoomChange}
            options={rooms
              .filter((r) => r.id !== record?.roomId)
              .map((r) => ({
                value: r.id,
                label: roomOptionLabel(r),
                disabled: !isRoomSelectable(r),
              }))}
          />
        </Form.Item>
        <Form.Item
          name="newBedId"
          label="目标床位"
          rules={[
            { required: true, message: '请选择目标床位' },
            {
              validator: (_: unknown, value?: number) =>
                !value || transferAvailableBeds.some((bed) => bed.id === value)
                  ? Promise.resolve()
                  : Promise.reject(new Error('请选择目标宿舍下的可用床位')),
            },
          ]}
        >
          <Select
            placeholder={selectedTransferRoomId ? '请选择目标床位' : '请先选择目标宿舍'}
            loading={transferResourcesLoading}
            disabled={
              !selectedTransferRoomId ||
              transferResourcesLoading ||
              transferAvailableBeds.length === 0
            }
            options={transferAvailableBeds.map((bed) => ({
              value: bed.id,
              label: bed.bedNumber,
            }))}
            notFoundContent={selectedTransferRoomId ? '目标宿舍暂无可用床位' : '请先选择目标宿舍'}
          />
        </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="可选分配目标宿舍柜子"
            loading={transferResourcesLoading}
            disabled={
              !selectedTransferRoomId ||
              transferResourcesLoading ||
              transferAvailableLockers.length === 0
            }
            options={transferAvailableLockers.map((locker) => ({
              value: locker.id,
              label: locker.lockerNumber,
            }))}
            notFoundContent="目标宿舍暂无可用柜子"
          />
        </Form.Item>
        <Form.Item
          name="transferDate"
          label="换房日期"
          rules={[
            { required: true, message: '请选择换房日期' },
            {
              validator: dateNotBefore(record?.checkInDate, '换房日期不能早于原入住日期') as never,
            },
          ]}
        >
          <DatePicker style={{ width: '100%' }} placeholder="选择换房日期" format="YYYY-MM-DD" />
        </Form.Item>
        <Form.Item
          name="oldBillingEndDate"
          label="旧房计费截止日"
          dependencies={['transferDate']}
          extra="默认为换房当天"
          rules={[
            ({ getFieldValue }) => ({
              validator: dateNotBefore(
                record?.billingStartDate || record?.checkInDate || getFieldValue('transferDate'),
                '旧房计费截止日不能早于计费起始日',
              ) as never,
            }),
          ]}
        >
          <DatePicker
            style={{ width: '100%' }}
            placeholder="选择旧房计费截止日"
            format="YYYY-MM-DD"
          />
        </Form.Item>
        <Form.Item
          name="newBillingStartDate"
          label="新房计费起始日"
          dependencies={['transferDate']}
          extra="默认为换房次日"
          rules={[
            ({ getFieldValue }) => ({
              validator: dateNotBefore(
                getFieldValue('transferDate'),
                '新房计费起始日不能早于换房日期',
              ) as never,
            }),
          ]}
        >
          <DatePicker
            style={{ width: '100%' }}
            placeholder="选择新房计费起始日"
            format="YYYY-MM-DD"
          />
        </Form.Item>
        <Form.Item name="reason" label="换房原因">
          <Input />
        </Form.Item>
      </Form>
    </Modal>
  );
};
