/**
 * LANE-UI — machine colors for build-bar icons.
 *
 * Contracts v3 RULING: `MachineDef.color` is the CHASSIS/BODY colour (codex §8 grime);
 * the emissive accent is derived from what the machine outputs. So an icon is built the
 * way the codex builds every asset — the two-material rule (§8): grimy industrial body
 * plus exactly ONE impossible element.
 *
 * This matters for legibility, not just fidelity: DATA's chassis values are all
 * desaturated neutrals (#4a4e52, #3f4348, #55595e…), exactly as §8 demands, and a bar of
 * 21 icons in those colours is an unreadable grey wall. The accent is what tells a
 * quantizer from a demuxer at a glance — and deriving it from outputs is also what
 * LANE-RENDER does, so the bar and the world agree.
 *
 * The id/kind tables below are the round-1 hand-transcriptions from docs/FKTRY_LORE.md §4
 * — each machine's ASSET block names its impossible element, so they were always accent
 * values. They were only ever mislabeled (the same mistake the v2 contract made); here
 * they serve as the accent fallback for machines that output nothing (belts, buffers).
 */
import type { GameData, ItemDef, MachineDef, MachineKind, RecipeDef } from '../contracts';

/** Accent by id — the "one impossible element" from each codex ASSET block. */
const ACCENT_BY_ID: Record<string, string> = {
  'seam-extractor': '#c8a03f', // grimy yellow chassis, CRT head
  belt: '#5a7a5a',
  demuxer: '#ff3fd4', // the magenta output chute
  quantizer: '#e8e0ff', // HF dust leaking from the seams
  'mosh-reactor': '#ff7a3f', // melt, seen through the porthole
  'decode-asic': '#3fffe0', // serene LED face
  shipper: '#d8ffd8', // THE SCREEN's own light
};

const ACCENT_BY_KIND: Record<MachineKind, string> = {
  extractor: '#c8a03f',
  belt: '#5a7a5a',
  crafter: '#3fffe0',
  splitter: '#7fb0ff',
  power: '#3fffe0',
  buffer: '#7fb0ff',
  shipper: '#d8ffd8',
  lab: '#b0a0ff', // v4 kind; placeholder
};

/** Fallback chassis for machines DATA hasn't art-directed yet. */
const CHASSIS_FALLBACK = '#4a4e52';

/** The body. Data wins; nothing here is ever saturated. */
export function machineChassis(def: MachineDef): string {
  return def.color || CHASSIS_FALLBACK;
}

export type AccentFn = (def: MachineDef) => string;

/**
 * Accent lookup, in the precedence LANE-RENDER uses (v4 — confirmed identical in NOTES):
 *   1. `MachineDef.accent` — art direction wins outright.
 *   2. the colour of the first item the machine outputs — the documented derivation.
 *   3. the codex id/kind tables below, for machines that output nothing.
 * Curried over GameData because the derivation needs recipes + items.
 */
export function createAccentLookup(data: GameData): AccentFn {
  const recipes = new Map<string, RecipeDef>(data.recipes.map((r) => [r.id, r]));
  const items = new Map<string, ItemDef>(data.items.map((i) => [i.id, i]));

  return (def) => {
    if (def.accent) return def.accent;

    for (const rid of def.recipes) {
      const r = recipes.get(rid);
      if (!r) continue;
      for (const out of Object.keys(r.outputs)) {
        const c = items.get(out)?.color;
        if (c) return c;
      }
    }
    // Belts, splitters, buffers and shippers produce nothing — they get their codex glow.
    return ACCENT_BY_ID[def.id] || ACCENT_BY_KIND[def.kind] || '#d8ffd8';
  };
}
