import { Icon } from './Icon';
import { Tag } from './ui';
import type { Tone } from '../lib/format';
import type { RuntimeHealth, RuntimeLevel, RuntimeTrend } from '../api/types';

/* The two places the process figures are read — the overview's Process card and the
   Runtime page — say the same things about them, so the wording lives here rather than
   twice. None of it decides anything: the verdict, its sentences and the areas to
   investigate all arrive from the gateway, and this renders what it was handed. */

export const levelTone: Record<RuntimeLevel, Tone> = {
  ok: 'ok',
  watch: 'warn',
  bad: 'bad',
};

const levelWord: Record<RuntimeLevel, string> = {
  ok: 'Healthy',
  watch: 'Worth watching',
  bad: 'Needs attention',
};

/** RuntimeVerdict is the headline. It replaces a bare goroutine count with the answer that
 *  count was standing in for, and when there is something to look at it names the area
 *  rather than leaving an operator to work out which number matters. */
export function RuntimeVerdict({
  health,
  compact,
}: {
  health: RuntimeHealth;
  compact?: boolean;
}) {
  const notes = health.notes ?? [];
  return (
    <div className="verdict" data-tone={levelTone[health.level] ?? 'ok'}>
      <div className="verdict-head">
        <Icon name={health.level === 'ok' ? 'check' : 'alert'} />
        <b>{levelWord[health.level] ?? 'Unknown'}</b>
        <span>{health.summary}</span>
      </div>
      {/* On the overview the summary is the whole of it — the card is a signpost, and the
          notes belong on the page it points at. */}
      {compact || notes.length === 0 ? null : (
        <ul className="verdict-notes">
          {notes.map((note, index) => (
            <li key={`${note.area}-${index}`}>
              <Tag tone={levelTone[note.level] ?? 'note'}>{note.area}</Tag>
              <span>{note.message}</span>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

/** trendWord turns a trend into the half-sentence that sits under a figure. "Steady" is
 *  worth printing: it is the answer to the question the figure raises, and a tile that
 *  says nothing when nothing is wrong makes the operator check anyway. */
export function trendWord(trend: RuntimeTrend, format: (value: number) => string): string {
  switch (trend.direction) {
    case 'rising':
      return `rising ${format(Math.abs(trend.perHour))} an hour`;
    case 'falling':
      return `falling ${format(Math.abs(trend.perHour))} an hour`;
    case 'steady':
      return 'steady';
    default:
      return 'gathering history';
  }
}

/** uptime words how long the process has been up. Days matter here and seconds do not: the
 *  question this answers is "has it restarted", not "how long exactly". */
export function uptime(seconds: number): string {
  if (!seconds || seconds < 60) return `${Math.max(0, Math.round(seconds))}s`;
  const minutes = Math.floor(seconds / 60);
  if (minutes < 60) return `${minutes} min`;
  const hours = Math.floor(minutes / 60);
  if (hours < 48) return `${hours}h ${minutes % 60}m`;
  return `${Math.floor(hours / 24)} days`;
}
