/** 兼容 MyBatis-Page / 自定义包装 / 拦截器未完全解包等结构 */
export function pickRecords(data: any): any[] {
  if (data == null) return [];
  if (Array.isArray(data)) return data;
  const inner = data.data;
  const candidates = [
    data.records,
    data.list,
    data.rows,
    data.items,
    inner?.records,
    inner?.list,
    inner?.rows,
    data.result?.records,
    data.result?.list,
    data.page?.records,
    data.page?.list,
  ];
  for (const c of candidates) {
    if (Array.isArray(c)) return c;
  }
  return [];
}

export function pickTotal(data: any): number {
  if (data == null || typeof data !== 'object') return 0;
  const inner = data.data;
  const raw =
    data.total ??
    data.totalCount ??
    data.totalRow ??
    inner?.total ??
    inner?.totalCount ??
    data.page?.total ??
    data.result?.total;
  const n = Number(raw);
  return Number.isFinite(n) ? n : 0;
}

/** 同时传 pageNo/pageSize 与 current/size，兼容不同后端分页参数名 */
export function buildPageParams(pageNo: number, pageSize: number, extra?: Record<string, any>) {
  return {
    pageNo,
    pageSize,
    current: pageNo,
    size: pageSize,
    limit: pageSize,
    ...(extra || {}),
  };
}

/** getMaterialsTypePage 等接口 pageSize 上限为 100 */
export const MATERIALS_TYPE_PAGE_SIZE_MAX = 100;

/**
 * 按每页最多 {@link MATERIALS_TYPE_PAGE_SIZE_MAX} 条拉取物资类型全量，避免单次 pageSize 超限。
 */
export async function fetchAllMaterialTypes(
  listType: (params: Record<string, any>) => Promise<any>,
  extra?: Record<string, any>,
): Promise<any[]> {
  const pageSize = MATERIALS_TYPE_PAGE_SIZE_MAX;
  const all: any[] = [];
  let pageNo = 1;
  const maxPages = 500;
  while (pageNo <= maxPages) {
    const res = await listType({
      ...buildPageParams(pageNo, pageSize),
      ...extra,
    });
    const batch = pickRecords(res);
    all.push(...batch);
    if (batch.length < pageSize) break;
    const total = pickTotal(res);
    if (total > 0 && all.length >= total) break;
    pageNo += 1;
  }
  return all;
}

/** Ant Design TreeSelect 的物资类型节点 */
export type MaterialTypeTreeNode = {
  title: string;
  value: number;
  key: number;
  children?: MaterialTypeTreeNode[];
};

function materialTypeRowId(row: any): number | null {
  /** 与 handleTree(flat, 'id', 'parentId') 一致：parentId 引用的是 id */
  const n = Number(row?.id ?? row?.materialsTypeId);
  return Number.isFinite(n) && n > 0 ? n : null;
}

function materialTypeParentId(row: any, idSet: Set<number>): number {
  const raw =
    row?.parentId ??
    row?.parent_id ??
    row?.materialsParentId ??
    row?.parentMaterialsTypeId ??
    row?.pid;
  const n = Number(raw);
  if (!Number.isFinite(n) || n <= 0) return 0;
  return idSet.has(n) ? n : 0;
}

function materialTypeDisplayName(row: any): string {
  return String(row?.materialsTypeName ?? row?.typeName ?? row?.name ?? '').trim();
}

/**
 * 将分页拉平的物资类型列表转为 TreeSelect 用的父子树（与旧版 el-tree-select 一致）。
 * 同 id 多行时保留首次出现的一条。
 */
export function buildMaterialTypeTreeData(flatRows: any[]): MaterialTypeTreeNode[] {
  const seen = new Set<number>();
  const rows: any[] = [];
  for (const row of flatRows) {
    const id = materialTypeRowId(row);
    if (id == null || seen.has(id)) continue;
    seen.add(id);
    rows.push(row);
  }

  const idSet = new Set<number>();
  for (const row of rows) {
    const id = materialTypeRowId(row);
    if (id != null) idSet.add(id);
  }

  const nodeById = new Map<number, MaterialTypeTreeNode>();
  for (const row of rows) {
    const id = materialTypeRowId(row);
    if (id == null) continue;
    const name = materialTypeDisplayName(row);
    if (!name) continue;
    if (!nodeById.has(id)) {
      nodeById.set(id, { title: name, value: id, key: id });
    }
  }

  const linkedAsChild = new Set<number>();
  for (const row of rows) {
    const id = materialTypeRowId(row);
    if (id == null || !nodeById.has(id)) continue;
    const pid = materialTypeParentId(row, idSet);
    if (pid <= 0 || pid === id) continue;
    const parent = nodeById.get(pid);
    const child = nodeById.get(id);
    if (!parent || !child) continue;
    if (!parent.children) parent.children = [];
    parent.children.push(child);
    linkedAsChild.add(id);
  }

  const roots: MaterialTypeTreeNode[] = [];
  for (const id of nodeById.keys()) {
    if (!linkedAsChild.has(id)) {
      const n = nodeById.get(id)!;
      roots.push(n);
    }
  }

  const pruneEmptyChildren = (nodes: MaterialTypeTreeNode[]) => {
    for (const node of nodes) {
      if (node.children?.length) {
        pruneEmptyChildren(node.children);
      } else {
        delete node.children;
      }
    }
  };
  pruneEmptyChildren(roots);

  return roots;
}

/** getMaterialsPropertyValuePage 等接口 pageSize 上限为 100 */
export const MATERIALS_PROPERTY_VALUE_PAGE_SIZE_MAX = 100;

/**
 * 按每页最多 {@link MATERIALS_PROPERTY_VALUE_PAGE_SIZE_MAX} 条拉取某规格下的规格值全量。
 */
export async function fetchAllPropertyValues(
  listPage: (params: Record<string, any>) => Promise<any>,
  extra?: Record<string, any>,
): Promise<any[]> {
  const pageSize = MATERIALS_PROPERTY_VALUE_PAGE_SIZE_MAX;
  const all: any[] = [];
  let pageNo = 1;
  const maxPages = 500;
  while (pageNo <= maxPages) {
    const res = await listPage({
      ...buildPageParams(pageNo, pageSize),
      ...extra,
    });
    const batch = pickRecords(res);
    all.push(...batch);
    if (batch.length < pageSize) break;
    const total = pickTotal(res);
    if (total > 0 && all.length >= total) break;
    pageNo += 1;
  }
  return all;
}

/** getWorkstationPage（岗位/区域树）pageSize 上限为 100 */
export const WORKSTATION_PAGE_SIZE_MAX = 100;

/**
 * 按每页最多 {@link WORKSTATION_PAGE_SIZE_MAX} 条拉取岗位/工作站全量，避免单次 pageSize 超限。
 */
export async function fetchAllWorkstations(
  listPage: (params: Record<string, any>) => Promise<any>,
  extra?: Record<string, any>,
): Promise<any[]> {
  const pageSize = WORKSTATION_PAGE_SIZE_MAX;
  const all: any[] = [];
  let pageNo = 1;
  const maxPages = 500;
  while (pageNo <= maxPages) {
    const res = await listPage({
      ...buildPageParams(pageNo, pageSize),
      ...extra,
    });
    const batch = pickRecords(res);
    all.push(...batch);
    if (batch.length < pageSize) break;
    const total = pickTotal(res);
    if (total > 0 && all.length >= total) break;
    pageNo += 1;
  }
  return all;
}

export function downloadBlob(blob: Blob, filename: string) {
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  window.URL.revokeObjectURL(url);
}
