import { createKyselyMock } from "@tailor-platform/sdk/vitest";
import { describe, expect, it } from "vitest";
import type { Namespace } from "../generated/kysely-tailordb";
import { expectOk, queryCtx } from "../testing/commandTestUtils";
import {
  baseCompany,
  baseCurrency,
  baseItem,
  basePriceList,
  basePriceRule,
  baseSupplier,
  baseUnit,
  higherBreakPriceRule,
  inactivePriceList,
  inactivePriceRule,
} from "../testing/fixtures";
import { run } from "./calculatePurchasePrice";

const defaultInput = {
  companyId: baseCompany.id,
  supplierId: baseSupplier.id,
  itemId: baseItem.id,
  unitId: baseUnit.id,
  currencyId: baseCurrency.id,
  quantity: "5",
  pricingDate: new Date("2024-06-01T00:00:00.000Z"),
};

describe("calculatePurchasePrice", () => {
  it("returns the best matching rule for a valid supplier item context", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([basePriceRule], [basePriceList]);

    const result = await run(mock.db, defaultInput, queryCtx);
    const { priceSuggestion, matchedRule } = expectOk<{
      priceSuggestion: { ruleId: string; priceListId: string; unitPrice: number } | null;
      matchedRule: unknown;
    }>(result as never);

    expect(priceSuggestion).not.toBeNull();
    expect(priceSuggestion!.ruleId).toBe(basePriceRule.id);
    expect(priceSuggestion!.priceListId).toBe(basePriceList.id);
    expect(priceSuggestion!.unitPrice).toBe("100");
    expect(matchedRule).not.toBeNull();
  });

  it("picks the higher quantity-break rule when ordered quantity qualifies", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([basePriceRule, higherBreakPriceRule], [basePriceList]);

    const result = await run(mock.db, { ...defaultInput, quantity: "15" }, queryCtx);
    const { priceSuggestion } = expectOk<{
      priceSuggestion: { ruleId: string; unitPrice: string } | null;
    }>(result as never);

    expect(priceSuggestion).not.toBeNull();
    expect(priceSuggestion!.ruleId).toBe(higherBreakPriceRule.id);
    expect(priceSuggestion!.unitPrice).toBe("90");
  });

  it("ignores inactive price lists and inactive rules", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([inactivePriceRule], [inactivePriceList]);

    const result = await run(mock.db, defaultInput, queryCtx);
    const { priceSuggestion } = expectOk<{
      priceSuggestion: null;
    }>(result as never);

    expect(priceSuggestion).toBeNull();
  });

  it("returns null when no active rule matches", async () => {
    const mock = createKyselyMock<Namespace["main-db"]>();
    mock.enqueueResults([], [basePriceList]);

    const result = await run(mock.db, defaultInput, queryCtx);
    const { priceSuggestion, matchedRule } = expectOk<{
      priceSuggestion: null;
      matchedRule: null;
    }>(result as never);

    expect(priceSuggestion).toBeNull();
    expect(matchedRule).toBeNull();
  });
});
