import { createKyselyMock } from "@tailor-platform/sdk/vitest";
import { describe, it } from "vitest";
import type { Namespace } from "../generated/kysely-tailordb";
import {
  CustomerNotActiveError,
  InvalidOrderStatusError,
  MissingFinalPriceError,
} from "../lib/errors.generated";
import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
import {
  baseCustomer,
  basePaymentTerm,
  baseSalesOrderLine,
  inactiveCustomer,
  submittedSalesOrder,
} from "../testing/fixtures";
import { mockBPQueries } from "../testing/moduleMocks";
import { run } from "./confirmSalesOrder";

describe("confirmSalesOrder", () => {
  it("confirms a submitted order and snapshots commercial context", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    const updated = {
      ...submittedSalesOrder,
      status: "CONFIRMED" as const,
      updatedAt: new Date("2024-01-02T00:00:00.000Z"),
    };
    mock.enqueueResults([submittedSalesOrder], [baseSalesOrderLine], [basePaymentTerm], [updated]);

    const result = await mock.withTx((trx) =>
      run(
        trx,
        { salesOrderId: submittedSalesOrder.id },
        commandCtx,
        mockBPQueries(baseCustomer, null),
      ),
    );

    expectOk(result);
  });

  it("throws when order is not submitted", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([{ ...submittedSalesOrder, status: "DRAFT" }]);

    const result = await mock.withTx((trx) =>
      run(
        trx,
        { salesOrderId: submittedSalesOrder.id },
        commandCtx,
        mockBPQueries(baseCustomer, null),
      ),
    );

    expectErr(result, InvalidOrderStatusError);
  });

  it("throws when customer became inactive before confirmation", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([submittedSalesOrder]);

    const result = await mock.withTx((trx) =>
      run(
        trx,
        { salesOrderId: submittedSalesOrder.id },
        commandCtx,
        mockBPQueries(inactiveCustomer, null),
      ),
    );

    expectErr(result, CustomerNotActiveError);
  });

  it("throws when a line lacks final pricing data", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([submittedSalesOrder], [{ ...baseSalesOrderLine, unitPrice: 0 }]);

    const result = await mock.withTx((trx) =>
      run(
        trx,
        { salesOrderId: submittedSalesOrder.id },
        commandCtx,
        mockBPQueries(baseCustomer, null),
      ),
    );

    expectErr(result, MissingFinalPriceError);
  });
});
