/**
 * SHADES / HARD YARDS — Lane E owns this file.
 *
 * The runtime end of the factory's anchor ratings (SPRINT15 gate 1.2).
 *
 * THE BUG THIS CLOSES: `adoptAnchor` is the only place a baked `rating_hint`
 * ever reached an anchor, and it only runs for anchors that name a GLB `node`.
 * Every shipped sail post is a plain JSON entry with no `node`, so the
 * factory's bake never arrived and `?? 1` won — the factory said 0.90, the sim
 * played 1.00, and nothing anywhere could see the disagreement. Gate 1.1 ruled
 * the shipped 1.00 canon (every measured number stands on it), and this module
 * is the mechanism half of that ruling: the same silent divergence is now
 * impossible for the whole extras family (`rating_hint`, `collateral`, and by
 * exclusion `tie_off`) on ANY node-less JSON anchor whose type the factory
 * rates.
 *
 * HOW: the factory emits `anchor_ratings.gen.js` from the re-imported GLBs —
 * per anchor TYPE, the baked extras, but only where every rated node of that
 * type in the palette agrees (`types`). Types whose nodes disagree (tree:
 * 1.0 → 0.4 down the trunk) are listed under `ambiguous`, and this module
 * REFUSES to guess for them — a node-less anchor of an ambiguous type keeps
 * the default hint and warns loudly, and e.test.js pins that no shipped site
 * declares one. Three-way agreement is pinned in e.test.js:
 * GLB === manifest === runtime, so a re-bake that skips regeneration, a
 * hand-edit to the gen file, or a future adoptAnchor-shaped gap all go red.
 *
 * WHO CALLS IT: world.js, at the JSON-anchor creation sites, as
 * `Object.assign(makeStaticAnchor(...), ..., a.node ? null : factoryExtras(type))`
 * — node-carrying anchors keep their graybox default and are corrected by
 * adoptAnchor at dress time, exactly as before; node-less ones take the
 * factory's word at construction, because dress will never reach them.
 */

import { FACTORY_ANCHOR_RATINGS } from './anchor_ratings.gen.js';

/** Warn once per type, not once per anchor — a site with four posts of a
 *  future ambiguous type should not print four identical warnings. */
const warned = new Set();

/**
 * The factory's baked extras for an anchor TYPE, in runtime (camelCase) field
 * names, ready to `Object.assign` onto an Anchor.
 *
 * @param {string} type  An ANCHOR_TYPE string (contracts.js).
 * @returns {{ratingHint: number, collateral?: string}|null}
 *   The extras when the factory rates this type unambiguously; null when it
 *   doesn't rate it at all (caller keeps its default) or rates it ambiguously
 *   (caller keeps its default AND this is almost certainly a site bug — a
 *   node-less anchor of an ambiguous type has no honest rating; declare a
 *   `node` instead. e.test.js refuses it in shipped sites).
 */
export function factoryExtras(type) {
  const t = FACTORY_ANCHOR_RATINGS.types[type];
  if (t) {
    const out = { ratingHint: t.rating_hint };
    if (t.collateral !== undefined) out.collateral = t.collateral;
    return out;
  }
  if (FACTORY_ANCHOR_RATINGS.ambiguous[type] && !warned.has(type)) {
    warned.add(type);
    console.warn(
      `[ratings] anchor type "${type}" is factory-AMBIGUOUS (its GLB nodes carry `
      + `different rating_hints) — a node-less "${type}" anchor falls back to the `
      + `default hint, which is the exact silent-divergence bug gate 1.2 buried. `
      + `Declare a \`node\` on the anchor so adoptAnchor can carry the real bake.`);
  }
  return null;
}
