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

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

const MATERIALS_CABINET_LIST_PARAMS = buildPageParams(1, -1);

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

/** 与旧版 coll/index.vue formatLoanDuration 一致 */
function formatLoanDurationText(row: any): string {
  const duration = String(firstDefined(row, ['loanDuration', 'duration', 'borrowDuration']) ?? '').trim();
  if (!duration) return '—';
  const s = duration.replace(/^0小时\s*/, '').replace(/^0分\s*/, '').trim();
  return s || '—';
}

const LOAN_STATE_MAP: Record<number, { label: string; color: string }> = {
  0: { label: '在柜', color: 'blue' },
  1: { label: '已领用', color: 'processing' },
  2: { label: '待归还', color: 'warning' },
  3: { label: '已归还', color: 'success' },
};

/** 兼容 camelCase / snake_case / 字符串数字（与旧版 dict-tag + 数值状态一致） */
function getLoanStateRaw(row: any): unknown {
  if (!row || typeof row !== 'object') return undefined;
  const code =
    row.loanState ??
    row.loan_state ??
    row.status ??
    row.borrowState ??
    row.borrow_state ??
    row.loanStatus ??
    row.loan_status;
  if (code !== undefined && code !== null && code !== '') return code;
  return row.loanStateName ?? row.loan_state_name ?? row.loanStateStr;
}

function renderLoanStateCell(_: unknown, row: any) {
  const raw = getLoanStateRaw(row);
  if (raw === undefined || raw === null || raw === '') {
    return <span className="text-gray-400">—</span>;
  }
  if (typeof raw === 'string' && raw.trim() !== '' && Number.isNaN(Number(raw))) {
    const t = raw.trim();
    const byLabel: Record<string, string> = {
      在柜: 'blue',
      已领用: 'processing',
      待归还: 'warning',
      已归还: 'success',
    };
    return <Tag color={byLabel[t] ?? 'default'}>{t}</Tag>;
  }
  const n = Number(raw);
  if (!Number.isFinite(n)) {
    return <Tag color="default">{String(raw)}</Tag>;
  }
  const item = LOAN_STATE_MAP[n];
  return <Tag color={item?.color ?? 'default'}>{item?.label ?? String(raw)}</Tag>;
}

type LoanDraft = {
  loanFromId?: number;
  materialsName: string;
  materialsTypeId?: number;
  loanUserName: string;
  restitutionUserName: string;
  status?: string;
  loanRange: [Dayjs, Dayjs] | null;
  restitutionRange: [Dayjs, Dayjs] | null;
};

function emptyDraft(fixedCabinetId?: number): LoanDraft {
  return {
    materialsName: '',
    loanUserName: '',
    restitutionUserName: '',
    status: undefined,
    loanRange: null,
    restitutionRange: null,
    ...(fixedCabinetId != null && Number.isFinite(Number(fixedCabinetId))
      ? { loanFromId: Number(fixedCabinetId) }
      : {}),
  };
}

/** 领取归还列表查询参数（与旧版 LoanApi.listLoan + coll/index.vue 对齐，并附带 cabinetId 等别名以兼容后端） */
function buildLoanListParams(
  pageNo: number,
  pageSize: number,
  applied: LoanDraft,
  fixedCabinetId?: number,
): Record<string, any> {
  const q: Record<string, any> = { ...buildPageParams(pageNo, pageSize) };
  if (applied.materialsName?.trim()) q.materialsName = applied.materialsName.trim();
  if (applied.materialsTypeId != null && Number.isFinite(applied.materialsTypeId)) {
    q.materialsTypeId = applied.materialsTypeId;
  }
  if (applied.loanUserName?.trim()) q.loanUserName = applied.loanUserName.trim();
  if (applied.restitutionUserName?.trim()) q.restitutionUserName = applied.restitutionUserName.trim();
  if (applied.status != null && applied.status !== '') q.status = applied.status;

  const cabinet =
    fixedCabinetId != null && Number.isFinite(Number(fixedCabinetId))
      ? Number(fixedCabinetId)
      : applied.loanFromId != null && Number.isFinite(Number(applied.loanFromId))
        ? Number(applied.loanFromId)
        : undefined;
  if (cabinet != null) {
    q.loanFromId = cabinet;
    q.cabinetId = cabinet;
  }

  if (applied.loanRange?.[0] && applied.loanRange[1]) {
    q.loanTimeStart = applied.loanRange[0].format('YYYY-MM-DD HH:mm:ss');
    q.loanTimeEnd = applied.loanRange[1].format('YYYY-MM-DD HH:mm:ss');
  }
  if (applied.restitutionRange?.[0] && applied.restitutionRange[1]) {
    q.restitutionTimeStart = applied.restitutionRange[0].format('YYYY-MM-DD HH:mm:ss');
    q.restitutionTimeEnd = applied.restitutionRange[1].format('YYYY-MM-DD HH:mm:ss');
  }
  return q;
}

