import { describe, it } from "vitest";
import { createMockDb } from "../../../testing/index";
import type { Transaction } from "../generated/kysely-tailordb";
import { InvalidOrderStatusError, OrderNotClosableError } from "../lib/errors.generated";
import { confirmedSalesOrder } from "../testing/fixtures";
import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
import { run } from "./closeSalesOrder";

describe("closeSalesOrder", () => {
  it("closes an order with no remaining open balance", async () => {
    const { db, spies } = createMockDb<Transaction>();
    spies.select
      .mockReturnValueOnce(confirmedSalesOrder)
      .mockReturnValueOnce([{ quantity: 10, shippedQuantity: 10, invoicedQuantity: 10 }]);
    spies.update.mockReturnValueOnce({ ...confirmedSalesOrder, status: "CLOSED" as const });

    const result = await run(db, { salesOrderId: confirmedSalesOrder.id }, commandCtx);

    expectOk(result);
  });

  it("throws when remaining quantity is still open", async () => {
    const { db, spies } = createMockDb<Transaction>();
    spies.select
      .mockReturnValueOnce(confirmedSalesOrder)
      .mockReturnValueOnce([{ quantity: 10, shippedQuantity: 10, invoicedQuantity: 5 }]);

    const result = await run(db, { salesOrderId: confirmedSalesOrder.id }, commandCtx);

    expectErr(result, OrderNotClosableError);
  });

  it("throws when order status does not allow closure", async () => {
    const { db, spies } = createMockDb<Transaction>();
    spies.select.mockReturnValueOnce({ ...confirmedSalesOrder, status: "DRAFT" });

    const result = await run(db, { salesOrderId: confirmedSalesOrder.id }, commandCtx);

    expectErr(result, InvalidOrderStatusError);
  });
});
