// app.js — boot, router, theme, command palette wiring.
// Each pane self-registers via registerPane(); only the active pane is initialized.

import { jget } from './lib/api.js';
import { initPalette, registerCommand, setHealthPill, setBrandVer, setFooterBuild, ok, err } from './lib/ui.js';

// Pane registry: id -> { label, init(host), refresh?(host), inited:false }
const PANES = new Map();
const MAIN  = document.getElementById('main');

export function registerPane(id, def) {
  PANES.set(id, { ...def, inited: false });
  registerCommand({
    id: `go:${id}`,
    label: `Go to ${def.label}`,
    group: 'Navigate',
    keywords: `tab ${id} ${def.label}`,
    run: () => activate(id),
  });
}

// dynamic imports so each pane is its own ES module
const PANE_LOADERS = {
  dashboard: () => import('./panes/dashboard.js'),
  agent:     () => import('./panes/agent.js'),
  inbox:     () => import('./panes/inbox.js'),
  tools:     () => import('./panes/tools.js'),
  items:     () => import('./panes/items.js'),
  diffusion: () => import('./panes/diffusion.js'),
  demand:    () => import('./panes/demand.js'),
  lang:      () => import('./panes/lang.js'),
  slack:     () => import('./panes/slack.js'),
  mac:       () => import('./panes/mac.js'),
  files:     () => import('./panes/files.js'),
  api:       () => import('./panes/api.js'),
  websocket: () => import('./panes/websocket.js'),
  system:    () => import('./panes/system.js'),
  about:     () => import('./panes/about.js'),
};

const NAV_LABELS = {
  dashboard: 'Dashboard', agent: 'Agent', inbox: 'Inbox', tools: 'Tools',
  items: 'Items', diffusion: 'Diffusion', demand: 'Demand', lang: 'Lang',
  slack: 'Slack', mac: 'macOS', files: 'Files · Platform', api: 'API Explorer', websocket: 'WebSocket',
  system: 'System', about: 'About',
};

async function activate(id) {
  if (!PANE_LOADERS[id]) id = 'dashboard';

  // mark nav
  document.querySelectorAll('.nav-item').forEach(el => {
    el.classList.toggle('active', el.dataset.tab === id);
  });
  // mark pane
  document.querySelectorAll('.pane').forEach(el => {
    el.classList.toggle('active', el.dataset.pane === id);
  });
  const crumb = document.getElementById('crumb-tab');
  if (crumb) crumb.textContent = NAV_LABELS[id] || id;
  document.title = `${NAV_LABELS[id] || id} · CxWebApp`;

  if (location.hash !== `#${id}`) history.replaceState(null, '', `#${id}`);

  // lazy-load pane module
  if (!PANES.has(id)) {
    try { await PANE_LOADERS[id](); }
    catch (e) {
      console.error(`pane ${id} failed to load`, e);
      const host = document.querySelector(`[data-pane="${id}"]`);
      if (host) host.innerHTML = `<div class="card"><div class="muted">Failed to load ${id}: ${e.message}</div></div>`;
      return;
    }
  }
  const pane = PANES.get(id);
  if (!pane) return;
  const host = document.querySelector(`[data-pane="${id}"]`);
  if (!host) return;
  if (!pane.inited) {
    try { await pane.init(host); pane.inited = true; }
    catch (e) { err(`init ${id}: ${e.message}`); console.error(e); }
  } else if (pane.refresh) {
    try { await pane.refresh(host); } catch (e) { console.warn(`refresh ${id}`, e); }
  }
}

// ---------------- theme ----------------
const themeBtn = document.getElementById('theme-toggle');
themeBtn?.addEventListener('click', () => {
  const dark = document.documentElement.classList.toggle('dark');
  localStorage.setItem('cx_theme', dark ? 'dark' : 'light');
});

// ---------------- nav ----------------
document.querySelectorAll('.nav-item').forEach(el => {
  el.addEventListener('click', () => activate(el.dataset.tab));
});

window.addEventListener('hashchange', () => {
  const id = (location.hash || '').replace('#', '');
  if (id) activate(id);
});

// ---------------- header health + version ----------------
async function refreshHealth() {
  try {
    const j = await jget('/api/health');
    setHealthPill('ok', 'healthy');
    return j;
  } catch (e) {
    setHealthPill('err', 'down');
  }
}
async function refreshVersion() {
  try {
    const j = await jget('/api/version');
    setBrandVer(`${j.name || 'cxwebapp'} ${j.version || ''}`.trim());
    setFooterBuild(`${(j.git_sha || '').slice(0, 7) || '—'} · ${j.build_time || ''}`.trim());
  } catch {
    setBrandVer('—');
  }
}

// ---------------- palette commands (global) ----------------
function registerGlobalCommands() {
  registerCommand({ id: 'theme:toggle', label: 'Toggle theme', group: 'View', run: () => themeBtn?.click() });
  registerCommand({ id: 'reload',       label: 'Reload page',  group: 'View', run: () => location.reload() });
  registerCommand({ id: 'open:health',  label: 'Open /api/health', group: 'API', run: () => window.open('/api/health', '_blank') });
  registerCommand({ id: 'open:version', label: 'Open /api/version', group: 'API', run: () => window.open('/api/version', '_blank') });
  registerCommand({ id: 'open:system',  label: 'Open /api/system', group: 'API', run: () => window.open('/api/system', '_blank') });
}

// ---------------- boot ----------------
(async function boot() {
  initPalette();
  registerGlobalCommands();

  const initial = (location.hash || '#dashboard').replace('#', '');
  await activate(initial);

  refreshHealth();
  refreshVersion();
  setInterval(refreshHealth, 10_000);

  // greet once
  ok('Control center ready', 'CxWebApp');
})();
