import React, { useCallback, useEffect, useMemo, useState } from 'react';
import dayjs, { type Dayjs } from 'dayjs';
import { Button, Table, Modal, Form, Input, Select, TreeSelect, Row, Col, Image, Tag, Space, DatePicker } from 'antd';
import type { FormProps } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { Plus, Trash2, Search, RefreshCw } from 'lucide-react';
import { toast } from 'sonner';
import { useTranslation } from 'react-i18next';
import { materialInformationApi, MaterialsVO } from '../../../api/material/information';
import { materialLockerApi } from '../../../api/material/lockers';
import { materialTypeApi } from '../../../api/material/type';
import { materialStandardApi } from '../../../api/material/standard';
import { materialPropertyValueApi } from '../../../api/material/propertyValue';
import { pickRecords, pickTotal, buildPageParams, fetchAllMaterialTypes, buildMaterialTypeTreeData } from '../materialListUtils';
import UploadImg from '../../lockCabinet/UploadImg';
import {
  MaterialPageRoot,
  MaterialTableCard,
  MaterialPaginationBar,
  MaterialEditButton,
  MaterialDeleteButton,
  materialConfirmDelete,
  getMaterialFormModalProps,
} from '../MaterialPageLayout';

function firstDefined(row: any, keys: string[]) {
  for (const k of keys) {
    const v = row[k];
    if (v !== undefined && v !== null && v !== '') return v;
  }
  return undefined;
}

function inCabinetTag(row: any) {
  const ic = firstDefined(row, ['inCabinet', 'isInCabinet', 'inCabinetFlag']);
  if (ic === 1 || ic === true || ic === '1') return <Tag color="success">是</Tag>;
  if (ic === 0 || ic === false || ic === '0') return <Tag color="default">否</Tag>;
  // 兼容旧接口：仅返回 loanState 时按借还状态推断是否在柜（0 在柜、3 已归还视为在柜）
  const ls = row.loanState;
  if (ls !== undefined && ls !== null && ls !== '') {
    const n = Number(ls);
    if (n === 0 || n === 3) return <Tag color="success">是</Tag>;
    if (n === 1 || n === 2) return <Tag color="default">否</Tag>;
  }
  return <span className="text-gray-400">—</span>;
}

function statusTag(row: any) {
  const s = firstDefined(row, ['status', 'materialsStatus', 'state']);
  if (s === undefined || s === null || s === '') return <span className="text-gray-400">—</span>;
  if (typeof s === 'string' && (s === '正常' || s === '停用' || s === '启用')) {
    return <Tag color={s === '停用' ? 'default' : 'blue'}>{s}</Tag>;
  }
  const n = Number(s);
  if (n === 0) return <Tag color="blue">正常</Tag>;
  if (n === 1) return <Tag>停用</Tag>;
  return <Tag color="blue">{String(s)}</Tag>;
}

/** 物资清单新增/编辑弹窗：与老系统 MaterialForm.vue（label-width 110px、控件约 348px）一致 */
const materialInfoModalFormLayout: FormProps = {
  layout: 'horizontal',
  colon: false,
  labelAlign: 'right',
  labelCol: { flex: '0 0 110px' },
  wrapperCol: { flex: '1 1 auto', style: { maxWidth: 348 } },
};

/** 与老系统 index.vue / MaterialForm.vue 一致：全量物资柜（pageSize: -1）+ 末尾「空」选项 */
const MATERIALS_CABINET_LIST_PARAMS = buildPageParams(1, -1);

function mapCabinetListToOptions(rows: any[]): { value: number; label: string }[] {
  const mapped = rows
    .map((c: any) => {
      const rawId = c.id ?? c.cabinetId;
      const value = Number(rawId);
      const label = String(c.cabinetName ?? c.name ?? '').trim();
      return { value, label: label || (Number.isFinite(value) ? `#${value}` : '') };
    })
    .filter((o) => Number.isFinite(o.value) && o.label);
  const hasZero = mapped.some((o) => o.value === 0);
  return hasZero ? mapped : [...mapped, { value: 0, label: '空' }];
}