export default function MaterialLoanPage({ fixedCabinetId, embedded, embeddedTabBar }: MaterialLoanPageProps = {}) {
  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<LoanDraft>(() => emptyDraft(fixedCabinetId));
  const [applied, setApplied] = useState<LoanDraft>(() => emptyDraft(fixedCabinetId));

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

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

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

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

  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([]);
      }
    })();
  }, []);

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

  const fetchList = useCallback(async () => {
    setLoading(true);
    try {
      const params = buildLoanListParams(pageNo, pageSize, applied, fixedCabinetId);
      const res = await materialLoanApi.listLoan(params);
      setList(pickRecords(res));
      setTotal(pickTotal(res));
    } catch (e: any) {
      toast.error(e?.message || t('common.operationFailed'));
    } finally {
      setLoading(false);
    }
  }, [pageNo, pageSize, applied, fixedCabinetId, t]);

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

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

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

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

  /** 与旧版 handleQueryStatus：筛选超时未还（status = '2'） */
  const handleOverdueNotReturned = () => {
    setDraft((d) => ({ ...d, status: '2' }));
    setApplied((a) => ({ ...a, status: '2' }));
    setPageNo(1);
  };

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

  const columns: ColumnsType<any> = useMemo(() => {
    const cols: ColumnsType<any> = [];
    if (!hideCabinetColumn) {
      cols.push({
        title: '物资柜',
        align: 'center',
        width: 120,
        render: (_, row) =>
          String(firstDefined(row, ['loanFromName', 'cabinetName', 'materialsCabinetName', 'cabinet']) ?? '—'),
      });
    }
    cols.push(
      {
        title: '物资编号',
        dataIndex: 'materialsId',
        align: 'center',
        width: 96,
        render: (v, row) => String(firstDefined(row, ['materialsId', 'materialsCode', 'id']) ?? v ?? '—'),
      },
      { title: '物资名称', dataIndex: 'materialsName', ellipsis: true, align: 'center', width: 120 },
      {
        title: '物资类型',
        align: 'center',
        width: 140,
        ellipsis: true,
        render: (_, row) => String(firstDefined(row, ['materialsTypeName', 'typeName']) ?? '—'),
      },
      {
        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: '领取人', dataIndex: 'loanUserName', width: 100, align: 'center' },
      { title: '领取时间', dataIndex: 'loanTime', width: 170, align: 'center' },
      {
        title: '归还人',
        width: 100,
        align: 'center',
        render: (_, row) => String(firstDefined(row, ['restitutionUserName', 'returnUserName']) ?? '—'),
      },
      {
        title: '归还时间',
        width: 170,
        align: 'center',
        render: (_, row) =>
          String(
            firstDefined(row, ['actualRestitutionTime', 'actualReturnTime', 'restitutionTime', 'returnTime']) ?? '—',
          ),
      },
      {
        title: '借出时长',
        width: 120,
        align: 'center',
        render: (_, row) => formatLoanDurationText(row),
      },
      {
        title: '状态',
        key: 'loanState',
        width: 110,
        align: 'center',
        render: (_, row) => renderLoanStateCell(_, row),
      },
    );
    return cols;
  }, [hideCabinetColumn]);

  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, 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={fixedCabinetId == null}
                  disabled={fixedCabinetId != null}
                  placeholder="请选择物资柜"
                  className="min-w-0 flex-1"
                  options={
                    fixedCabinetId != null
                      ? [
                          {
                            value: Number(fixedCabinetId),
                            label:
                              cabinetNameMap.get(Number(fixedCabinetId))?.trim() ||
                              `物资柜 #${fixedCabinetId}`,
                          },
                        ]
                      : cabinetOpts
                  }
                  value={draft.loanFromId}
                  onChange={(v) => setDraftField('loanFromId', 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>
                <Input
                  allowClear
                  placeholder="请输入领取人"
                  className="min-w-0 flex-1"
                  value={draft.loanUserName}
                  onChange={(e) => setDraftField('loanUserName', 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>
                <DatePicker.RangePicker
                  showTime
                  className="min-w-0 flex-1 [&_.ant-picker-input]:min-w-0"
                  value={draft.loanRange}
                  onChange={(vals) => {
                    const a = vals?.[0];
                    const b = vals?.[1];
                    setDraftField('loanRange', a && b ? [a, b] : null);
                  }}
                  placeholder={['开始日期', '结束日期']}
                />
              </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.restitutionUserName}
                  onChange={(e) => setDraftField('restitutionUserName', 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
                  showTime
                  className="min-w-0 flex-1 [&_.ant-picker-input]:min-w-0"
                  value={draft.restitutionRange}
                  onChange={(vals) => {
                    const a = vals?.[0];
                    const b = vals?.[1];
                    setDraftField('restitutionRange', a && b ? [a, b] : null);
                  }}
                  placeholder={['开始日期', '结束日期']}
                />
              </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: '已领用' },
                    { value: '2', label: '待归还' },
                    { value: '3', label: '已归还' },
                  ]}
                />
              </div>
            </Col>
          </Row>
          <Row gutter={[16, 16]} align="middle">
            <Col xs={24} sm={24} lg={12}>
              <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>
                {fixedCabinetId == null ? (
                  <Button danger ghost icon={<Clock className="h-4 w-4" />} onClick={handleOverdueNotReturned}>
                    超时未还
                  </Button>
                ) : null}
              </Space>
            </Col>
          </Row>
        </div>
      </div>
    </div>
  );

  const tableInner = (
    <>
      <MaterialTableCard flush={Boolean(embedded)}>
        <Table
          rowKey={(r) => r.materialsLoanId ?? r.id ?? `${r.materialsId}-${r.loanTime}`}
          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}
      />
    </>
  );

  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}
    </>
  );

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