// Byte-rate ETA for the transfer progress strip.
//
// The engine reports cumulative bytesDone/bytesTotal with every event. File
// counts alone mislead on real depots — a handful of giant paks can hold the
// "done" counter still for minutes while gigabytes flow — so the strip shows
// byte-based percent and a time estimate instead of a per-file readout.
//
// Rate = bytes over a trailing window (default 20 s), so the estimate adapts
// to link speed changes without whiplashing on individual events. No
// estimate is produced until the window holds ≥ 2 s and some bytes, or when
// the total is unknown.

const WINDOW_MS = 20_000;
const MIN_SPAN_MS = 2_000;

export function createEtaTracker(now = () => Date.now()) {
  let samples = []; // { t, bytes } — bytes are cumulative

  return {
    /** Record the latest cumulative byte count. */
    update(bytesDone) {
      const t = now();
      samples.push({ t, bytes: bytesDone });
      const cutoff = t - WINDOW_MS;
      while (samples.length > 2 && samples[1].t <= cutoff) samples.shift();
    },

    /** Seconds left, or null while there's no trustworthy rate yet. */
    remainingSeconds(bytesDone, bytesTotal) {
      if (!bytesTotal || bytesDone >= bytesTotal) return null;
      if (samples.length < 2) return null;
      const first = samples[0];
      const last = samples[samples.length - 1];
      const spanMs = last.t - first.t;
      const bytes = last.bytes - first.bytes;
      if (spanMs < MIN_SPAN_MS || bytes <= 0) return null;
      const rate = bytes / (spanMs / 1000);
      return (bytesTotal - bytesDone) / rate;
    },
  };
}

/** "under a minute" / "about 3 min" / "about 1 h 21 min" */
export function formatEta(seconds) {
  if (seconds == null) return null;
  if (seconds < 60) return 'under a minute';
  const minutes = Math.round(seconds / 60);
  if (minutes < 60) return `about ${minutes} min`;
  const hours = Math.floor(minutes / 60);
  const rest = minutes % 60;
  return rest ? `about ${hours} h ${rest} min` : `about ${hours} h`;
}
