/**
 * LANE-UI — build bar pagination (pure; see pages.test.ts).
 *
 * Round 2 orders: kind tabs, `[`/`]` to page, 1-9 within the active page, "every machine
 * hotkey-reachable at any catalog size".
 *
 * Kind tabs alone don't deliver that last clause: LANE-DATA's 21 machines include 14
 * crafters, and 1-9 cannot reach 14. So a page is at most PER_PAGE machines, and a kind
 * group larger than that spills into numbered pages (REFINE 1/2, REFINE 2/2). That keeps
 * the invariant true no matter how big the catalog gets.
 */
import type { MachineDef, MachineKind } from '../contracts';

/** Hotkeys are 1-9, so a page can never hold more than nine. */
export const PER_PAGE = 9;

/** Kinds collapse into these tabs, in house order: dig, move, refine, power, ship. */
const GROUP_OF: Record<MachineKind, string> = {
  extractor: 'EXTRACT',
  belt: 'LOGISTICS',
  splitter: 'LOGISTICS',
  buffer: 'LOGISTICS',
  crafter: 'REFINE',
  power: 'POWER',
  shipper: 'SHIP',
  lab: 'RESEARCH', // v4 kind
};

const GROUP_ORDER = ['EXTRACT', 'LOGISTICS', 'REFINE', 'POWER', 'RESEARCH', 'SHIP'];

export interface BuildPage {
  /** Tab label, e.g. "REFINE" or "REFINE 2/2". */
  label: string;
  machines: MachineDef[];
}

export function paginate(machines: MachineDef[], perPage: number = PER_PAGE): BuildPage[] {
  const groups = new Map<string, MachineDef[]>();
  for (const m of machines) {
    // An unknown kind still gets a home rather than vanishing from the bar.
    const g = GROUP_OF[m.kind] ?? 'OTHER';
    const list = groups.get(g);
    if (list) list.push(m);
    else groups.set(g, [m]);
  }

  const names = [...groups.keys()].sort((a, b) => {
    const ia = GROUP_ORDER.indexOf(a);
    const ib = GROUP_ORDER.indexOf(b);
    // Unknown groups sort last, alphabetically, rather than jumping the queue.
    if (ia === -1 && ib === -1) return a < b ? -1 : a > b ? 1 : 0;
    if (ia === -1) return 1;
    if (ib === -1) return -1;
    return ia - ib;
  });

  const pages: BuildPage[] = [];
  for (const name of names) {
    const list = groups.get(name)!;
    const chunks = Math.max(1, Math.ceil(list.length / perPage));
    for (let i = 0; i < chunks; i++) {
      pages.push({
        label: chunks > 1 ? `${name} ${i + 1}/${chunks}` : name,
        machines: list.slice(i * perPage, (i + 1) * perPage),
      });
    }
  }
  return pages;
}

/** Page index holding `defId`, or -1. Used to follow a click-selection to its tab. */
export function pageOf(pages: BuildPage[], defId: string): number {
  return pages.findIndex((p) => p.machines.some((m) => m.id === defId));
}
