import type { defineModule as defineOrganizationModule } from "../../organization";
import type { Transaction } from "../generated/kysely-tailordb";
import {
  SiteNotFoundError,
  SiteInactiveError,
  DuplicateWarehouseNameError,
} from "../lib/errors.generated";
import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/module";

type OrganizationModule = ReturnType<typeof defineOrganizationModule>;
export type OrganizationQueries = OrganizationModule["queries"];

export interface CreateWarehouseInput {
  name: string;
  siteId: string;
  storageCondition?: string | null;
  capacity?: number | null;
}

/**
 * Function: createWarehouse
 *
 * Creates a new warehouse linked to an organizational site.
 * The warehouse is created in ACTIVE status and is immediately available
 * for storage location creation and stock operations.
 */
export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: CreateWarehouseInput & CF,
  ctx: CommandContext,
  organizationQueries: Pick<OrganizationQueries, "getSite">,
) {
  const { name, siteId, storageCondition, capacity, ...customFields } = input;

  // 1. Validate site exists and is ACTIVE
  const { site } = (await organizationQueries.getSite(db, { id: siteId }, ctx)).value;

  if (!site) {
    return err(new SiteNotFoundError(siteId));
  }

  if (site.status !== "ACTIVE") {
    return err(new SiteInactiveError(siteId));
  }

  // 2. Check name uniqueness within the site
  const existingWarehouse = await db
    .selectFrom("Warehouse")
    .selectAll()
    .where("name", "=", name)
    .where("siteId", "=", siteId)
    .forUpdate()
    .executeTakeFirst();

  if (existingWarehouse) {
    return err(new DuplicateWarehouseNameError(name));
  }

  // 3. Create warehouse with ACTIVE status
  const warehouse = await db
    .insertInto("Warehouse")
    .values({
      ...(customFields as Record<string, unknown>),
      name,
      siteId,
      storageCondition: storageCondition ?? null,
      capacity: capacity ?? null,
      status: "ACTIVE",
      createdAt: new Date(),
      updatedAt: null,
    })
    .returningAll()
    .executeTakeFirst();

  return ok({ warehouse: warehouse! });
}
