import { createKyselyMock } from "@tailor-platform/sdk/vitest";
import { describe, expect, it } from "vitest";
import type { Namespace } from "../generated/kysely-tailordb";
import { PurchaseOrderNotFoundError } from "../lib/errors.generated";
import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
import { basePurchaseOrder, basePurchaseOrderLine, baseReceiptEvidence } from "../testing/fixtures";
import { mockInventoryQueries } from "../testing/moduleMocks";
import { recalculatePurchaseOrderReceiptStatusInternal } from "./purchaseOrder";

describe("recalculatePurchaseOrderReceiptStatusInternal", () => {
  it("updates receiptStatus from posted inventory receipt evidence", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    const line = { ...basePurchaseOrderLine, quantity: "10" };
    mock.enqueueResults(
      [basePurchaseOrder],
      [line],
      [{ ...basePurchaseOrder, receiptStatus: "PARTIALLY_RECEIVED" }],
    );

    const result = await mock.withTx((trx) =>
      recalculatePurchaseOrderReceiptStatusInternal(
        trx,
        { purchaseOrderId: basePurchaseOrder.id },
        commandCtx,
        mockInventoryQueries({
          receiptEvidence: [baseReceiptEvidence],
        }),
      ),
    );

    expect(expectOk(result).purchaseOrder.receiptStatus).toBe("PARTIALLY_RECEIVED");
    expect(mock.updates[0].updateValues()).toEqual(
      expect.objectContaining({ receiptStatus: "PARTIALLY_RECEIVED" }),
    );
  });

  it("marks the order received when evidence covers all ordered quantity", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    const line = { ...basePurchaseOrderLine, quantity: "10" };
    mock.enqueueResults(
      [basePurchaseOrder],
      [line],
      [{ ...basePurchaseOrder, receiptStatus: "RECEIVED" }],
    );

    const result = await mock.withTx((trx) =>
      recalculatePurchaseOrderReceiptStatusInternal(
        trx,
        { purchaseOrderId: basePurchaseOrder.id },
        commandCtx,
        mockInventoryQueries({
          receiptEvidence: [{ ...baseReceiptEvidence, quantity: "10" }],
        }),
      ),
    );

    expect(expectOk(result).purchaseOrder.receiptStatus).toBe("RECEIVED");
  });

  it("returns error when purchase order does not exist", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([]);

    const result = await mock.withTx((trx) =>
      recalculatePurchaseOrderReceiptStatusInternal(
        trx,
        { purchaseOrderId: "missing-po" },
        commandCtx,
        mockInventoryQueries(),
      ),
    );

    expectErr(result, PurchaseOrderNotFoundError);
  });
});
