#!/usr/bin/env node
// design-sync-gen.mjs — deterministic converter inputs for `/design-sync`.
//
// AgentDeck's design system is a CSS-class + token system (no React component
// library, no Storybook), so the design-sync converter (which targets React
// DSes) is fed two generated, gitignored inputs under `_ds_gen/`:
//
//   1. icons.tsx       — a *mechanical* transform of design/icons.jsx into an
//                        ES module: `import React`, a shared `IconProps` type,
//                        and each `Icon*` function turned into a named export.
//                        The SVG bodies stay verbatim — no reimplementation.
//   2. agentdeck.css   — tokens.css + patterns.css + components.css concatenated
//                        (the converter copies cfg.cssEntry verbatim into
//                        _ds_bundle.css; @import targets wouldn't ship, so the
//                        real CSS is inlined), with the Google-Fonts @import
//                        first so the brand families load at runtime.
//
// It also prints the discovered icon-name list to stdout (JSON) so the
// committed .design-sync/config.json componentSrcMap can be regenerated.
//
// Run from the repo root:  node scripts/design-sync-gen.mjs

import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { extractIconNames } from './lib/design-sync-icons.mjs';

const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
const GEN = join(ROOT, '_ds_gen');
mkdirSync(GEN, { recursive: true });

// ── 1. icons.tsx ───────────────────────────────────────────────────────────
const iconsSrc = readFileSync(join(ROOT, 'design/icons.jsx'), 'utf8');

// Canonical export set = the keys of `window.AgentDeckIcons = { ... }`.
const exportBlock = iconsSrc.match(/window\.AgentDeckIcons\s*=\s*\{([\s\S]*?)\}/);
if (!exportBlock) throw new Error('could not find window.AgentDeckIcons export block in design/icons.jsx');
const iconNames = extractIconNames(ROOT);

// Drop the window assignment; type _svg's options + each Icon param; add React.
let body = iconsSrc.slice(0, exportBlock.index).trimEnd();
body = body.replace(
  /function _svg\(children,/,
  'function _svg(children: React.ReactNode,',
);
// `function IconX(p)` -> `export function IconX(p: IconProps)`
body = body.replace(/\bfunction (Icon[A-Za-z0-9]+)\(p\)/g, 'export function $1(p: IconProps)');

// Guard against silent drift: if icons.jsx ever switches an icon to an arrow
// function or a different param name, the replace above misses it and the icon
// would vanish from the bundle with no error. Assert every exported name was
// actually turned into an `export function`.
const exported = new Set([...body.matchAll(/export function (Icon[A-Za-z0-9]+)\(/g)].map((m) => m[1]));
const missed = iconNames.filter((n) => !exported.has(n));
if (missed.length) {
  throw new Error(
    `design/icons.jsx: ${missed.length} icon(s) in the export block were not transformed to \`export function …(p: IconProps)\` ` +
    `(non-\`function Name(p)\` form?): ${missed.join(', ')}`,
  );
}

const iconsTsx = `// GENERATED by scripts/design-sync-gen.mjs from design/icons.jsx — do not edit.
import React from 'react';

/** Props shared by every AgentDeck icon. All optional; sensible defaults. */
export interface IconProps {
  /** Pixel size of the square icon. Default 24. */
  size?: number;
  /** Stroke/fill color. Default "currentColor" (inherits text color). */
  color?: string;
  /** Stroke width. Default 1.6. */
  stroke?: number;
  /** Fill for the SVG. Default "none". */
  fill?: string;
}

${body}
`;
writeFileSync(join(GEN, 'icons.tsx'), iconsTsx);

// ── 2. agentdeck.css ─────────────────────────────────────────────────────────
const FONT_IMPORT =
  '@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Sans+KR:wght@400;500;600;700&family=IBM+Plex+Sans+JP:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap");';

const parts = ['tokens.css', 'patterns.css', 'components.css'].map((f) => {
  const css = readFileSync(join(ROOT, 'design', f), 'utf8');
  return `/* ===== design/${f} ===== */\n${css.trim()}`;
});
const css = `/* GENERATED by scripts/design-sync-gen.mjs — do not edit.
   AgentDeck aquarium-tide design system: brand fonts + tokens + patterns + component classes. */
${FONT_IMPORT}

${parts.join('\n\n')}
`;
writeFileSync(join(GEN, 'agentdeck.css'), css);

writeFileSync(join(GEN, 'icon-names.json'), JSON.stringify(iconNames, null, 2) + '\n');

console.error(`✓ _ds_gen/icons.tsx (${iconNames.length} icons), _ds_gen/agentdeck.css`);
process.stdout.write(JSON.stringify(iconNames) + '\n');
