import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core";
import type { Transaction } from "../generated/kysely-tailordb";
import {
  ChannelNotFoundError,
  DuplicateListingIdentityError,
  ItemNotActiveError,
  ItemNotFoundError,
} from "../lib/errors.generated";
import type { ItemManagementQueries } from "../module";

export interface CreateListingInput {
  channelId: string;
  itemId: string;
  sku?: string;
  externalIdentifier?: string | null;
  title?: string;
  requiresPriceSync?: boolean;
  salesPriceListId?: string | null;
}

export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: CreateListingInput & CF,
  ctx: CommandContext,
  itemManagementQueries: Pick<ItemManagementQueries, "getItem">,
) {
  const channel = await db
    .selectFrom("Channel")
    .selectAll()
    .where("id", "=", input.channelId)
    .executeTakeFirst();
  if (!channel) {
    return err(new ChannelNotFoundError(input.channelId));
  }
  const { item } = (await itemManagementQueries.getItem(db, { id: input.itemId }, ctx)).value;
  if (!item) {
    return err(new ItemNotFoundError(input.itemId));
  }
  if (item.status !== "ACTIVE") {
    return err(new ItemNotActiveError(input.itemId));
  }
  const existing = await db
    .selectFrom("Listing")
    .selectAll()
    .where("channelId", "=", input.channelId)
    .execute();
  if (
    existing.some(
      (listing) =>
        (input.externalIdentifier != null &&
          listing.externalIdentifier === input.externalIdentifier) ||
        (input.sku != null && listing.sku === input.sku),
    )
  ) {
    return err(
      new DuplicateListingIdentityError(input.externalIdentifier ?? input.sku ?? "listing"),
    );
  }
  const {
    channelId,
    itemId,
    sku,
    externalIdentifier,
    title,
    requiresPriceSync,
    salesPriceListId,
    ...customFields
  } = input;
  const listing = await db
    .insertInto("Listing")
    .values({
      ...(customFields as Record<string, unknown>),
      companyId: channel.companyId,
      channelId,
      itemId,
      sku: sku ?? null,
      externalIdentifier: externalIdentifier ?? null,
      title: title ?? null,
      status: "DRAFT",
      requiresPriceSync: requiresPriceSync ?? false,
      salesPriceListId: salesPriceListId ?? null,
    })
    .returningAll()
    .executeTakeFirstOrThrow();
  return ok({ listing });
}
