import { bootstrap } from '@/api/client';
import { __ } from '@/lib/i18n';

/**
 * Turning stored timestamps into something worth reading.
 *
 * Everything FlowWP stores goes in as `current_time( 'mysql', true )`, which is
 * UTC in the form `2026-09-08 14:22:01`. That string has no timezone marker, so
 * `new Date()` reads it as *local* time — which silently shifts every date in
 * the interface by the reader's offset. Normalising it to an ISO instant first
 * is the whole reason this file exists.
 */

/** Parse a MySQL UTC datetime. Returns null for anything unusable. */
export function parseUtc(value: string): Date | null {
  if (value === '' || value.startsWith('0000-00-00')) {
    return null;
  }

  const date = new Date(`${value.replace(' ', 'T')}Z`);

  return Number.isNaN(date.getTime()) ? null : date;
}

const UNITS: Array<{ limit: number; seconds: number; unit: Intl.RelativeTimeFormatUnit }> = [
  { limit: 60, seconds: 1, unit: 'second' },
  { limit: 3600, seconds: 60, unit: 'minute' },
  { limit: 86400, seconds: 3600, unit: 'hour' },
  { limit: 604800, seconds: 86400, unit: 'day' },
  { limit: 2629800, seconds: 604800, unit: 'week' },
  { limit: 31557600, seconds: 2629800, unit: 'month' },
];

/**
 * "3 minutes ago", "yesterday", "last month".
 *
 * Relative because the question behind a timestamp in a list is almost always
 * "is this recent?", not "what was the date?". The absolute value stays
 * available as a title attribute for the times when it is the other question.
 */
export function relativeTime(value: string, now: Date = new Date()): string {
  const date = parseUtc(value);

  if (date === null) {
    return '—';
  }

  const seconds = Math.round((date.getTime() - now.getTime()) / 1000);
  const magnitude = Math.abs(seconds);

  if (magnitude < 45) {
    return __('just now', 'flowwp-workflow-automation');
  }

  const format = new Intl.RelativeTimeFormat(wordpressLocale(), { numeric: 'auto' });

  for (const { limit, seconds: size, unit } of UNITS) {
    if (magnitude < limit) {
      return format.format(Math.round(seconds / size), unit);
    }
  }

  return format.format(Math.round(seconds / 31557600), 'year');
}

/** The full date and time, in the reader's own locale and zone. */
export function absoluteTime(value: string): string {
  const date = parseUtc(value);

  return date === null ? '—' : date.toLocaleString(wordpressLocale());
}

/**
 * The locale WordPress is showing this person, as Intl wants it.
 *
 * Not `undefined`, which is what Intl falls back to and which means *the
 * browser's* locale. A site running in French, read by somebody whose browser
 * is in English, would render every date in English beside a French interface
 * — the one place where getting it wrong looks like a bug rather than a
 * missing translation.
 *
 * WordPress spells a locale `fr_FR`; BCP 47, which Intl reads, spells it
 * `fr-FR`. Returns undefined when the bundle is running outside the admin, so
 * Intl falls back on its own.
 */
function wordpressLocale(): string | undefined {
  const locale = bootstrap().locale;

  return typeof locale === 'string' && locale !== '' ? locale.replace('_', '-') : undefined;
}
