import { describe, expect, it } from "vitest";
import { createMockDb } from "../../../testing/index";
import type { Transaction } from "../generated/kysely-tailordb";
import { DuplicateExternalIdentifierError, ListingNotEditableError } from "../lib/errors.generated";
import { baseListing, pausedListing, retiredListing } from "../testing/fixtures";
import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
import { run } from "./updateListing";

describe("updateListing", () => {
  it("updates listing metadata while listing remains active or paused", async () => {
    const { db, spies } = createMockDb<Transaction>();
    const updated = { ...pausedListing, title: "Updated Title", updatedAt: new Date() };
    spies.select.mockReturnValueOnce(pausedListing);
    spies.update.mockReturnValueOnce(updated);

    const result = await run(
      db,
      { listingId: pausedListing.id, title: "Updated Title" },
      commandCtx,
    );

    expectOk(result);
    expect(spies.set).toHaveBeenCalledWith(expect.objectContaining({ title: "Updated Title" }));
  });

  it("returns error when listing is retired", async () => {
    const { db, spies } = createMockDb<Transaction>();
    spies.select.mockReturnValueOnce(retiredListing);

    const result = await run(
      db,
      { listingId: retiredListing.id, title: "Updated Title" },
      commandCtx,
    );

    expectErr(result, ListingNotEditableError);
  });

  it("returns error when updated external identifier conflicts with another listing", async () => {
    const { db, spies } = createMockDb<Transaction>();
    spies.select
      .mockReturnValueOnce(baseListing)
      .mockReturnValueOnce([
        baseListing,
        { ...baseListing, id: "listing-99", externalIdentifier: "AMZ-CONFLICT" },
      ]);

    const result = await run(
      db,
      { listingId: baseListing.id, externalIdentifier: "AMZ-CONFLICT" },
      commandCtx,
    );

    expectErr(result, DuplicateExternalIdentifierError);
  });
});
