import { cn } from 'helpers/cn';

// "3 days ago", with the exact timestamp on hover.
//
// The hover title is the whole reason this is a component rather than a string helper. Relative time
// is right for scanning and useless for anything else — "2 months ago" cannot be compared to a log
// line or quoted in a message — and every list that renders it loses the real value. Keeping both
// costs one attribute.

const MINUTE = 60_000;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;

export function timeAgo(value: string | number | Date | null | undefined): string {
  if (!value) return '';
  const then = new Date(value).getTime();
  if (Number.isNaN(then)) return '';

  const delta = Date.now() - then;
  if (delta < 0) return 'just now';
  if (delta < MINUTE) return 'just now';
  if (delta < HOUR) {
    const n = Math.floor(delta / MINUTE);
    return `${n}m ago`;
  }
  if (delta < DAY) {
    const n = Math.floor(delta / HOUR);
    return `${n}h ago`;
  }
  if (delta < 30 * DAY) {
    const n = Math.floor(delta / DAY);
    return n === 1 ? 'yesterday' : `${n}d ago`;
  }
  if (delta < 365 * DAY) {
    const n = Math.floor(delta / (30 * DAY));
    return `${n}mo ago`;
  }
  return `${Math.floor(delta / (365 * DAY))}y ago`;
}

export function absoluteTime(value: string | number | Date): string {
  const date = new Date(value);
  return Number.isNaN(date.getTime()) ? '' : date.toLocaleString();
}

export const RelativeTime = ({
  value,
  className,
  prefix,
}: {
  value: string | number | Date | null | undefined;
  className?: string;
  /** e.g. "updated" → "updated 3d ago". Kept out of the value so it is not repeated per list item. */
  prefix?: string;
}) => {
  if (!value) return null;
  const relative = timeAgo(value);
  if (!relative) return null;
  return (
    <time
      dateTime={new Date(value).toISOString()}
      title={absoluteTime(value)}
      className={cn('tabular-nums', className)}
    >
      {prefix ? `${prefix} ${relative}` : relative}
    </time>
  );
};
