/** Display formatting only. No ride logic lives in the frontend (§4.3). */

const EM_DASH = '—';

export function clock(seconds: number | null | undefined): string {
  if (seconds == null || !Number.isFinite(seconds)) return EM_DASH;
  const s = Math.max(0, Math.round(seconds));
  const h = Math.floor(s / 3600);
  const m = Math.floor((s % 3600) / 60);
  const sec = s % 60;
  const pad = (n: number) => String(n).padStart(2, '0');
  return h > 0 ? `${h}:${pad(m)}:${pad(sec)}` : `${m}:${pad(sec)}`;
}

/** Shorter form for an ETA: "1h 04" / "42 min" / "38 s". */
export function duration(seconds: number | null | undefined): string {
  if (seconds == null || !Number.isFinite(seconds)) return EM_DASH;
  const s = Math.max(0, Math.round(seconds));
  if (s >= 3600) {
    const h = Math.floor(s / 3600);
    const m = Math.floor((s % 3600) / 60);
    return `${h}h ${String(m).padStart(2, '0')}`;
  }
  if (s >= 60) return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;
  return `${s}s`;
}

/** Wall-clock time of arrival, e.g. "14:37". */
export function finishAt(secondsFromNow: number | null | undefined): string {
  if (secondsFromNow == null || !Number.isFinite(secondsFromNow)) return EM_DASH;
  const t = new Date(Date.now() + secondsFromNow * 1000);
  return `${String(t.getHours()).padStart(2, '0')}:${String(t.getMinutes()).padStart(2, '0')}`;
}

export function km(metres: number | null | undefined, digits = 2): string {
  if (metres == null || !Number.isFinite(metres)) return EM_DASH;
  return (metres / 1000).toFixed(digits);
}

export function num(v: number | null | undefined, digits = 0): string {
  if (v == null || !Number.isFinite(v)) return EM_DASH;
  return v.toFixed(digits);
}

export function signed(v: number | null | undefined, digits = 1): string {
  if (v == null || !Number.isFinite(v)) return EM_DASH;
  return `${v >= 0 ? '' : '−'}${Math.abs(v).toFixed(digits)}`;
}

export function axisLabel(unit: 'seconds' | 'metres'): string {
  return unit === 'metres' ? 'distance' : 'time';
}

export function axisValue(unit: 'seconds' | 'metres', x: number): string {
  return unit === 'metres' ? `${(x / 1000).toFixed(1)} km` : clock(x);
}

export function rssiBars(rssi: number): number {
  if (rssi >= -55) return 4;
  if (rssi >= -67) return 3;
  if (rssi >= -78) return 2;
  if (rssi >= -88) return 1;
  return 0;
}

export function targetText(
  target:
    | { Gradient: { percent: number } }
    | { Resistance: { level: number } }
    | { Power: { watts: number } }
    | null,
): string {
  if (!target) return EM_DASH;
  if ('Gradient' in target) return `${signed(target.Gradient.percent, 1)}%`;
  if ('Resistance' in target) return `L${target.Resistance.level}`;
  return `${target.Power.watts} W`;
}

export const MODE_LABEL: Record<string, string> = {
  ManualGrade: 'Manual grade',
  Resistance: 'Resistance',
  Profile: 'Profile',
  Erg: 'ERG',
};

export function connectionText(
  state: string | { Lost: { reason: string } },
): { label: string; tone: 'ok' | 'warn' | 'bad' | 'idle' } {
  if (typeof state !== 'string') return { label: `Lost — ${state.Lost.reason}`, tone: 'bad' };
  switch (state) {
    case 'Controlling':
      return { label: 'Connected', tone: 'ok' };
    case 'Connected':
      return { label: 'Connected', tone: 'warn' };
    case 'Connecting':
      return { label: 'Connecting', tone: 'warn' };
    case 'Reconnecting':
      return { label: 'Reconnecting', tone: 'warn' };
    case 'Scanning':
      return { label: 'Discovered', tone: 'idle' };
    default:
      return { label: 'Idle', tone: 'idle' };
  }
}
