import { Decimal } from "decimal.js";

/**
 * Decimal 工具类
 * 统一处理精度计算，避免重复的 Decimal 创建和配置
 */
export class DecimalUtils {
  private static readonly CONFIG = {
    precision: 20,
    rounding: Decimal.ROUND_HALF_UP,
    toExpNeg: -7,
    toExpPos: 21,
  };

  static {
    Decimal.set(this.CONFIG);
  }

  /**
   * 创建 Decimal 实例
   */
  static create(value: number | string | Decimal = 0): Decimal {
    return new Decimal(value || 0);
  }

  /**
   * 安全的乘法运算，保留0位小数
   */
  static multiply(a: number | string, b: number | string): number {
    return this.create(a).mul(b).toDecimalPlaces(0).toNumber();
  }

  /**
   * 安全的加法运算
   */
  static add(...values: (number | string)[]): number {
    return values.reduce(
      (sum, value) => this.create(sum).plus(value).toNumber(),
      0,
    ) as number;
  }

  /**
   * 安全的减法运算
   */
  static subtract(...values: (number | string)[]): number {
    if (values.length === 0) {
      return 0;
    }

    return values.reduce((result, value, index) => {
      // 第一个值作为初始值
      if (index === 0) {
        return this.create(result).plus(value).toNumber();
      }
      // 后续值进行减法运算
      return this.create(result).sub(value).toNumber();
    }, 0) as number;
  }

  /**
   * 安全的除法运算，处理除零情况
   */
  static divide(
    a: number | string,
    b: number | string,
    defaultValue = 0,
  ): number {
    if (!b || this.create(b).isZero()) {
      return defaultValue;
    }
    return this.create(a).div(b).toDecimalPlaces(2).toNumber();
  }

  /**
   * 计算百分比
   */
  static percentage(
    value: number | string,
    percent: number | string,
    decimalPlaces = 0,
  ): number {
    return this.create(value)
      .mul(percent)
      .div(100)
      .toDecimalPlaces(decimalPlaces)
      .toNumber();
  }

  /**
   * 保留指定小数位数
   */
  static toFixed(value: number | string, decimalPlaces = 2): string {
    return this.create(value).toFixed(decimalPlaces);
  }

  /**
   * 保留指定小数位数，返回数字
   */
  static toDecimalPlaces(value: number | string, decimalPlaces = 0): number {
    return this.create(value).toDecimalPlaces(decimalPlaces).toNumber();
  }
}
