import { Quantity } from "../quantity";

describe("Quantity", () => {
  describe("create", () => {
    it("debería crear una cantidad válida", () => {
      const result = Quantity.create({ amount: 100, scale: 2 });
      expect(result.isSuccess).toBe(true);
      expect(result.data.amount).toBe(100);
      expect(result.data.scale).toBe(2);
    });

    it("debería fallar si la escala es negativa", () => {
      const result = Quantity.create({ amount: 100, scale: -1 });
      expect(result.isFailure).toBe(true);
    });
  });

  describe("toNumber & toString", () => {
    it("debería convertir correctamente a número", () => {
      const quantity = Quantity.create({ amount: 150, scale: 2 }).data;
      expect(quantity.toNumber()).toBe(1.5);
    });

    it("debería convertir correctamente a string", () => {
      const quantity = Quantity.create({ amount: 123, scale: 2 }).data;
      expect(quantity.toString()).toBe("1.23");
    });
  });

  describe("increment", () => {
    it("debería incrementar en 1 si no se pasa otra cantidad", () => {
      const quantity = Quantity.create({ amount: 100, scale: 2 }).data;
      const incremented = quantity.increment().data;
      expect(incremented.amount).toBe(101);
      expect(incremented.scale).toBe(2);
    });

    it("debería sumar correctamente si tienen la misma escala", () => {
      const quantity1 = Quantity.create({ amount: 100, scale: 2 }).data;
      const quantity2 = Quantity.create({ amount: 50, scale: 2 }).data;

      const result = quantity1.increment(quantity2);
      expect(result.isSuccess).toBe(true);
      expect(result.data.amount).toBe(150);
    });

    it("debería fallar si las escalas son diferentes", () => {
      const quantity1 = Quantity.create({ amount: 100, scale: 2 }).data;
      const quantity2 = Quantity.create({ amount: 50, scale: 1 }).data;

      const result = quantity1.increment(quantity2);
      expect(result.isFailure).toBe(true);
    });
  });

  describe("decrement", () => {
    it("debería decrementar en 1 si no se pasa otra cantidad", () => {
      const quantity = Quantity.create({ amount: 100, scale: 2 }).data;
      const decremented = quantity.decrement().data;
      expect(decremented.amount).toBe(99);
    });

    it("debería restar correctamente si tienen la misma escala", () => {
      const quantity1 = Quantity.create({ amount: 100, scale: 2 }).data;
      const quantity2 = Quantity.create({ amount: 50, scale: 2 }).data;

      const result = quantity1.decrement(quantity2);
      expect(result.isSuccess).toBe(true);
      expect(result.data.amount).toBe(50);
    });

    it("debería fallar si las escalas son diferentes", () => {
      const quantity1 = Quantity.create({ amount: 100, scale: 2 }).data;
      const quantity2 = Quantity.create({ amount: 50, scale: 1 }).data;

      const result = quantity1.decrement(quantity2);
      expect(result.isFailure).toBe(true);
    });
  });

  describe("convertScale", () => {
    it("debería convertir correctamente a una nueva escala", () => {
      const quantity = Quantity.create({ amount: 100, scale: 2 }).data;
      const result = quantity.convertScale(1);
      expect(result.isSuccess).toBe(true);
      expect(result.data.amount).toBe(10);
      expect(result.data.scale).toBe(1);
    });

    it("debería fallar si la escala está fuera de rango", () => {
      const quantity = Quantity.create({ amount: 100, scale: 2 }).data;
      const result = quantity.convertScale(3);
      expect(result.isFailure).toBe(true);
    });
  });

  describe("hasSameScale", () => {
    it("debería retornar true si las escalas son iguales", () => {
      const quantity1 = Quantity.create({ amount: 100, scale: 2 }).data;
      const quantity2 = Quantity.create({ amount: 50, scale: 2 }).data;

      expect(quantity1.hasSameScale(quantity2)).toBe(true);
    });

    it("debería retornar false si las escalas son diferentes", () => {
      const quantity1 = Quantity.create({ amount: 100, scale: 2 }).data;
      const quantity2 = Quantity.create({ amount: 50, scale: 1 }).data;

      expect(quantity1.hasSameScale(quantity2)).toBe(false);
    });
  });
});
