/** biome-ignore-all lint/suspicious/noApproximativeNumericConstant: <explanation>great */
import NumberUtil from "./NumberUtil";

describe("NumberUtil", () => {
  describe("decimalPart", () => {
    test("returns decimal part of positive number", () => {
      expect(NumberUtil.decimalPart(3.14159)).toBe(0.14);
    });

    test("returns decimal part of negative number", () => {
      expect(NumberUtil.decimalPart(-3.14159)).toBe(-0.14);
    });

    test("returns 0 for whole number", () => {
      expect(NumberUtil.decimalPart(5)).toBe(0);
    });

    test("returns 0 for zero", () => {
      expect(NumberUtil.decimalPart(0)).toBe(0);
    });

    test("handles very small decimal parts", () => {
      expect(NumberUtil.decimalPart(1.001)).toBe(0);
    });

    test("handles decimal parts with multiple digits", () => {
      expect(NumberUtil.decimalPart(2.999)).toBe(1);
    });
  });

  describe("getValidNumber", () => {
    test("returns number when valid number is passed", () => {
      expect(NumberUtil.getValidNumber(42)).toBe(42);
    });

    test("returns number when valid string number is passed", () => {
      expect(NumberUtil.getValidNumber("42")).toBe(42);
    });

    test("returns number when valid float string is passed", () => {
      expect(NumberUtil.getValidNumber("3.14")).toBe(3.14);
    });

    test("returns null when null is passed", () => {
      expect(NumberUtil.getValidNumber(null)).toBe(null);
    });

    test("returns null when undefined is passed", () => {
      expect(NumberUtil.getValidNumber(undefined)).toBe(null);
    });

    test("returns null when empty string is passed", () => {
      expect(NumberUtil.getValidNumber("")).toBe(null);
    });

    test("returns null when invalid string is passed", () => {
      expect(NumberUtil.getValidNumber("abc")).toBe(null);
    });

    test("returns null when NaN is passed", () => {
      expect(NumberUtil.getValidNumber(Number.NaN)).toBe(null);
    });

    test("returns 0 when zero string is passed", () => {
      expect(NumberUtil.getValidNumber("0")).toBe(0);
    });

    test("handles negative numbers", () => {
      expect(NumberUtil.getValidNumber(-42)).toBe(-42);
      expect(NumberUtil.getValidNumber("-42")).toBe(-42);
    });

    test("handles floating point numbers", () => {
      expect(NumberUtil.getValidNumber(3.14159)).toBe(3.14159);
      expect(NumberUtil.getValidNumber("-3.14159")).toBe(-3.14159);
    });
  });

  describe("getValidNumberOrThrow", () => {
    test("returns number when valid number is passed", () => {
      expect(NumberUtil.getValidNumberOrThrow(42)).toBe(42);
    });

    test("returns number when valid string number is passed", () => {
      expect(NumberUtil.getValidNumberOrThrow("42")).toBe(42);
    });

    test("throws error when null is passed", () => {
      expect(() => NumberUtil.getValidNumberOrThrow(null)).toThrow(
        "Invalid number='null'",
      );
    });

    test("throws error when undefined is passed", () => {
      expect(() => NumberUtil.getValidNumberOrThrow(undefined)).toThrow(
        "Invalid number='undefined'",
      );
    });

    test("throws error when empty string is passed", () => {
      expect(() => NumberUtil.getValidNumberOrThrow("")).toThrow(
        "Invalid number=''",
      );
    });

    test("throws error when invalid string is passed", () => {
      expect(() => NumberUtil.getValidNumberOrThrow("abc")).toThrow(
        "Invalid number='abc'",
      );
    });

    test("throws error when NaN is passed", () => {
      expect(() => NumberUtil.getValidNumberOrThrow(Number.NaN)).toThrow(
        "Invalid number='NaN'",
      );
    });

    test("returns 0 when zero string is passed", () => {
      expect(NumberUtil.getValidNumberOrThrow("0")).toBe(0);
    });

    test("handles negative numbers", () => {
      expect(NumberUtil.getValidNumberOrThrow(-42)).toBe(-42);
      expect(NumberUtil.getValidNumberOrThrow("-42")).toBe(-42);
    });
  });
});
