/**
 * 与后端 format_price / PrescriptionService 中药计价口径一致
 */

export function parsePriceValue(value: unknown): number {
  if (value === null || value === undefined || value === '') {
    return 0;
  }
  const num = Number(value);
  return Number.isFinite(num) ? num : 0;
}

/**
 * 与后端 format_price 一致：第三位小数非 0 则分位进 1，再保留两位小数
 */
export function formatPriceLikeBackend(value: unknown): number {
  const price = parsePriceValue(value);
  let milli = Math.round(price * 1000);
  if (milli % 10 > 0) {
    milli += 10;
  }
  milli -= milli % 10;
  return Math.round((milli / 1000) * 100) / 100;
  // return milli / 1000;
}

/** 模拟 PHP bcmul 在指定 scale 下向零截断 */
function bcmulScale(a: unknown, b: unknown, scale: number): number {
  const product = parsePriceValue(a) * parsePriceValue(b);
  const factor = 10 ** scale;
  return Math.trunc(product * factor) / factor;
}

/** 模拟 PHP bcadd 在指定 scale 下向零截断 */
function bcaddScale(a: number, b: number, scale: number): number {
  const sum = a + b;
  const factor = 10 ** scale;
  return Math.trunc(sum * factor) / factor;
}

type ChineseDrugLine = {
  number?: number | string;
  price?: number | string;
};

/**
 * 中药商品总价（与 PrescriptionService::createChineseReprice 一致）
 * 每行：bcmul(dosage, bcmul(price, number, 3), 3)，累加后 format_price
 */
export function calculateChineseProductPriceLikeBackend(
  drugs: ChineseDrugLine[],
  dosage = 7,
): number {
  if (!drugs?.length) {
    return 0;
  }
  const dose = parsePriceValue(dosage);
  let total = 0;
  for (const drug of drugs) {
    const linePerDose = bcmulScale(drug.price, drug.number ?? 1, 3);
    const lineTotal = bcmulScale(dose, linePerDose, 3);
    total = bcaddScale(total, lineTotal, 3);
  }
  return formatPriceLikeBackend(total);
}

export function formatPriceDisplay(value: unknown): string {
  return formatPriceLikeBackend(value).toFixed(2);
}

type ProcessRuleLine = {
  calc_method?: number;
  price?: unknown;
};

/**
 * 计算委托调剂加工费（与移动端 PrescriptionCalculator.calculateProcessingFee 一致）
 * calc_method: 1=固定价格，2=按剂数，3=按数量
 */
export function calculateProcessingFee(
  processRule: ProcessRuleLine | null | undefined,
  dosage = 7,
  totalDrugQuantity = 0,
): number {
  if (!processRule?.calc_method) {
    return 0;
  }
  const price = parsePriceValue(processRule.price);
  const dose = parsePriceValue(dosage);
  const qty = parsePriceValue(totalDrugQuantity);
  switch (processRule.calc_method) {
    case 1:
      return price;
    case 2:
      return price * dose;
    case 3:
      return price * dose * qty;
    default:
      return 0;
  }
}
