// The DJ shift (design §6 role ladder, previewed as a floor interaction the way
// the glassie run was). Pure numbers + judgement here, tested; the scene owns
// sprites, keys and the TechnoEngine hookup.
//
// The shape of the fantasy: the resident needs a minute, you hold the decks.
// BUILD pulls the bass out and the room leans in; DROP is judged against the
// bar line the engine is actually playing. Requests arrive mid-set and every
// answer costs something (§4.3 — being the fun DJ and being the good DJ are
// different jobs).

export type DropVerdict = 'clean' | 'late' | 'clang';

/** Inside this of a bar boundary is a clean drop. */
export const DROP_CLEAN_MS = 140;
/** Beyond clean but inside this is a stumble the room forgives. */
export const DROP_LATE_MS = 320;

/**
 * Judge a drop from its distance to the NEAREST bar line (early or late are the
 * same offence — the room only hears wrong).
 */
export function judgeDrop(msToNearestBar: number): DropVerdict {
  const d = Math.abs(msToNearestBar);
  if (d <= DROP_CLEAN_MS) return 'clean';
  if (d <= DROP_LATE_MS) return 'late';
  return 'clang';
}

/**
 * Distance to the nearest bar boundary, from the current beat index within the
 * bar and ms elapsed since that beat. Bars are 4 beats.
 */
export function msToNearestBar(beatInBar: number, msSinceBeat: number, beatMs: number): number {
  const intoBar = beatInBar * beatMs + msSinceBeat;
  const barMs = 4 * beatMs;
  const behind = intoBar;          // how late past the last bar line
  const ahead = barMs - intoBar;   // how early before the next
  return behind <= ahead ? behind : -ahead;
}

/** A build that never drops runs out of stairs after this many bars. */
export const BUILD_FIZZLE_BARS = 4;

// ---- outcomes (§4.3: priced, never graded) ----------------------------------

export const DROP_PAYOUT: Record<DropVerdict, { vibe: number; hype: number; aggro: number }> = {
  clean: { vibe: 4, hype: 0.4, aggro: 0 },
  late: { vibe: 1, hype: 0.1, aggro: 0 },
  clang: { vibe: -2, hype: 0, aggro: 1 },
};

export const BUILD_HYPE = 0.1;
export const FIZZLE_VIBE = -2;

/** Per-request odds the floor is WITH it. The rest of the request lives in
 * data/strings/floor.ts (DJ_REQUESTS) keyed by the same id. */
export const REQUEST_HIT: Record<string, number> = {
  dnb: 0.75,
  nan: 0.5,
  birthday: 0.65,
  shazam: 0.55,
  slower: 0.4,
  again: 0.7,
};

export const REQUEST_PLAY_HIT = { vibe: 3, hype: 0.2 };
export const REQUEST_PLAY_FLOP = { vibe: -3 };
export const REQUEST_NAH_AGGRO = 1;
/** "after this one": chance they come back later, having remembered. */
export const REQUEST_LATER_GRUDGE = 0.4;
