import { DecimalUtils } from "../core/DecimalUtils";

/**
 * 农户重量计算器
 * 负责计算每个农户的净重和毛重
 */
export class SupplierWeightCalculator {
  private suppliers: BusinessAPI.OrderSupplier[];
  private initialEmptyWeight: number;
  private previousTotalWeight: number;

  constructor(suppliers: BusinessAPI.OrderSupplier[]) {
    this.suppliers = suppliers || [];
    this.initialEmptyWeight = this.suppliers[0]?.emptyWeight || 0;
    this.previousTotalWeight = this.initialEmptyWeight;
  }

  /**
   * 计算所有农户的重量信息
   * @returns 处理后的供应商列表
   */
  calculate(): BusinessAPI.OrderSupplier[] {
    if (!this.suppliers.length) {
      return this.suppliers;
    }

    for (let i = 0; i < this.suppliers.length; i++) {
      const supplier = this.suppliers[i];
      this.calculateSupplierWeight(supplier, i);
    }

    return this.suppliers;
  }

  /**
   * 计算单个供应商的重量
   */
  private calculateSupplierWeight(
    supplier: BusinessAPI.OrderSupplier,
    index: number,
  ): void {
    const isFirstSupplier = index === 0;
    const isLastSupplier = supplier.isLast;

    // 设置空磅重量
    this.setEmptyWeight(supplier, index);

    // 计算各类纸箱重量
    const weights = this.calculateAllBoxWeights(
      supplier.orderPackageList || [],
    );

    if (!supplier.isPaper) {
      // 不带纸箱包装的简化计算
      this.calculateNonPaperSupplier(supplier, weights.used);
    } else {
      // 纸箱包装的复杂计算
      this.calculatePaperSupplier(
        supplier,
        weights,
        isFirstSupplier,
        isLastSupplier,
      );
    }

    // 计算发票金额
    this.calculateInvoiceAmount(supplier);

    // 更新上一个供应商的总重量
    this.previousTotalWeight = supplier.totalWeight || 0;
  }

  /**
   * 设置空磅重量
   */
  private setEmptyWeight(
    supplier: BusinessAPI.OrderSupplier,
    index: number,
  ): void {
    if (index === 0) {
      // 第一个农户保持原有空磅重量
    } else {
      // 其他农户使用前一个农户的总磅重量
      supplier.emptyWeight = this.suppliers[index - 1]?.totalWeight || 0;
    }
  }

  /**
   * 计算所有类型的纸箱重量
   */
  private calculateAllBoxWeights(packages: BusinessAPI.OrderPackage[]) {
    return {
      used: this.calculateBoxWeightByType(packages, "USED"),
      extra: this.calculateBoxWeightByType(packages, "EXTRA"),
      remain: this.calculateBoxWeightByType(packages, "REMAIN"),
      extraUsed: this.calculateBoxWeightByType(packages, "EXTRA_USED"),
    };
  }

  /**
   * 计算非纸箱包装供应商的重量
   */
  private calculateNonPaperSupplier(
    supplier: BusinessAPI.OrderSupplier,
    usedBoxesWeight: number,
  ): void {
    if (supplier.type === "FARMER") {
      // 毛重 = (总磅 - 空磅) × 2
      supplier.grossWeight = DecimalUtils.multiply(
        DecimalUtils.subtract(
          supplier.totalWeight || 0,
          supplier.emptyWeight || 0,
        ),
        2,
      );
    }

    // 净重 = 毛重 - 使用纸箱重量
    supplier.netWeight = DecimalUtils.subtract(
      supplier.grossWeight || 0,
      usedBoxesWeight,
    );
  }

