import type { MesWmMaterialStockApi } from '#/api/mes/wm/materialstock';

import { getBagCodeByCode, resolveTraceType } from '#/api/mes/pro/bagCode';
import { getBatchByCode } from '#/api/mes/pro/batch';
import { getPalletByCode } from '#/api/mes/pro/pallet';
import { getMaterialStockPage } from '#/api/mes/wm/materialstock';

import { extractCode } from './traceCode';

export type TraceType = 'bag' | 'batch' | 'pallet';

export interface TraceObject {
  bagCount?: number;
  bagQuantity?: number;
  batchCode?: string;
  batchId?: number;
  batchStatus?: number;
  businessCode?: string;
  code?: string;
  id?: number;
  inboundBagQuantity?: number;
  inboundTime?: string;
  itemId?: number;
  itemName?: string;
  lineName?: string;
  palletCode?: string;
  palletId?: number;
  pendingBagQuantity?: number;
  produceDate?: string;
  status?: number;
  tempCode?: string;
  unitMeasureName?: string;
}

export interface TraceResult {
  code: string;
  data: TraceObject;
  type: TraceType;
}

/** 解析扫描原文，按码类型查询袋码 / 托盘 / 批次对象。 */
export async function lookupTrace(raw: string): Promise<TraceResult> {
  const code = extractCode(raw);
  const type = (await resolveTraceType(code)) as TraceType | null;
  if (!type) {
    throw new Error('未找到对应袋码、托盘或批次');
  }
  const fetchers: Record<TraceType, (value: string) => Promise<TraceObject>> = {
    bag: getBagCodeByCode,
    batch: getBatchByCode,
    pallet: getPalletByCode,
  };
  const data = await fetchers[type](code);
  if (!data?.id) {
    throw new Error('未找到对象信息');
  }
  return { code, data, type };
}

/** 扫码对象可带入单据的数量：袋码按 1 袋，托盘按已装袋数，批次按批次袋数。 */
export function traceQuantity(trace: TraceResult): number | undefined {
  if (trace.type === 'bag') {
    return 1;
  }
  if (trace.type === 'pallet') {
    return trace.data.bagCount;
  }
  return trace.data.bagQuantity;
}

/** 按扫码对象的物料与批次查找对应库存记录，供需要选择库存记录的单据带出明细。 */
export async function findMaterialStocks(
  trace: TraceResult,
  options: { stockState?: number; virtualFilter?: string } = {},
): Promise<MesWmMaterialStockApi.MaterialStock[]> {
  if (!trace.data.itemId) {
    return [];
  }
  const result = await getMaterialStockPage({
    pageNo: 1,
    pageSize: 50,
    batchCode: trace.data.batchCode,
    itemId: trace.data.itemId,
    ...options,
  });
  return result.list;
}
