import React, { useCallback, useEffect, useMemo, useState } from 'react';
import type { Dayjs } from 'dayjs';
import { Table, Button, Row, Col, Select, Input, TreeSelect, DatePicker, Space, Image } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { Search, RefreshCw } from 'lucide-react';
import { toast } from 'sonner';
import { useTranslation } from 'react-i18next';
import { materialReplaceApi } from '../../../api/material/replace';
import { materialLockerApi } from '../../../api/material/lockers';
import { materialTypeApi } from '../../../api/material/type';
import {
  pickRecords,
  pickTotal,
  buildPageParams,
  fetchAllMaterialTypes,
  buildMaterialTypeTreeData,
} from '../materialListUtils';
import { MATERIAL_REPLACEMENT_RECORD_PRESET_KEY } from '../materialPvNav';
import { MaterialPageRoot, MaterialTableCard, MaterialPaginationBar } from '../MaterialPageLayout';

const MATERIALS_CABINET_LIST_PARAMS = buildPageParams(1, -1);

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

function mapCabinetListToFilterOptions(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: '空' }];
}

function digitsOnly(s: string) {
  return s.replace(/\D/g, '');
}

type RecordDraft = {
  cabinetId?: number;
  materialsTypeId?: number;
  oldMaterialsId: string;
  oldMaterialsRfid: string;
  newMaterialsId: string;
  newMaterialsRfid: string;
  changeUserName: string;
  changeTimeRange: [Dayjs, Dayjs] | null;
};

function emptyDraft(fixedCabinetId?: number): RecordDraft {
  return {
    oldMaterialsId: '',
    oldMaterialsRfid: '',
    newMaterialsId: '',
    newMaterialsRfid: '',
    changeUserName: '',
    changeTimeRange: null,
    ...(fixedCabinetId != null && Number.isFinite(Number(fixedCabinetId))
      ? { cabinetId: Number(fixedCabinetId) }
      : {}),
  };
}

export interface MaterialReplacementRecordPageProps {
  fixedCabinetId?: number;
  embedded?: boolean;
  embeddedTabBar?: React.ReactNode;
}

