import { h } from '../core/dom';
import { store, type ToolId } from '../core/store';
import { icon } from '../ui/icons';
import { TOOLS } from './tools';
import { clamp } from '../core/util';

export interface ToolbarCallbacks {
  onZoom: (scale: number) => void;
  onFit: () => void;
  // unified undo/redo (annotation snapshots + native byte edits); default to store
  onUndo?: () => void;
  onRedo?: () => void;
  canUndo?: () => boolean;
  canRedo?: () => boolean;
}

export function buildToolbar(cb: ToolbarCallbacks): HTMLElement {
  const toolButtons = new Map<ToolId, HTMLElement>();
  // Tools are grouped into labeled sections (Basics, Shapes, Markup, …) — each
  // section stacks as a label + 2-column grid down the left rail on desktop.
  // On mobile the labels/dividers collapse and every button flows into one
  // flat horizontally-scrolling strip (see CSS).
  const groups: HTMLElement[] = [];
  let currentGroup = -1;
  let groupBtns: HTMLElement | null = null;
  for (const t of TOOLS) {
    if (t.group !== currentGroup) {
      currentGroup = t.group;
      groupBtns = h('div.tool-group-btns');
      groups.push(h('div.tool-group', h('div.tool-group-label', t.groupName), groupBtns));
    }
    const btn = h(
      'button.tool-btn',
      { title: t.label + (t.hotkey ? ` (${t.hotkey.toUpperCase()})` : ''), onclick: () => store.setTool(t.id) },
      icon(t.icon, 19),
      h('span.tool-label', t.short ?? t.label),
    );
    toolButtons.set(t.id, btn);
    groupBtns!.appendChild(btn);
  }

  const zoomLabel = h('span.zoom-val', '100%');
  const zoomOutBtn = h('button.zoom-btn', { title: 'Zoom out', onclick: () => step(-1) }, icon('minus', 15));
  const zoomInBtn = h('button.zoom-btn', { title: 'Zoom in', onclick: () => step(1) }, icon('plus', 15));
  const zoomFitBtn = h('button.zoom-btn', { title: 'Fit width', onclick: cb.onFit }, icon('fit', 15));
  const zoomCtl = h('div.zoom-ctl', zoomOutBtn, zoomLabel, zoomInBtn, zoomFitBtn);

  function step(dir: number) {
    const next = clamp(Math.round((store.zoom + dir * 0.1) * 10) / 10, 0.2, 5);
    cb.onZoom(next);
  }

  const undoBtn = h('button.tool-btn', { title: 'Undo (⌘Z)', onclick: () => (cb.onUndo ? cb.onUndo() : store.undo()) }, icon('undo', 19), h('span.tool-label', 'Undo'));
  const redoBtn = h('button.tool-btn', { title: 'Redo (⌘⇧Z)', onclick: () => (cb.onRedo ? cb.onRedo() : store.redo()) }, icon('redo', 19), h('span.tool-label', 'Redo'));
  const historyGroup = h('div.tool-group', h('div.tool-group-label', 'History'), h('div.tool-group-btns', undoBtn, redoBtn));

  const bar = h(
    'div.toolbar',
    zoomCtl,
    ...groups,
    historyGroup,
  );

  const syncActive = () => {
    for (const [id, btn] of toolButtons) btn.classList.toggle('active', store.tool === id);
  };
  const syncHistory = () => {
    (undoBtn as HTMLButtonElement).disabled = !(cb.canUndo ? cb.canUndo() : store.canUndo());
    (redoBtn as HTMLButtonElement).disabled = !(cb.canRedo ? cb.canRedo() : store.canRedo());
  };
  const syncZoom = () => { zoomLabel.textContent = `${Math.round(store.zoom * 100)}%`; };
  // Every tool here draws on / edits the currently open document's canvas —
  // there's nothing for any of them to do without one, so lock the whole rail
  // (and zoom, which has nothing to zoom) until a document is open.
  const syncDocState = () => {
    const hasDoc = !!store.doc;
    for (const [, btn] of toolButtons) (btn as HTMLButtonElement).disabled = !hasDoc;
    (zoomOutBtn as HTMLButtonElement).disabled = !hasDoc;
    (zoomInBtn as HTMLButtonElement).disabled = !hasDoc;
    (zoomFitBtn as HTMLButtonElement).disabled = !hasDoc;
  };

  store.on('tool', syncActive);
  store.on('history', syncHistory);
  store.on('zoom', syncZoom);
  store.on('doc', syncDocState);
  syncActive(); syncHistory(); syncZoom(); syncDocState();

  return bar;
}
