import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core";
import { Transaction } from "../generated/kysely-tailordb";
import {
  DuplicateBarcodeError,
  DuplicateSkuError,
  UnitNotFoundError,
} from "../lib/errors.generated";
import { type PrimitivesQueries } from "../module";

export interface CreateItemInput {
  sku: string;
  name: string;
  barcode?: string;
  unitId: string;
  status?: "DRAFT" | "ACTIVE";
}
/**
 * Function: createItem
 *
 * Creates a new item with a unique SKU in DRAFT or ACTIVE status.
 * DRAFT items allow review before activation; ACTIVE items are immediately available.
 */
export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: CreateItemInput & CF,
  ctx: CommandContext,
  primitivesQueries: Pick<PrimitivesQueries, "getUnit">,
) {
  const { sku, name, barcode, unitId, status = "DRAFT", ...customFields } = input;

  // 1. Check SKU uniqueness
  const existingSku = await db
    .selectFrom("Item")
    .selectAll()
    .where("sku", "=", sku)
    .forUpdate()
    .executeTakeFirst();

  if (existingSku) {
    return err(new DuplicateSkuError(sku));
  }

  // 2. Check barcode uniqueness (when provided)
  if (barcode) {
    const existingBarcode = await db
      .selectFrom("Item")
      .selectAll()
      .where("barcode", "=", barcode)
      .forUpdate()
      .executeTakeFirst();

    if (existingBarcode) {
      return err(new DuplicateBarcodeError(barcode));
    }
  }

  // 3. Validate UoM exists and is active
  const { unit } = (await primitivesQueries.getUnit(db, { id: unitId }, ctx)).value;

  if (unit?.status !== "ACTIVE") {
    return err(new UnitNotFoundError(unitId));
  }

  // 4. Create item
  const item = await db
    .insertInto("Item")
    .values({
      ...(customFields as Record<string, unknown>),
      sku,
      name,
      barcode: barcode ?? null,
      unitId,
      status,
    })
    .returningAll()
    .executeTakeFirstOrThrow();

  return ok({ item });
}
