// <Root> — root of the Preact rewrite. Wires `Header` + `StatusChips`
// to the real `/api/state` snapshot via `useAgentState`. Still a slice,
// not the whole page — see main.tsx's file comment for what's left
// (the live SSE stream, login flow, inbox/todos, term input, overflow).
import type { BadgeTone } from '@hive/shared/badge.js';
import { Header } from './components/Header.js';
import { StatusChips } from './components/StatusChips.js';
import { useAgentState } from './hooks/useAgentState.js';
import { fmtAge, fmtTokens } from './lib/format.js';
import { resolveDashboardBase } from './lib/dashboardBase.js';
import { submitPauseResume } from './lib/pauseAction.js';
import { postModel, postEffort } from './lib/modelEffort.js';
import type { TokenUsage } from './types.js';

const ALIVE_LABELS: Record<string, { glyph: string; text: string; tone: BadgeTone }> = {
  online: { glyph: '●', text: 'alive', tone: 'positive' },
  rate_limited: { glyph: '⊘', text: 'rate limited', tone: 'warning' },
  needs_login_idle: { glyph: '◌', text: 'needs login', tone: 'warning' },
  needs_login_in_progress: { glyph: '◌', text: 'logging in', tone: 'warning' },
};
const STATE_LABELS: Record<string, { glyph: string; text: string; tone: BadgeTone }> = {
  idle: { glyph: '💤', text: 'idle', tone: 'neutral' },
  thinking: { glyph: '🧠', text: 'thinking', tone: 'accent' },
  compacting: { glyph: '📦', text: 'compacting', tone: 'warning' },
};
const STATE_TOOLTIPS: Record<string, string> = {
  offline: 'harness unreachable or claude not logged in',
  idle: 'turn loop running, no claude invocation in flight',
  thinking: 'claude is executing the current turn',
  compacting: "operator-triggered /compact running on the persistent session",
};

// `total` here matches app.js's `renderOneUsage` exactly: input + both
// cache buckets, output_tokens deliberately excluded (it's shown in the
// title breakdown, not folded into the headline number).
function tokenTotal(u: TokenUsage | null): number | null {
  if (!u) return null;
  return (u.input_tokens ?? 0) + (u.cache_read_input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0);
}

export function Root() {
  const { state, refresh } = useAgentState();

  if (!state) {
    return (
      <Header label="…">
        <StatusChips
          aliveLabel="… connecting"
          aliveTone="neutral"
          stateLabel="… booting"
          stateTone="neutral"
          model=""
          availableModels={[]}
          onSelectModel={() => {}}
          effort=""
          availableEfforts={[]}
          onSelectEffort={() => {}}
          paused={false}
          onTogglePause={() => {}}
        />
      </Header>
    );
  }

  const alive = ALIVE_LABELS[state.status] ?? { glyph: '○', text: 'offline', tone: 'negative' as BadgeTone };
  // Mirrors app.js's refreshState: any non-'online' status forces the
  // turn-state badge to 'offline' regardless of the server's last-known
  // turn_state (login/rate-limit takes visual priority over a stale
  // idle/thinking reading from before the harness went offline).
  const effectiveTurnState = state.status === 'online' ? state.turn_state : 'offline';
  const turnDef = STATE_LABELS[effectiveTurnState] ?? { glyph: '○', text: 'offline', tone: 'negative' as BadgeTone };
  const stateAge = fmtAge(Date.now() - state.turn_state_since * 1000);
  const ctx = tokenTotal(state.ctx_usage);
  const cost = tokenTotal(state.cost_usage);

  return (
    <Header label={state.label} hiveLabel={[state.swarm_name, state.hive_name].filter(Boolean).join(' / ') || null}>
      <StatusChips
        aliveLabel={`${alive.glyph} ${alive.text}`}
        aliveTone={alive.tone}
        stateLabel={`${turnDef.glyph} ${turnDef.text} · ${stateAge}`}
        stateTone={turnDef.tone}
        stateTooltip={STATE_TOOLTIPS[effectiveTurnState]}
        model={state.model}
        availableModels={state.available_models}
        onSelectModel={(name) => {
          postModel(name).then(() => refresh());
        }}
        effort={state.effort}
        availableEfforts={state.available_efforts}
        onSelectEffort={(level) => {
          postEffort(level).then(() => refresh());
        }}
        ctxLabel={ctx !== null ? fmtTokens(ctx) : undefined}
        costLabel={cost !== null ? fmtTokens(cost) : undefined}
        paused={state.paused}
        onTogglePause={() => {
          submitPauseResume(resolveDashboardBase(state.dashboard_port), state.label, state.paused ? 'resume' : 'pause');
        }}
      />
    </Header>
  );
}
