import { describe, expect, it } from "vitest";
import { createMockDb } from "../../../testing/index";
import type { Transaction } from "../generated/kysely-tailordb";
import {
  EmptyOrderNotAllowedError,
  InvalidOrderStatusError,
  ShippingAddressRequiredError,
} from "../lib/errors.generated";
import { baseSalesOrder, baseSalesOrderLine } from "../testing/fixtures";
import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
import { run } from "./submitSalesOrder";

describe("submitSalesOrder", () => {
  it("submits a complete draft order", async () => {
    const { db, spies } = createMockDb<Transaction>();
    const submitted = {
      ...baseSalesOrder,
      status: "SUBMITTED",
      updatedAt: new Date("2024-01-02T00:00:00.000Z"),
    };
    spies.select.mockReturnValueOnce(baseSalesOrder).mockReturnValueOnce([baseSalesOrderLine]);
    spies.update.mockReturnValueOnce(submitted);

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

    const value = expectOk(result);
    expect(value.salesOrder.status).toBe("SUBMITTED");
  });

  it("throws when the order is not in DRAFT status", async () => {
    const { db, spies } = createMockDb<Transaction>();
    spies.select.mockReturnValueOnce({ ...baseSalesOrder, status: "SUBMITTED" });

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

    expectErr(result, InvalidOrderStatusError);
  });

  it("throws when the order has no lines", async () => {
    const { db, spies } = createMockDb<Transaction>();
    spies.select.mockReturnValueOnce(baseSalesOrder).mockReturnValueOnce([]);

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

    expectErr(result, EmptyOrderNotAllowedError);
  });

  it("throws when shipping address is missing for physical fulfillment lines", async () => {
    const { db, spies } = createMockDb<Transaction>();
    spies.select
      .mockReturnValueOnce({ ...baseSalesOrder, shippingAddressSnapshot: null })
      .mockReturnValueOnce([baseSalesOrderLine]);

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

    expectErr(result, ShippingAddressRequiredError);
  });
});
