/**
 * LANE-UI — pure chip-spec builders.
 *
 * The arithmetic behind every chip row (what's short, what's met, what the count reads)
 * with no DOM in sight, so it can be tested and so `chips.ts` stays a dumb renderer.
 */
import type { CommissionDef, EntityState, RecipeDef } from '../contracts';
import type { ChipSpec } from './chips';

/** Recipe inputs against what the machine is actually holding: `have/need`. */
export function intakeChips(recipe: RecipeDef, e: EntityState): ChipSpec[] {
  return Object.entries(recipe.inputs).map(([item, need]) => {
    const have = e.inputBuf[item] ?? 0;
    return { item, count: `${have}/${need}`, state: have >= need ? 'met' : 'short' };
  });
}

/**
 * Recipe outputs, then anything else the output buffer is holding — a jam is often an
 * item the current recipe never mentions (left over from a previous recipe).
 */
export function outputChips(recipe: RecipeDef, e: EntityState): ChipSpec[] {
  const ids = new Set(Object.keys(recipe.outputs));
  for (const id of Object.keys(e.outputBuf)) ids.add(id);
  return [...ids].map((item) => ({ item, count: String(e.outputBuf[item] ?? 0) }));
}

/** Commission wants against delivered progress. Never shows more delivered than wanted. */
export function commissionChips(c: CommissionDef, progress: Record<string, number>): ChipSpec[] {
  return Object.entries(c.wants).map(([item, need]) => {
    const have = progress[item] ?? 0;
    return {
      item,
      count: `${Math.min(have, need)}/${need}`,
      state: have >= need ? 'met' : 'plain',
    };
  });
}

/** True once every want is satisfied. */
export function commissionMet(c: CommissionDef, progress: Record<string, number>): boolean {
  return Object.entries(c.wants).every(([item, need]) => (progress[item] ?? 0) >= need);
}
