/**
 * Pacing for the try-on processing view.
 *
 * Measured generation times (photo-ranker-be, gemini provider): p50 ~11s,
 * p90 ~35s, worst observed 48s, and identical inputs on the same day
 * produced both 10.1s and 35.7s, so nothing we hold predicts which we get.
 *
 * That rules out a countdown: any estimate would be wrong most of the time.
 * Instead both the bar and the status copy are pure functions of elapsed
 * time. There is no estimate to be wrong about, and because they share one
 * input they cannot drift out of sync with each other.
 */

/** The bar approaches but never reaches this. It has nowhere to stall. */
export const BAR_CEILING = 0.92;

/**
 * Time constant of the asymptotic fill, in seconds. Chosen so the bar reads
 * half-full at our measured p50 of 11s:
 *   0.92 * (1 - e^(-11/14)) ≈ 0.50
 * Tune this if the measured p50 moves.
 */
export const TAU_SECONDS = 14;

/** Elapsed seconds at which each status string takes over. */
export const STATUS_SCHEDULE_SECONDS = [0, 4, 8, 13, 19, 26] as const;

export const STATUS_COUNT = STATUS_SCHEDULE_SECONDS.length;

/**
 * Fraction of the progress bar to fill. Strictly increasing, asymptotic to
 * BAR_CEILING, so it is always still moving no matter how long generation
 * takes.
 */
export function barProgress(elapsedMs: number): number {
  const seconds = Math.max(0, elapsedMs) / 1000;
  return BAR_CEILING * (1 - Math.exp(-seconds / TAU_SECONDS));
}

/**
 * Index of the status string to show. Non-decreasing, and holds on the last
 * string forever rather than wrapping, a visible loop would give the game
 * away, a held line just reads as "still working".
 */
export function statusIndexFor(elapsedMs: number): number {
  const seconds = Math.max(0, elapsedMs) / 1000;
  let index = 0;
  for (let i = 0; i < STATUS_SCHEDULE_SECONDS.length; i++) {
    if (seconds >= STATUS_SCHEDULE_SECONDS[i]) {
      index = i;
    }
  }
  return index;
}

/** Elapsed seconds truncated to one decimal, e.g. 12.4. */
export function elapsedTenths(elapsedMs: number): number {
  return Math.floor(Math.max(0, elapsedMs) / 100) / 10;
}
