#!/usr/bin/env node
/**
 * Build the bundled Divi 5 catalog from a local copy of the Divi 5 theme
 * source. Walks the `visual-builder/packages/*` subtree and consolidates:
 *
 *   - module-library: every module's attribute path tree + default values
 *   - icon-library:   ~2,000 icons (name + unicode + styles)
 *   - divider-library: named SVG section dividers
 *   - mask-and-pattern-library: named background masks and patterns
 *
 * The output is one trimmed JSON file the plugin loads on demand. Re-run on
 * each Divi 5 major release. Source path is the first CLI argument; defaults
 * to the developer-local extracted location.
 */
import { readFileSync, writeFileSync, readdirSync, existsSync, statSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));

const DEFAULT_SOURCE = '/tmp/divi5-newest/Divi/includes/builder-5/visual-builder/packages';
const DEFAULT_DIVI_ROOT = '/tmp/divi5-newest/Divi';
const sourceDir = process.argv[2] || DEFAULT_SOURCE;
// Best-effort: locate the theme root for sibling assets (Google Fonts).
const diviRoot = process.argv[3] || DEFAULT_DIVI_ROOT;
const outFile = join(__dirname, '..', 'assets', 'divi5-catalog.json');

if (!existsSync(sourceDir)) {
  console.error(`Source directory not found: ${sourceDir}`);
  console.error(`Pass the visual-builder/packages dir as the first argument.`);
  process.exit(1);
}

// ---- Helpers ----

function stripComments(v) {
  if (!v || typeof v !== 'object') return v;
  if (Array.isArray(v)) return v.map(stripComments);
  const out = {};
  for (const [k, val] of Object.entries(v)) {
    if (k === '_comment') continue;
    out[k] = stripComments(val);
  }
  return out;
}

function trimAttrs(v) {
  if (!v || typeof v !== 'object') return v;
  if (Array.isArray(v)) return v.map(trimAttrs);
  const out = {};
  for (const [k, val] of Object.entries(v)) {
    if (k === '_comment') continue;
    if (k === 'settings') continue; // Visual-builder UI metadata — not useful to AI
    if (val && typeof val === 'object') {
      const child = trimAttrs(val);
      if (typeof child === 'object' && !Array.isArray(child) && Object.keys(child).length === 0) continue;
      out[k] = child;
    } else {
      out[k] = val;
    }
  }
  return out;
}

function readJson(path) {
  try { return JSON.parse(readFileSync(path, 'utf8')); }
  catch { return null; }
}

// ---- Modules ----

const modulesDir = join(sourceDir, 'module-library', 'src', 'components');
const modules = {};
let modIncluded = 0, modSkipped = 0;

if (existsSync(modulesDir)) {
  for (const entry of readdirSync(modulesDir)) {
    const dir = join(modulesDir, entry);
    if (!statSync(dir).isDirectory()) continue;
    const mod = readJson(join(dir, 'module.json'));
    if (!mod || !mod.name) { modSkipped++; continue; }
    const render = readJson(join(dir, 'module-default-render-attributes.json'));
    const style  = readJson(join(dir, 'module-default-printed-style-attributes.json'));
    // conversion-outline maps Divi 4 shortcode attribute names to Divi 5
    // block attribute paths. Lets the AI intelligently convert an existing
    // D4 layout's attributes to the right D5 paths.
    const conversion = readJson(join(dir, 'conversion-outline.json'));
    modules[mod.name] = {
      name: mod.name,
      d4Shortcode: mod.d4Shortcode || null,
      title: mod.title || '',
      category: mod.category || '',
      nestable: !!mod.nestable,
      childModuleName: mod.childModuleName || null,
      childModuleTitle: mod.childModuleTitle || null,
      attributes: trimAttrs(mod.attributes || {}),
      defaults: {
        render: stripComments(render),
        printedStyle: stripComments(style),
      },
      conversionOutline: stripComments(conversion),
    };
    modIncluded++;
  }
}

// ---- Google Fonts ----

const gfontsPath = join(diviRoot, 'core', 'json-data', 'google-fonts.json');
const gfontsRaw = readJson(gfontsPath);
const googleFonts = ((gfontsRaw && gfontsRaw.items) || []).map((f) => ({
  family: f.family,
  category: f.category,
  variants: f.variants || [],
  subsets: f.subsets || [],
}));

// ---- Icons ----

const iconListPath = join(sourceDir, 'icon-library', 'src', 'components', 'icon-font', 'iconList.json');
const iconList = readJson(iconListPath) || [];
const icons = iconList.map((i) => ({
  name: i.name,
  unicode: i.unicode,
  decoded: i.decodedUnicode,
  styles: i.styles || [],
  weight: i.fontWeight,
}));

// ---- Dividers ----

const dividerDir = join(sourceDir, 'divider-library', 'src', 'components');
const dividers = [];
if (existsSync(dividerDir)) {
  for (const f of readdirSync(dividerDir)) {
    if (!f.endsWith('.json')) continue;
    const name = f.replace(/\.json$/, '');
    dividers.push({ name });
  }
}

// ---- Masks & Patterns ----

function listLibrary(rel) {
  const dir = join(sourceDir, 'mask-and-pattern-library', 'src', 'components', rel, 'components');
  if (!existsSync(dir)) return [];
  return readdirSync(dir)
    .filter((f) => f.endsWith('.json'))
    .map((f) => ({ name: f.replace(/\.json$/, '') }));
}

const masks = listLibrary('mask-svg');
const patterns = listLibrary('pattern-svg');

// ---- Output ----

const catalog = {
  generated_at: new Date().toISOString(),
  source: sourceDir,
  divi_version: 'detect from source style.css',
  notes: 'Bundled Divi 5 reference: modules (with attribute schemas, defaults, and D4→D5 attribute mappings), icons, dividers, masks, patterns, Google Fonts. Used as fallback / enrichment for divi_module_schema, divi_module_example, divi_module_catalog, divi_asset_catalog. Re-run bin/build-divi5-catalog.mjs after each Divi 5 release.',
  module_count: modIncluded,
  icon_count: icons.length,
  divider_count: dividers.length,
  mask_count: masks.length,
  pattern_count: patterns.length,
  google_font_count: googleFonts.length,
  modules,
  icons,
  dividers,
  masks,
  patterns,
  googleFonts,
};

writeFileSync(outFile, JSON.stringify(catalog));
const sizeKb = (statSync(outFile).size / 1024).toFixed(1);
console.log(`Wrote ${outFile}`);
console.log(`Modules: ${modIncluded} (${modSkipped} skipped)`);
console.log(`Icons: ${icons.length}`);
console.log(`Dividers: ${dividers.length}`);
console.log(`Masks: ${masks.length}`);
console.log(`Patterns: ${patterns.length}`);
console.log(`Google Fonts: ${googleFonts.length}`);
console.log(`File size: ${sizeKb} KB`);
