import { createKyselyMock } from "@tailor-platform/sdk/vitest";
import { describe, expect, it } from "vitest";
import type { Namespace } from "../generated/kysely-tailordb";
import { commandCtx, expectOk } from "../testing/commandTestUtils";
import {
  baseAccountPayableDocumentLine,
  creditMemoAccountPayableDocument,
  registeredAccountPayableDocument,
} from "../testing/fixtures";
import { mockPurchaseCommands } from "../testing/moduleMocks";
import { syncPurchaseOrderBillingStatusFromAccountPayable } from "./purchaseBillingFeedback";

describe("syncPurchaseOrderBillingStatusFromAccountPayable", () => {
  it("excludes price corrections from billed quantity", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([
      {
        purchaseOrderLineId: "purchase-order-line-1",
        quantity: "10",
        correctionType: null,
        documentType: "INVOICE",
      },
      {
        purchaseOrderLineId: "purchase-order-line-1",
        quantity: "10",
        correctionType: "PRICE",
        documentType: "INVOICE",
      },
    ]);
    const purchaseCommands = mockPurchaseCommands();

    const result = await mock.withTx((trx) =>
      syncPurchaseOrderBillingStatusFromAccountPayable(
        trx,
        { document: registeredAccountPayableDocument, lines: [baseAccountPayableDocumentLine] },
        commandCtx,
        purchaseCommands,
      ),
    );

    expectOk(result);
    expect(purchaseCommands.recalculatePurchaseOrderBillingStatus.mock.lastCall?.[1]).toEqual({
      lineBillings: [{ purchaseOrderLineId: "purchase-order-line-1", billedQuantity: "10" }],
    });
  });

  it("subtracts credit memo quantity corrections from billed quantity", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([
      {
        purchaseOrderLineId: "purchase-order-line-1",
        quantity: "10",
        correctionType: null,
        documentType: "INVOICE",
      },
      {
        purchaseOrderLineId: "purchase-order-line-1",
        quantity: "2",
        correctionType: "QUANTITY",
        documentType: "CREDIT_MEMO",
      },
    ]);
    const purchaseCommands = mockPurchaseCommands();

    const result = await mock.withTx((trx) =>
      syncPurchaseOrderBillingStatusFromAccountPayable(
        trx,
        {
          document: creditMemoAccountPayableDocument,
          lines: [{ ...baseAccountPayableDocumentLine, correctionType: "QUANTITY" }],
        },
        commandCtx,
        purchaseCommands,
      ),
    );

    expectOk(result);
    expect(purchaseCommands.recalculatePurchaseOrderBillingStatus.mock.lastCall?.[1]).toEqual({
      lineBillings: [{ purchaseOrderLineId: "purchase-order-line-1", billedQuantity: "8" }],
    });
  });
});