  /**
   * 计算纸箱包装供应商的重量
   */
  private calculatePaperSupplier(
    supplier: BusinessAPI.OrderSupplier,
    weights: { used: number; extra: number; remain: number; extraUsed: number },
    isFirstSupplier: boolean,
    isLastSupplier: boolean,
  ): void {
    const weightDiff = isFirstSupplier
      ? DecimalUtils.subtract(
          supplier.totalWeight || 0,
          this.initialEmptyWeight,
        )
      : DecimalUtils.subtract(
          supplier.totalWeight || 0,
          this.previousTotalWeight,
        );

    const weightDiffInJin = DecimalUtils.multiply(weightDiff, 2);

    if (isFirstSupplier && isLastSupplier) {
      // 单个农户情况
      supplier.netWeight = DecimalUtils.add(
        DecimalUtils.subtract(
          DecimalUtils.add(weightDiffInJin, weights.remain),
          weights.extraUsed,
        ),
      );
    } else if (isLastSupplier) {
      // 最后一个农户
      supplier.netWeight = DecimalUtils.add(
        DecimalUtils.subtract(weightDiffInJin, weights.extraUsed),
        weights.remain,
      );
    } else {
      // 中间农户（包括第一个但不是最后一个）
      supplier.netWeight = DecimalUtils.subtract(
        weightDiffInJin,
        weights.extra,
      );
    }

    // 毛重 = 净重 + 本次使用纸箱重量
    supplier.grossWeight = DecimalUtils.add(
      supplier.netWeight || 0,
      weights.used,
    );
  }
  /**
   * 获取报价的重量
   */
  private calculateQuoteWeight(supplier: BusinessAPI.OrderSupplier): number {
    console.log("quote weight:", supplier.pricingMethod);
    return supplier.pricingMethod === "BY_GROSS_WEIGHT"
      ? supplier.grossWeight
      : supplier.netWeight;
  }

  /**
   * 计算发票金额
   */
  private calculateInvoiceAmount(supplier: BusinessAPI.OrderSupplier): void {
    supplier.invoiceAmount = DecimalUtils.multiply(
      this.calculateQuoteWeight(supplier),
      supplier.purchasePrice || 0,
    );
  }

  /**
   * 根据类型计算纸箱总重量（斤）
   */
  private calculateBoxWeightByType(
    packages: BusinessAPI.OrderPackage[],
    boxType?: string,
  ): number {
    const filteredPackages = boxType
      ? packages.filter((pkg) => pkg.boxType === boxType)
      : packages;

    return filteredPackages.reduce((total, pkg) => {
      const weight = DecimalUtils.multiply(
        pkg.boxCount || 0,
        pkg.boxProductWeight || 0,
      );
      return DecimalUtils.add(total, weight);
    }, 0);
  }

  /**
   * 获取计算后的供应商列表
   */
  getSuppliers(): BusinessAPI.OrderSupplier[] {
    return this.suppliers;
  }

  /**
   * 获取指定供应商的净重
   */
  getSupplierNetWeight(supplierId: string | number): number {
    const supplier = this.suppliers.find((s) => s.supplierId === supplierId);
    return supplier?.netWeight || 0;
  }

  /**
   * 获取指定供应商的毛重
   */
  getSupplierGrossWeight(supplierId: string | number): number {
    const supplier = this.suppliers.find((s) => s.supplierId === supplierId);
    return supplier?.grossWeight || 0;
  }

  /**
   * 获取总净重
   */
  getTotalNetWeight(): number {
    return this.suppliers.reduce((total, supplier) => {
      return DecimalUtils.add(total, supplier.netWeight || 0);
    }, 0);
  }

  /**
   * 获取总毛重
   */
  getTotalGrossWeight(): number {
    return this.suppliers.reduce((total, supplier) => {
      return DecimalUtils.add(total, supplier.grossWeight || 0);
    }, 0);
  }

  /**
   * 获取总发票金额
   */
  getTotalInvoiceAmount(): number {
    return this.suppliers.reduce((total, supplier) => {
      return DecimalUtils.add(total, supplier.invoiceAmount || 0);
    }, 0);
  }

  /**
   * 验证计算结果的合理性
   */
  validate(): { isValid: boolean; errors: string[] } {
    const errors: string[] = [];

    for (const supplier of this.suppliers) {
      if ((supplier.netWeight || 0) < 0) {
        errors.push(`供应商 ${supplier.name} 的净重为负数`);
      }
      if ((supplier.grossWeight || 0) < 0) {
        errors.push(`供应商 ${supplier.name} 的毛重为负数`);
      }
      if ((supplier.grossWeight || 0) < (supplier.netWeight || 0)) {
        errors.push(`供应商 ${supplier.name} 的毛重小于净重`);
      }
    }

    return {
      isValid: errors.length === 0,
      errors,
    };
  }
}
