// Shapes and shared English for bills of materials and builds — Task 5 of
// docs/superpowers/plans/2026-08-03-inventory.md. Mirrors server/src/builds.ts's
// reply bodies exactly; nothing here derives a number the API already gives.
//
// The sentences below are shared between the BOM editor and the build screen
// on purpose: "a build costs exactly its parts" has to read identically in
// both places, because it is the same fact, and a manufacturer who meets two
// wordings of it will assume they mean different things.

/** One row of GET/PUT /api/c/items/:id/components. */
export interface ApiComponent {
  id: string;
  itemId: string;
  sku: string | null;
  name: string;
  qtyPer: string;
  qtyOnHand: string;
  averageCost: string;
}

export interface ApiComponentsBody {
  item: { id: string; name: string; kind: string };
  components: ApiComponent[];
}

/** One row of POST /api/c/builds/preview's `components`. */
export interface ApiPreviewComponent {
  itemId: string;
  sku: string | null;
  name: string;
  qtyPer: string;
  qtyNeeded: string;
  qtyOnHand: string;
  averageCost: string;
  drawValue: string;
  sufficient: boolean;
}

export interface ApiBuildPreview {
  assemblyItemId: string;
  assemblyName: string;
  assemblyKind: string;
  inventoryAccountId: string | null;
  inventoryAccountName: string | null;
  qty: string;
  components: ApiPreviewComponent[];
  totalValue: string;
  unitCost: string;
  canBuild: boolean;
  /** The refusal, already in English, already naming the item and the
   *  numbers — post_build()'s own rules, restated by the preview so the
   *  screen can say them BEFORE the button (server/src/builds.ts). */
  blockedBecause: string | null;
}

/** POST /api/c/builds's 201 body. */
export interface ApiBuildResult {
  buildId: string;
  buildNo: string;
  assemblyItemId: string;
  assemblyName: string;
  qty: string;
  builtOn: string;
  status: string;
  entryId: string;
  entryNo: string | null;
  memo: string | null;
  value: string;
  unitCost: string;
  summary: string;
}

/** One row of GET /api/c/builds. */
export interface ApiBuildRow {
  buildId: string;
  buildNo: string;
  assemblyItemId: string;
  assemblyName: string;
  qty: string;
  builtOn: string;
  status: string;
  entryId: string;
  entryNo: string | null;
  memo: string | null;
  value: string;
}

export interface ApiBuildsBody {
  total: number;
  builds: ApiBuildRow[];
}

/** What a build costs, said once. Spec non-goals: no labor, no overhead, no
 *  routings — and the screen says so rather than leaving a manufacturer to
 *  work it out from a number that looks too low. */
export const BUILD_COST_NOTE =
  "A build costs exactly what its parts cost — nothing is added for labor, overhead or machine time. If you want those in the cost of your finished goods, they stay where they are today: in your expenses.";

/** Both rules the database enforces on a parts list, said before it has to.
 *  (0018's assemblies_no_recursion; server/src/builds.ts deliberately does not
 *  pre-check them, so these are a courtesy, never the guard.) */
export const BOM_PART_RULE =
  "A part has to be something you stock — a service or a non-stocked item has no quantity to draw down.";
export const BOM_RECURSION_RULE =
  "Nothing can be a part of itself, directly or through another assembly.";
