/** "1.2 MB", "512 KB", "48 B" — used anywhere a raw byte count needs to be human-readable. */
export function formatBytes(bytes: number): string {
  if (!bytes || bytes < 1024) return `${bytes || 0} B`;
  const units = ["KB", "MB", "GB"];
  let value = bytes / 1024;
  let unitIndex = 0;
  while (value >= 1024 && unitIndex < units.length - 1) {
    value /= 1024;
    unitIndex++;
  }
  return `${value.toFixed(1)} ${units[unitIndex]}`;
}

/** "Today" / "Yesterday" / "September 3" / "September 3, 2025" (year only shown when not this year) — the label for a date-grouped section header. `dayStartMs` must already be midnight-aligned (see `dayStart`). */
export function dateSectionLabel(dayStartMs: number): string {
  const d = new Date(dayStartMs);
  const now = new Date();
  const diffDays = Math.round((dayStart(now.getTime()) - dayStartMs) / 86400000);
  if (diffDays === 0) return "Today";
  if (diffDays === 1) return "Yesterday";
  return d.toLocaleDateString(undefined, {
    month: "long",
    day: "numeric",
    year: d.getFullYear() !== now.getFullYear() ? "numeric" : undefined,
  });
}

/** Midnight-aligned timestamp for the local day containing `ms` — the grouping key for date sections. */
export function dayStart(ms: number): number {
  const d = new Date(ms);
  d.setHours(0, 0, 0, 0);
  return d.getTime();
}
