/**
 * Locale-aware number/clock formatting helpers — the single source for the
 * `locale === 'fa' ? 'fa-IR' : 'en-US'` decision that used to be copy-pasted at 25+ call
 * sites (and had already drifted — some call sites passed the raw app locale straight into
 * `Intl.NumberFormat`, which is *not* the same as `fa-IR`).
 */

const FA_LOCALE_TAG = 'fa-IR';
const EN_LOCALE_TAG = 'en-US';

/** Resolves the app locale ('fa' | 'en') to the `Intl` locale tag used for numbers/clocks. */
export function localeTag(locale: string): typeof FA_LOCALE_TAG | typeof EN_LOCALE_TAG {
  return locale === 'fa' ? FA_LOCALE_TAG : EN_LOCALE_TAG;
}

/** Formats a plain number with locale-correct grouping + digits (Persian digits on `fa`). */
export function formatNumber(value: number, locale: string, options?: Intl.NumberFormatOptions): string {
  return new Intl.NumberFormat(localeTag(locale), options).format(value);
}

const SECOND_MS = 1000;
const MINUTE_S = 60;
const HOUR_S = 3600;
const DAY_S = 86400;

/**
 * Relative time with a decay rule: relative phrasing up to ~7 days («۲ ساعت پیش», «دیروز»),
 * then falls back to the absolute Shamsi date (via the caller-supplied `absolute` formatter,
 * e.g. `formatShamsiDate`) — a 3-week-old notification reading "۲۱ روز پیش" is worse than a
 * dated one. `iso` must be in the past; a future timestamp still formats (negative diff) since
 * `Intl.RelativeTimeFormat` handles both directions and no current consumer needs future dates.
 */
export function formatRelativeTime(
  iso: string,
  locale: string,
  absolute: (iso: string, locale: string) => string,
): string {
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return '';

  const diffSeconds = (date.getTime() - Date.now()) / SECOND_MS;
  const diffDays = Math.abs(diffSeconds) / DAY_S;

  if (diffDays >= 7) return absolute(iso, locale);

  const rtf = new Intl.RelativeTimeFormat(localeTag(locale), { numeric: 'auto' });
  const absSeconds = Math.abs(diffSeconds);

  if (absSeconds < MINUTE_S) return rtf.format(Math.round(diffSeconds), 'second');
  if (absSeconds < HOUR_S) return rtf.format(Math.round(diffSeconds / MINUTE_S), 'minute');
  if (absSeconds < DAY_S) return rtf.format(Math.round(diffSeconds / HOUR_S), 'hour');
  return rtf.format(Math.round(diffSeconds / DAY_S), 'day');
}

/** Formats a duration in whole seconds as a locale-digit `mm:ss` (or `hh:mm:ss` past an hour). */
export function formatClock(totalSeconds: number, locale: string): string {
  const safeSeconds = Math.max(0, Math.floor(totalSeconds));
  const hours = Math.floor(safeSeconds / HOUR_S);
  const minutes = Math.floor((safeSeconds % HOUR_S) / MINUTE_S);
  const seconds = safeSeconds % MINUTE_S;

  const pad = new Intl.NumberFormat(localeTag(locale), { minimumIntegerDigits: 2, useGrouping: false });
  const parts = hours > 0 ? [pad.format(hours), pad.format(minutes), pad.format(seconds)] : [pad.format(minutes), pad.format(seconds)];
  return parts.join(':');
}