export default function MaterialReplacementRecordPage({
  fixedCabinetId,
  embedded,
  embeddedTabBar,
}: MaterialReplacementRecordPageProps = {}) {
  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, setPageSize] = useState(10);
  const [draft, setDraft] = useState<RecordDraft>(() => emptyDraft(fixedCabinetId));
  const [applied, setApplied] = useState<RecordDraft>(() => emptyDraft(fixedCabinetId));
  const [appliedCheckRecordId, setAppliedCheckRecordId] = useState<number | undefined>();
  const [cabinetOpts, setCabinetOpts] = useState<{ value: number; label: string }[]>([]);
  const [materialTypeRows, setMaterialTypeRows] = useState<any[]>([]);

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

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

  const cabinetLocked = fixedCabinetId != null && Number.isFinite(Number(fixedCabinetId));

  useEffect(() => {
    if (embedded) return;
    try {
      const raw = sessionStorage.getItem(MATERIAL_REPLACEMENT_RECORD_PRESET_KEY);
      if (!raw) return;
      const p = JSON.parse(raw);
      sessionStorage.removeItem(MATERIAL_REPLACEMENT_RECORD_PRESET_KEY);
      const rid = p?.recordId ?? p?.checkRecordId;
      if (rid != null && Number.isFinite(Number(rid))) {
        setAppliedCheckRecordId(Number(rid));
        setPageNo(1);
      }
    } catch {
      sessionStorage.removeItem(MATERIAL_REPLACEMENT_RECORD_PRESET_KEY);
    }
  }, [embedded]);

  useEffect(() => {
    (async () => {
      try {
        const res = await materialLockerApi.listMaterialsCabinet(MATERIALS_CABINET_LIST_PARAMS);
        setCabinetOpts(mapCabinetListToFilterOptions(pickRecords(res)));
      } catch {
        try {
          const res2 = await materialLockerApi.listMaterialsCabinet(buildPageParams(1, 500));
          setCabinetOpts(mapCabinetListToFilterOptions(pickRecords(res2)));
        } catch {
          setCabinetOpts([]);
        }
      }
    })();
  }, []);

  useEffect(() => {
    (async () => {
      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([]);
      }
    })();
  }, []);

  useEffect(() => {
    if (cabinetLocked) {
      const id = Number(fixedCabinetId);
      setDraft((d) => ({ ...d, cabinetId: id }));
      setApplied((a) => ({ ...a, cabinetId: id }));
    }
  }, [fixedCabinetId, cabinetLocked]);

  const buildListParams = useCallback(() => {
    const q: Record<string, any> = {
      ...buildPageParams(pageNo, pageSize),
    };
    const cab =
      cabinetLocked && fixedCabinetId != null
        ? Number(fixedCabinetId)
        : applied.cabinetId != null && Number.isFinite(applied.cabinetId) && Number(applied.cabinetId) > 0
          ? Number(applied.cabinetId)
          : undefined;
    if (cab != null) q.cabinetId = cab;
    if (applied.materialsTypeId != null) q.materialsTypeId = applied.materialsTypeId;
    const oldId = digitsOnly(applied.oldMaterialsId);
    if (oldId) q.oldMaterialsId = Number(oldId);
    if (applied.oldMaterialsRfid?.trim()) q.oldMaterialsRfid = applied.oldMaterialsRfid.trim();
    const newId = digitsOnly(applied.newMaterialsId);
    if (newId) q.newMaterialsId = Number(newId);
    if (applied.newMaterialsRfid?.trim()) q.newMaterialsRfid = applied.newMaterialsRfid.trim();
    if (applied.changeUserName?.trim()) q.changeUserName = applied.changeUserName.trim();
    if (applied.changeTimeRange?.[0] && applied.changeTimeRange[1]) {
      q.startTime = applied.changeTimeRange[0].format('YYYY-MM-DD HH:mm:ss');
      q.endTime = applied.changeTimeRange[1].format('YYYY-MM-DD HH:mm:ss');
    }
    if (appliedCheckRecordId != null && Number.isFinite(appliedCheckRecordId)) {
      q.recordId = appliedCheckRecordId;
      q.checkRecordId = appliedCheckRecordId;
      q.materialsCheckRecordId = appliedCheckRecordId;
    }
    return q;
  }, [pageNo, pageSize, applied, cabinetLocked, fixedCabinetId, appliedCheckRecordId]);

  const fetchList = useCallback(async () => {
    setLoading(true);
    try {
      const res = await materialReplaceApi.listChangeRecord(buildListParams());
      setList(pickRecords(res));
      setTotal(pickTotal(res));
    } catch (e: any) {
      toast.error(e?.message || t('common.operationFailed'));
    } finally {
      setLoading(false);
    }
  }, [buildListParams, t]);

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

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

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

  const resetQuery = () => {
    const e = emptyDraft(fixedCabinetId);
    setDraft(e);
    setApplied(e);
    setAppliedCheckRecordId(undefined);
    setPageNo(1);
  };

  const columns: ColumnsType<any> = useMemo(
    () => [
      {
        title: '物资柜',
        width: 120,
        align: 'center',
        render: (_, row) => String(firstDefined(row, ['cabinetName', 'cabinet_name', 'materialsCabinetName']) ?? '—'),
      },
      {
        title: '物资类型',
        width: 120,
        align: 'center',
        ellipsis: true,
        render: (_, row) => String(firstDefined(row, ['materialsTypeName', 'typeName']) ?? '—'),
      },
      {
        title: '物资图片',
        width: 88,
        align: 'center',
        render: (_, row) => {
          const src = firstDefined(row, ['materialsTypePicture', 'materialsPicture', '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: '原物资编号',
        width: 100,
        align: 'center',
        render: (_, row) => String(firstDefined(row, ['oldMaterialsId', 'old_materials_id']) ?? '—'),
      },
      {
        title: '原物资名称',
        width: 120,
        align: 'center',
        ellipsis: true,
        render: (_, row) => String(firstDefined(row, ['oldMaterialsName', 'old_materials_name']) ?? '—'),
      },
      {
        title: '原RFID',
        width: 120,
        align: 'center',
        ellipsis: true,
        render: (_, row) => String(firstDefined(row, ['oldMaterialsRfid', 'oldMaterialsRFID', 'oldRfid']) ?? '—'),
      },
      {
        title: '新物资编号',
        width: 100,
        align: 'center',
        render: (_, row) => String(firstDefined(row, ['newMaterialsId', 'new_materials_id']) ?? '—'),
      },
      {
        title: '新物资名称',
        width: 120,
        align: 'center',
        ellipsis: true,
        render: (_, row) => String(firstDefined(row, ['newMaterialsName', 'new_materials_name']) ?? '—'),
      },
      {
        title: '新RFID',
        width: 120,
        align: 'center',
        ellipsis: true,
        render: (_, row) => String(firstDefined(row, ['newMaterialsRfid', 'newMaterialsRFID', 'newRfid']) ?? '—'),
      },
      {
        title: '更换人',
        width: 100,
        align: 'center',
        render: (_, row) =>
          String(firstDefined(row, ['changeUserName', 'change_user_name', 'changeUser', 'operatorName']) ?? '—'),
      },
      {
        title: '更换时间',
        width: 172,
        align: 'center',
        render: (_, row) =>
          String(firstDefined(row, ['changeDate', 'changeTime', 'change_time', 'createTime']) ?? '—'),
      },
    ],
    [],
  );

  const filterCard = (
    <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, 16]}>
            <Col xs={24} sm={12} lg={6}>
              <div className="flex min-w-0 items-center gap-2.5">
                <span className={filterLabelCls}>物资柜</span>
                <Select
                  allowClear={!cabinetLocked}
                  disabled={cabinetLocked}
                  placeholder="请选择物资柜"
                  className="min-w-0 flex-1"
                  options={cabinetOpts}
                  value={draft.cabinetId}
                  onChange={(v) => setDraftField('cabinetId', 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>
                <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>
                <Input
                  allowClear
                  placeholder="请输入原物资编号（数字格式）"
                  className="min-w-0 flex-1"
                  value={draft.oldMaterialsId}
                  onChange={(e) => setDraftField('oldMaterialsId', digitsOnly(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}>原RFID</span>
                <Input
                  allowClear
                  placeholder="请输入原RFID"
                  className="min-w-0 flex-1"
                  value={draft.oldMaterialsRfid}
                  onChange={(e) => setDraftField('oldMaterialsRfid', e.target.value)}
                  onPressEnter={handleQuery}
                />
              </div>
            </Col>
          </Row>
          <Row gutter={[16, 16]}>
            <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.newMaterialsId}
                  onChange={(e) => setDraftField('newMaterialsId', digitsOnly(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}>新RFID</span>
                <Input
                  allowClear
                  placeholder="请输入新RFID"
                  className="min-w-0 flex-1"
                  value={draft.newMaterialsRfid}
                  onChange={(e) => setDraftField('newMaterialsRfid', 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.changeUserName}
                  onChange={(e) => setDraftField('changeUserName', e.target.value)}
                  onPressEnter={handleQuery}
                />
              </div>
            </Col>
            <Col xs={24} sm={12} lg={9}>
              <div className="flex min-w-0 items-center gap-2.5">
                <span className={filterLabelCls}>更换时间</span>
                <DatePicker.RangePicker
                  showTime
                  className="min-w-0 flex-1 [&_.ant-picker-input]:min-w-0"
                  value={draft.changeTimeRange}
                  onChange={(vals) => {
                    const a = vals?.[0];
                    const b = vals?.[1];
                    setDraftField('changeTimeRange', a && b ? [a, b] : null);
                  }}
                  placeholder={['开始日期', '结束日期']}
                />
              </div>
            </Col>
            <Col flex="auto" className="min-w-0">
              <div className="ml-[20px] flex min-w-0 flex-wrap items-center">
                <Space size="small" wrap>
                  <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>
                </Space>
              </div>
            </Col>
          </Row>
        </div>
      </div>
    </div>
  );

  const tableInner = (
    <>
      <MaterialTableCard flush={Boolean(embedded)}>
        <Table
          rowKey={(r) => r.changeId ?? r.id ?? `${r.oldMaterialsId}-${r.newMaterialsId}-${r.changeDate}`}
          loading={loading}
          columns={columns}
          dataSource={list}
          pagination={false}
          scroll={{ x: 'max-content' }}
          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}
        onPageSizeChange={(size) => {
          setPageSize(size);
          setPageNo(1);
        }}
        showQuickJumper
      />
    </>
  );

  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 = (
    <>
      {filterCard}
      {listSection}
    </>
  );

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