type DraftQuery = {
  materialsCabinetId?: number;
  materialsName: string;
  materialsTypeId?: number;
  materialsPropertyId?: number;
  materialsPropertyValueId?: number;
  rfid: string;
  supplier: string;
  validityStart: string;
  validityEnd: string;
  inCabinet?: number;
  status?: number;
};

const emptyDraft = (fixedCabinetId?: number): DraftQuery => ({
  materialsName: '',
  rfid: '',
  supplier: '',
  validityStart: '',
  validityEnd: '',
  ...(fixedCabinetId != null && Number.isFinite(fixedCabinetId) ? { materialsCabinetId: fixedCabinetId } : {}),
});

export interface MaterialInformationPageProps {
  /** 嵌入物资柜详情时固定筛选该柜，不可改选 */
  fixedCabinetId?: number;
  fixedCabinetName?: string;
  /** 为 true 时不使用 MaterialPageRoot 外层（由详情页布局） */
  embedded?: boolean;
  /** 嵌入详情时与筛选区同卡顶部的 Tab 条 */
  embeddedTabBar?: React.ReactNode;
}

export default function MaterialInformationPage({
  fixedCabinetId,
  fixedCabinetName,
  embedded,
  embeddedTabBar,
}: MaterialInformationPageProps = {}) {
  const { t } = useTranslation();
  const [loading, setLoading] = useState(false);
  const [list, setList] = useState<any[]>([]);
  const [total, setTotal] = useState(0);
  const [pageNo, setPageNo] = useState(1);
  const [pageSize] = useState(10);
  const [draft, setDraft] = useState<DraftQuery>(() => emptyDraft(fixedCabinetId));
  const [applied, setApplied] = useState<DraftQuery>(() => emptyDraft(fixedCabinetId));
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  const [modalOpen, setModalOpen] = useState(false);
  const [form] = Form.useForm();
  const [editing, setEditing] = useState<any | null>(null);

  const [cabinetOpts, setCabinetOpts] = useState<{ value: number; label: string }[]>([]);
  const [materialTypeRows, setMaterialTypeRows] = useState<any[]>([]);
  const [propertyOpts, setPropertyOpts] = useState<{ value: number; label: string }[]>([]);
  const [valueOpts, setValueOpts] = useState<{ value: number; label: string }[]>([]);

  const typeTreeData = useMemo(() => buildMaterialTypeTreeData(materialTypeRows), [materialTypeRows]);

  const typeNameMap = useMemo(() => {
    const m = new Map<number, string>();
    for (const x of materialTypeRows) {
      const id = Number(x.id ?? x.materialsTypeId);
      if (!Number.isFinite(id)) continue;
      const name = String(x.materialsTypeName ?? x.typeName ?? x.name ?? '').trim();
      if (name) m.set(id, name);
    }
    return m;
  }, [materialTypeRows]);

  const cabinetNameMap = useMemo(() => {
    const m = new Map<number, string>();
    cabinetOpts.forEach((o) => m.set(o.value, o.label));
    return m;
  }, [cabinetOpts]);

  /** 嵌入物资柜详情时弹窗内只能展示当前柜，选项需与 disabled 状态一致，否则易不显示或提交异常 */
  const modalCabinetSelectOptions = useMemo(() => {
    if (fixedCabinetId != null && Number.isFinite(Number(fixedCabinetId))) {
      const id = Number(fixedCabinetId);
      return [
        {
          value: id,
          label:
            fixedCabinetName?.trim() ||
            cabinetNameMap.get(id) ||
            (Number.isFinite(id) ? `物资柜 #${id}` : ''),
        },
      ];
    }
    return cabinetOpts;
  }, [fixedCabinetId, fixedCabinetName, cabinetNameMap, cabinetOpts]);

  useEffect(() => {
    (async () => {
      try {
        const cabRes = await materialLockerApi.listMaterialsCabinet(MATERIALS_CABINET_LIST_PARAMS);
        setCabinetOpts(mapCabinetListToOptions(pickRecords(cabRes)));
      } catch {
        try {
          const cabRes2 = await materialLockerApi.listMaterialsCabinet(buildPageParams(1, 500));
          setCabinetOpts(mapCabinetListToOptions(pickRecords(cabRes2)));
        } catch {
          setCabinetOpts([{ value: 0, label: '空' }]);
        }
      }
      try {
        const typeRows = await fetchAllMaterialTypes(materialTypeApi.listType);
        const seen = new Set<number>();
        const unique: any[] = [];
        for (const x of typeRows) {
          const id = Number(x.id ?? x.materialsTypeId);
          if (!Number.isFinite(id) || id <= 0 || seen.has(id)) continue;
          seen.add(id);
          unique.push(x);
        }
        setMaterialTypeRows(unique);
      } catch {
        setMaterialTypeRows([]);
      }
      try {
        const propRes = await materialStandardApi.PropertyPage(buildPageParams(1, 500));
        setPropertyOpts(
          pickRecords(propRes)
            .map((x: any) => ({
              value: Number(x.propertyId ?? x.id),
              label: String(x.propertyName ?? x.propertyId ?? ''),
            }))
            .filter((o) => Number.isFinite(o.value) && o.label),
        );
      } catch {
        setPropertyOpts([]);
      }
    })();
  }, []);

  useEffect(() => {
    if (fixedCabinetId != null && Number.isFinite(fixedCabinetId)) {
      setDraft((d) => ({ ...d, materialsCabinetId: fixedCabinetId }));
      setApplied((a) => ({ ...a, materialsCabinetId: fixedCabinetId }));
    }
  }, [fixedCabinetId]);

  useEffect(() => {
    const pid = draft.materialsPropertyId;
    if (pid == null) {
      setValueOpts([]);
      return;
    }
    materialPropertyValueApi
      .PropertyValuePage(buildPageParams(1, 500, { propertyId: pid }))
      .then((res) => {
        setValueOpts(
          pickRecords(res)
            .map((x: any) => ({
              value: Number(x.recordId ?? x.id ?? x.propertyValueId),
              label: String(x.propertyValue ?? ''),
            }))
            .filter((o) => Number.isFinite(o.value)),
        );
      })
      .catch(() => setValueOpts([]));
  }, [draft.materialsPropertyId]);

  const buildListParams = useCallback(() => {
    const base = buildPageParams(pageNo, pageSize);
    const q: Record<string, any> = { ...base };
    if (applied.materialsCabinetId != null) {
      const mc = Number(applied.materialsCabinetId);
      if (Number.isFinite(mc)) {
        q.materialsCabinetId = mc;
        q.cabinetId = mc;
      }
    }
    if (applied.materialsName?.trim()) q.materialsName = applied.materialsName.trim();
    if (applied.materialsTypeId != null) q.materialsTypeId = applied.materialsTypeId;
    if (applied.materialsPropertyId != null) {
      q.materialsPropertyId = applied.materialsPropertyId;
      q.propertyId = applied.materialsPropertyId;
    }
    if (applied.materialsPropertyValueId != null) {
      q.materialsPropertyValueId = applied.materialsPropertyValueId;
      q.propertyValueId = applied.materialsPropertyValueId;
    }
    if (applied.rfid?.trim()) {
      const r = applied.rfid.trim();
      q.rfid = r;
      q.materialsRfid = r;
    }
    if (applied.supplier?.trim()) q.supplier = applied.supplier.trim();
    if (applied.validityStart) {
      q.validityEndStart = applied.validityStart;
      q.expirationDateStart = applied.validityStart;
    }
    if (applied.validityEnd) {
      q.validityEndEnd = applied.validityEnd;
      q.expirationDateEnd = applied.validityEnd;
    }
    if (applied.inCabinet != null) q.inCabinet = applied.inCabinet;
    if (applied.status != null) q.status = applied.status;
    return q;
  }, [pageNo, pageSize, applied]);

  const fetchList = useCallback(async () => {
    setLoading(true);
    try {
      const q = buildListParams();
      let res: any;
      try {
        res = await materialInformationApi.getExMaterials(q);
      } catch {
        res = await materialInformationApi.listMaterials({
          ...buildPageParams(pageNo, pageSize),
          materialsName: applied.materialsName?.trim() || undefined,
          materialsCabinetId: applied.materialsCabinetId,
          cabinetId: applied.materialsCabinetId,
          materialsTypeId: applied.materialsTypeId,
        });
      }
      const records = pickRecords(res);
      const tot = pickTotal(res);
      setList(records);
      setTotal(tot > 0 ? tot : records.length);
    } catch (e: any) {
      toast.error(e?.message || t('common.operationFailed'));
      setList([]);
      setTotal(0);
    } finally {
      setLoading(false);
    }
  }, [buildListParams, t]);

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

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

  const handleQuery = () => {
    setApplied({ ...draft });
    setPageNo(1);
    setSelectedRowKeys([]);
  };

  const resetQuery = () => {
    const e = emptyDraft(fixedCabinetId);
    setDraft(e);
    setApplied(e);
    setPageNo(1);
    setSelectedRowKeys([]);
  };

  const rowKey = (r: any, i?: number) =>
    String(r.materialsId ?? r.id ?? r.materialsDetailId ?? r.recordId ?? `row-${i ?? 0}`);

  const openForm = (row?: any) => {
    setEditing(row || null);
    form.resetFields();
    if (row) {
      const expRaw = firstDefined(row, ['expirationDate', 'validityEnd', 'expireDate', 'expiryDate', 'endTime']);
      const cabRaw = firstDefined(row, ['materialsCabinetId', 'cabinetId', 'bindCabinetId']);
      const rawProps = firstDefined(row, ['properties', 'materialsSpec', 'materialsSpecDesc']);
      let propertiesText = '';
      if (rawProps != null && String(rawProps).trim() !== '') {
        const s = String(rawProps).trim();
        try {
          const parsed = JSON.parse(s);
          if (typeof parsed === 'string') propertiesText = parsed;
          else if (parsed != null && typeof parsed === 'object') propertiesText = '';
        } catch {
          propertiesText = s;
        }
      }
      if (!propertiesText) {
        const namePart = firstDefined(row, ['propertiesProperty', 'propertyName', 'materialsPropertyName']);
        const valPart = firstDefined(row, ['propertiesValue', 'propertyValue', 'materialsPropertyValue']);
        const parts = [namePart, valPart].filter((x) => x != null && String(x).trim() !== '');
        if (parts.length) propertiesText = parts.map((x) => String(x).trim()).join(' / ');
      }
      form.setFieldsValue({
        materialsCabinetId: cabRaw != null && cabRaw !== '' ? Number(cabRaw) : undefined,
        materialsName: row.materialsName,
        materialsTypeId: row.materialsTypeId != null ? Number(row.materialsTypeId) : undefined,
        materialsRfid: firstDefined(row, ['materialsRfid', 'rfid', 'rfidCode']),
        supplier: firstDefined(row, ['supplier', 'supplierName']),
        expirationDate: expRaw ? dayjs(String(expRaw).slice(0, 10)) : undefined,
        materialsPicture: firstDefined(row, ['materialsPicture', 'materialsTypePicture', 'picture', 'imageUrl']),
        properties: propertiesText || undefined,
      });
      if (fixedCabinetId != null && Number.isFinite(fixedCabinetId)) {
        form.setFieldsValue({ materialsCabinetId: Number(fixedCabinetId) });
      }
    } else if (fixedCabinetId != null && Number.isFinite(fixedCabinetId)) {
      form.setFieldsValue({ materialsCabinetId: fixedCabinetId });
    }
    setModalOpen(true);
  };

  const submit = async () => {
    const v = await form.validateFields();
    const expRaw = v.expirationDate;
    const expStr =
      expRaw == null
        ? undefined
        : dayjs.isDayjs(expRaw)
          ? expRaw.format('YYYY-MM-DD')
          : dayjs(expRaw as string | number | Date).format('YYYY-MM-DD');
    const rid = typeof v.materialsRfid === 'string' ? v.materialsRfid.trim() : '';
    const sup = typeof v.supplier === 'string' ? v.supplier.trim() : '';
    const pic = v.materialsPicture;
    const mc = v.materialsCabinetId;
    const propsText = typeof v.properties === 'string' ? v.properties.trim() : '';
    const basePayload: Record<string, unknown> = {
      materialsName: v.materialsName,
      materialsTypeId: v.materialsTypeId,
      materialsPicture: pic,
      materialsIcon: pic ?? (editing ? firstDefined(editing, ['materialsIcon', 'materialsTypeIcon']) : undefined),
      loanState: editing != null && editing.loanState != null ? Number(editing.loanState) : 0,
      remark: editing?.remark,
      materialsCabinetId: mc,
      cabinetId: mc,
      materialsRfid: rid || undefined,
      rfid: rid || undefined,
      supplier: sup || undefined,
      expirationDate: expStr,
      validityEnd: expStr,
      properties: propsText,
    };
    setLoading(true);
    try {
      if (editing) {
        await materialInformationApi.updateMaterials({
          ...editing,
          ...basePayload,
          materialsId: editing.materialsId ?? editing.id,
        } as MaterialsVO);
        toast.success(t('common.updateSuccess'));
      } else {
        await materialInformationApi.addMaterials(basePayload as MaterialsVO);
        toast.success(t('common.addSuccess'));
      }
      setModalOpen(false);
      fetchList();
    } catch (e: any) {
      if (!e?.errorFields) toast.error(e?.message || t('common.operationFailed'));
    } finally {
      setLoading(false);
    }
  };

  const onDelete = (row: any) => {
    const id = row.materialsId ?? row.id;
    materialConfirmDelete(t, {
      count: 1,
      onOk: async () => {
        await materialInformationApi.deleteMaterials(id);
        toast.success(t('common.deleteSuccess'));
        fetchList();
      },
    });
  };

  const batchDelete = () => {
    if (selectedRowKeys.length === 0) return;
    const ids = list
      .filter((r, idx) => selectedRowKeys.includes(rowKey(r, idx)))
      .map((r) => r.materialsId ?? r.id)
      .filter((x) => x != null);
    if (ids.length === 0) {
      toast.error('无法解析选中行的物资 ID');
      return;
    }
    materialConfirmDelete(t, {
      count: ids.length,
      onOk: async () => {
        await materialInformationApi.deleteMaterials(ids.join(','));
        toast.success(t('common.deleteSuccess'));
        setSelectedRowKeys([]);
        fetchList();
      },
    });
  };

  const setDraftField = <K extends keyof DraftQuery>(key: K, value: DraftQuery[K]) => {
    setDraft((d) => ({ ...d, [key]: value }));
  };

  const columns: ColumnsType<any> = [
    {
      title: fixedCabinetId != null ? '物资柜' : '绑定物资柜',
      width: 124,
      align: 'center',
      render: (_, row) => {
        const name = firstDefined(row, ['cabinetName', 'materialsCabinetName']);
        const rawId = firstDefined(row, ['materialsCabinetId', 'cabinetId', 'bindCabinetId']);
        const id = rawId !== undefined && rawId !== null && rawId !== '' ? Number(rawId) : NaN;
        if (name) return String(name);
        if (id === 0) return '空';
        if (Number.isFinite(id) && id > 0) return cabinetNameMap.get(id) ?? String(id);
        return '—';
      },
    },
    {
      title: '物资编号',
      width: 92,
      align: 'center',
      render: (_, row) =>
        String(firstDefined(row, ['materialsCode', 'materialsNo', 'materialsId', 'id']) ?? '—'),
    },
    {
      title: '物资名称',
      dataIndex: 'materialsName',
      key: 'materialsName',
      width: 160,
      align: 'center',
      ellipsis: { showTitle: true },
    },
    {
      title: '物资类型',
      width: 132,
      align: 'center',
      render: (_, row) => {
        const name = firstDefined(row, ['materialsTypeName', 'typeName']);
        if (name) return String(name);
        const tid = row.materialsTypeId;
        if (tid != null) return typeNameMap.get(Number(tid)) ?? String(tid);
        return '—';
      },
    },
    {
      title: '物资规格种类',
      width: 128,
      align: 'center',
      render: (_, row) =>
        String(
          firstDefined(row, [
            'propertiesProperty',
            'propertyName',
            'materialsPropertyName',
            'specTypeName',
          ]) ?? '—',
        ),
    },
    {
      title: '物资规格',
      width: 104,
      align: 'center',
      render: (_, row) =>
        String(
          firstDefined(row, ['propertiesValue', 'propertyValue', 'materialsPropertyValue', 'specValue']) ?? '—',
        ),
    },
    {
      title: '物资图片',
      width: 96,
      align: 'center',
      render: (_, row) => {
        const src = firstDefined(row, [
          'materialsTypePicture',
          'materialsPicture',
          'materialsTypeIcon',
          'materialsIcon',
          'picture',
          'imageUrl',
        ]);
        if (!src) return <span className="text-gray-400">—</span>;
        return (
          <div className="inline-flex rounded-md border border-gray-200 bg-gray-50 p-0.5 shadow-sm">
            <Image
              src={String(src)}
              width={44}
              height={44}
              className="!rounded object-cover"
              preview={{ mask: '预览' }}
            />
          </div>
        );
      },
    },
    {
      title: 'RFID',
      width: 148,
      ellipsis: true,
      align: 'center',
      render: (_, row) => String(firstDefined(row, ['materialsRfid', 'rfid', 'rfidCode', 'rfId']) ?? '—'),
    },
    {
      title: '供应商',
      width: 108,
      ellipsis: true,
      align: 'center',
      render: (_, row) => String(firstDefined(row, ['supplier', 'supplierName']) ?? '—'),
    },
    {
      title: '有效期截止',
      width: 118,
      align: 'center',
      render: (_, row) => {
        const d = firstDefined(row, [
          'expirationDate',
          'validityEnd',
          'expireDate',
          'expiryDate',
          'endTime',
        ]);
        return d ? String(d).slice(0, 10) : '—';
      },
    },
    { title: '是否在柜中', width: 112, align: 'center', render: (_, row) => inCabinetTag(row) },
    { title: '状态', width: 88, align: 'center', render: (_, row) => statusTag(row) },
    {
      title: t('table.operation'),
      width: 160,
      align: 'center',
      fixed: 'right',
      render: (_, row) => (
        <div className="flex items-center gap-2 justify-center flex-wrap">
          <MaterialEditButton label={t('common.edit')} onClick={() => openForm(row)} />
          <MaterialDeleteButton label={t('common.delete')} onClick={() => onDelete(row)} />
        </div>
      ),
    },
  ];

  const filterLabelCls =
    'shrink-0 text-right text-sm font-medium text-gray-600 whitespace-nowrap w-[100px] sm:w-[108px]';

  const validityRangeValue: [Dayjs | null, Dayjs | null] | null =
    draft.validityStart || draft.validityEnd
      ? [draft.validityStart ? dayjs(draft.validityStart) : null, draft.validityEnd ? dayjs(draft.validityEnd) : null]
      : null;

  const toolbarCard = (
    <div className="overflow-hidden rounded-xl border border-gray-200/80 bg-white shadow-sm ring-1 ring-gray-100/80">
      {embeddedTabBar ? (
        <div className="border-b border-gray-100/80 px-2 pb-3 pt-4 sm:px-3 sm:pb-4 sm:pt-5">
          {embeddedTabBar}
        </div>
      ) : null}
      <div
        className="box-border w-full min-w-0 px-5"
        style={{ paddingTop: 28, paddingBottom: 20 }}
      >
        <div className="w-full min-w-0 space-y-4">
        <Row gutter={[16, 0]}>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>{fixedCabinetId != null ? '物资柜' : '绑定物资柜'}</span>
              <Select
                allowClear={fixedCabinetId == null}
                disabled={fixedCabinetId != null}
                placeholder="请选择物资柜"
                className="min-w-0 flex-1"
                options={
                  fixedCabinetId != null
                    ? [
                        {
                          value: fixedCabinetId,
                          label:
                            fixedCabinetName?.trim() ||
                            cabinetNameMap.get(fixedCabinetId) ||
                            `物资柜 #${fixedCabinetId}`,
                        },
                      ]
                    : cabinetOpts
                }
                value={draft.materialsCabinetId}
                onChange={(v) => setDraftField('materialsCabinetId', v ?? undefined)}
              />
            </div>
          </Col>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>物资名称</span>
              <Input
                allowClear
                placeholder="请输入物资名称"
                className="min-w-0 flex-1"
                value={draft.materialsName}
                onChange={(e) => setDraftField('materialsName', e.target.value)}
                onPressEnter={handleQuery}
              />
            </div>
          </Col>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>物资类型</span>
              <TreeSelect
                allowClear
                showSearch
                treeDefaultExpandAll
                treeLine={{ showLeafIcon: false }}
                placeholder="请选择物资类型"
                className="min-w-0 flex-1"
                treeData={typeTreeData}
                treeNodeFilterProp="title"
                value={draft.materialsTypeId}
                onChange={(v) =>
                  setDraftField('materialsTypeId', v != null && v !== '' ? Number(v) : undefined)
                }
              />
            </div>
          </Col>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>物资规格种类</span>
              <Select
                allowClear
                placeholder="请选择物资规格种类"
                className="min-w-0 flex-1"
                options={propertyOpts}
                value={draft.materialsPropertyId}
                onChange={(v) => {
                  setDraftField('materialsPropertyId', v ?? undefined);
                  setDraftField('materialsPropertyValueId', undefined);
                }}
              />
            </div>
          </Col>
        </Row>
        <Row gutter={[16, 0]}>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>物资规格</span>
              <Select
                allowClear
                placeholder="请选择物资规格"
                className="min-w-0 flex-1"
                disabled={draft.materialsPropertyId == null}
                options={valueOpts}
                value={draft.materialsPropertyValueId}
                onChange={(v) => setDraftField('materialsPropertyValueId', v ?? undefined)}
              />
            </div>
          </Col>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>RFID</span>
              <Input
                allowClear
                placeholder="请输入RFID"
                className="min-w-0 flex-1"
                value={draft.rfid}
                onChange={(e) => setDraftField('rfid', e.target.value)}
                onPressEnter={handleQuery}
              />
            </div>
          </Col>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>供应商</span>
              <Input
                allowClear
                placeholder="请输入供应商"
                className="min-w-0 flex-1"
                value={draft.supplier}
                onChange={(e) => setDraftField('supplier', e.target.value)}
                onPressEnter={handleQuery}
              />
            </div>
          </Col>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>有效期截止</span>
              <DatePicker.RangePicker
                className="min-w-0 flex-1 [&_.ant-picker-input]:min-w-0"
                value={validityRangeValue}
                onChange={(vals) => {
                  const [s, e] = vals || [];
                  setDraft((d) => ({
                    ...d,
                    validityStart: s ? s.format('YYYY-MM-DD') : '',
                    validityEnd: e ? e.format('YYYY-MM-DD') : '',
                  }));
                }}
                placeholder={['开始日期', '结束日期']}
              />
            </div>
          </Col>
        </Row>
        <Row gutter={[16, 0]} align="middle">
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>是否在柜中</span>
              <Select
                allowClear
                placeholder="是否在柜中"
                className="min-w-0 flex-1"
                value={draft.inCabinet}
                onChange={(v) => setDraftField('inCabinet', v ?? undefined)}
                options={[
                  { value: 1, label: '是' },
                  { value: 0, label: '否' },
                ]}
              />
            </div>
          </Col>
          <Col xs={24} sm={12} lg={6}>
            <div className="flex min-w-0 items-center gap-2.5">
              <span className={filterLabelCls}>状态</span>
              <Select
                allowClear
                placeholder="物资状态"
                className="min-w-0 flex-1"
                value={draft.status}
                onChange={(v) => setDraftField('status', v ?? undefined)}
                options={[
                  { value: 0, label: '正常' },
                  { value: 1, label: '停用' },
                ]}
              />
            </div>
          </Col>
          <Col xs={24} sm={24} lg={12}>
            <div className="flex min-w-0 w-full flex-wrap items-center justify-start lg:min-h-[32px]">
              <Space size="small" wrap className="min-w-0 shrink-0">
                <Button type="primary" icon={<Search className="h-4 w-4" />} onClick={handleQuery}>
                  {t('common.search')}
                </Button>
                <Button icon={<RefreshCw className="h-4 w-4" />} onClick={resetQuery}>
                  {t('common.reset')}
                </Button>
                <Button type="primary" icon={<Plus />} onClick={() => openForm()}>
                  {t('common.addNew')}
                </Button>
                <Button
                  danger
                  icon={<Trash2 className="h-4 w-4" />}
                  disabled={selectedRowKeys.length === 0}
                  onClick={batchDelete}
                >
                  {t('common.batchDelete')}
                </Button>
              </Space>
            </div>
          </Col>
        </Row>
        </div>
      </div>
    </div>
  );

  const tableInner = (
    <>
      <MaterialTableCard flush={Boolean(embedded)}>
        <Table
          size="middle"
          rowKey={(r, i) => rowKey(r, i)}
          loading={loading}
          columns={columns}
          dataSource={list}
          pagination={false}
          scroll={{ x: 1360 }}
          rowSelection={{
            columnWidth: 48,
            selectedRowKeys,
            onChange: setSelectedRowKeys,
          }}
          rowClassName={(_, index) => (index !== undefined && index % 2 === 1 ? 'isolation-work-list-row-alt' : '')}
        />
      </MaterialTableCard>
      <MaterialPaginationBar
        flushTop={Boolean(embedded)}
        total={total}
        current={pageNo}
        pageSize={pageSize}
        onPageChange={setPageNo}
        loading={loading}
        listLength={list.length}
      />
    </>
  );

  const listSection = embedded ? (
    <div className="rounded-xl border border-gray-200/80 bg-white shadow-sm ring-1 ring-gray-100/80">
      {tableInner}
    </div>
  ) : (
    tableInner
  );

  const pageBody = (
    <>
      {toolbarCard}
      {listSection}

      <Modal
        title={editing ? '编辑' : '新增'}
        open={modalOpen}
        onCancel={() => setModalOpen(false)}
        footer={
          <div className="flex justify-end gap-2">
            <Button
              type="primary"
              loading={loading}
              onClick={() => {
                void submit().catch(() => {});
              }}
            >
              {t('common.confirm')}
            </Button>
            <Button onClick={() => setModalOpen(false)}>{t('common.cancel')}</Button>
          </div>
        }
        {...getMaterialFormModalProps(t, 960)}
        styles={{ body: { padding: '12px 24px 16px' } }}
      >
        <Form form={form} {...materialInfoModalFormLayout}>
          <Row gutter={16}>
            <Col span={12}>
              <Form.Item name="materialsCabinetId" label="绑定物资柜">
                <Select
                  allowClear={fixedCabinetId == null}
                  disabled={fixedCabinetId != null}
                  showSearch
                  optionFilterProp="label"
                  options={modalCabinetSelectOptions}
                  placeholder="请选择绑定物资柜"
                  onClear={() => form.setFieldValue('materialsCabinetId', 0)}
                />
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item name="materialsName" label="物资名称" rules={[{ required: true, message: '请输入物资名称' }]}>
                <Input allowClear placeholder="请输入物资名称" />
              </Form.Item>
            </Col>
          </Row>
          <Row gutter={16}>
            <Col span={12}>
              <Form.Item name="materialsTypeId" label="物资类型" rules={[{ required: true, message: '请选择物资类型' }]}>
                <TreeSelect
                  showSearch
                  treeDefaultExpandAll
                  treeLine={{ showLeafIcon: false }}
                  treeData={typeTreeData}
                  treeNodeFilterProp="title"
                  placeholder="选择物资类型"
                  className="w-full"
                />
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item name="materialsRfid" label="RFID">
                <Input allowClear placeholder="请输入物资RFID" />
              </Form.Item>
            </Col>
          </Row>
          <Row gutter={16}>
            <Col span={12}>
              <Form.Item name="supplier" label="供应商">
                <Input allowClear placeholder="请输入供应商" />
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item name="expirationDate" label="有效期截止">
                <DatePicker className="w-full" allowClear placeholder="选择日期" />
              </Form.Item>
            </Col>
          </Row>
          <Row gutter={16} align="top">
            <Col span={12}>
              <Form.Item name="properties" label="物资规格">
                <Input.TextArea
                  allowClear
                  placeholder="请输入物资规格"
                  rows={6}
                  maxLength={2000}
                  showCount
                  className="w-full"
                />
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item name="materialsPicture" label="物资图片">
                <UploadImg width="90px" height="90px" />
              </Form.Item>
            </Col>
          </Row>
        </Form>
      </Modal>
    </>
  );

  return embedded ? <div className="space-y-4">{pageBody}</div> : <MaterialPageRoot>{pageBody}</MaterialPageRoot>;
}
