#!/usr/bin/env node
/**
 * sync-doc-paths — Propagate DocCenter path changes to all workflow JSONs.
 *
 * Usage:
 *   node scripts/sync-doc-paths.js              # dry-run (show renames only)
 *   node scripts/sync-doc-paths.js --apply      # actually write changes
 *   node scripts/sync-doc-paths.js --rename 6:16  # move path 6 → 16 everywhere
 *   node scripts/sync-doc-paths.js --rename 6:16,2:12  # multiple renames
 *   node scripts/sync-doc-paths.js --sync-desc   # also sync descriptions from registry
 *
 * What it does:
 *   1. Reads src/data/doc-paths.js as the source of truth
 *   2. Scans all workflow JSONs (both .vl-code/workflows/ and seed-workflows/)
 *   3. For each workflow:
 *      a. Updates registry.docs descriptions to match doc-paths.js
 *      b. If --rename given, remaps old path → new path in registry.docs keys + step docs arrays
 *   4. Updates hardcoded docId references in JS source files
 */
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '..');

// Dynamic import of doc-paths (ES module)
const { PATH_MAP, DOC_REGISTRY } = await import('../src/data/doc-paths.js');

const args = process.argv.slice(2);
const apply = args.includes('--apply');
const syncDesc = args.includes('--sync-desc');
const renameIdx = args.indexOf('--rename');
const renames = new Map(); // oldPath → newPath

if (renameIdx !== -1 && args[renameIdx + 1]) {
  for (const pair of args[renameIdx + 1].split(',')) {
    const [from, to] = pair.split(':').map(Number);
    if (!isNaN(from) && !isNaN(to)) {
      renames.set(from, to);
    }
  }
}

// ─── Workflow JSON directories ──────────────────────────────────
const WORKFLOW_DIRS = [
  path.join(ROOT, '.vl-code', 'workflows'),
  path.join(ROOT, 'public', 'seed-workflows'),
];

let totalChanges = 0;

console.log(`\n📄 DocCenter Path Sync ${apply ? '(APPLY MODE)' : '(DRY RUN)'}`);
console.log(`   Registry: ${Object.keys(DOC_REGISTRY).length} entries`);
if (renames.size > 0) {
  console.log(`   Renames: ${[...renames.entries()].map(([f, t]) => `${f}→${t}`).join(', ')}`);
}
console.log('');

// ─── Phase 1: Update workflow JSONs ─────────────────────────────
for (const dir of WORKFLOW_DIRS) {
  if (!fs.existsSync(dir)) continue;

  const files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
  for (const file of files) {
    const fp = path.join(dir, file);
    const relPath = path.relative(ROOT, fp);
    let content = fs.readFileSync(fp, 'utf-8');
    let data;
    try { data = JSON.parse(content); } catch { continue; }

    const changes = [];
    const registryDocs = data?.registry?.docs;

    if (registryDocs && typeof registryDocs === 'object') {
      // 1a. Apply renames to registry.docs keys
      if (renames.size > 0) {
        const newDocs = {};
        for (const [pathStr, desc] of Object.entries(registryDocs)) {
          const pathNum = Number(pathStr);
          const newPath = renames.get(pathNum);
          if (newPath !== undefined) {
            newDocs[String(newPath)] = desc;
            changes.push(`  registry.docs: key ${pathStr} → ${newPath}`);
          } else {
            newDocs[pathStr] = desc;
          }
        }
        data.registry.docs = newDocs;
      }

      // 1b. Sync descriptions from doc-paths.js (only with --sync-desc flag)
      // NOTE: Some path numbers are reused across workflow families with different meanings.
      // Only use --sync-desc when you've verified the registry descriptions are correct.
      if (syncDesc) {
        for (const [pathStr, desc] of Object.entries(data.registry.docs)) {
          const pathNum = Number(pathStr);
          const canonical = PATH_MAP.get(pathNum);
          if (canonical && canonical.desc !== desc) {
            changes.push(`  registry.docs["${pathStr}"]: "${desc}" → "${canonical.desc}"`);
            data.registry.docs[pathStr] = canonical.desc;
          }
        }
      }
    }

    // 1c. Apply renames to step docs arrays
    if (renames.size > 0 && data.steps) {
      const renameInSteps = (steps) => {
        for (const step of steps) {
          if (step.in?.docs && Array.isArray(step.in.docs)) {
            for (let i = 0; i < step.in.docs.length; i++) {
              const pathNum = Number(step.in.docs[i]);
              const newPath = renames.get(pathNum);
              if (newPath !== undefined) {
                changes.push(`  ${step.id}.in.docs: "${step.in.docs[i]}" → "${newPath}"`);
                step.in.docs[i] = String(newPath);
              }
            }
          }
          // Recurse into children (for Fork nodes)
          if (step.children && Array.isArray(step.children)) {
            // children are IDs, not nested steps — check steps array
          }
        }
      };
      renameInSteps(data.steps);
    }

    if (changes.length > 0) {
      totalChanges += changes.length;
      console.log(`📝 ${relPath} (${changes.length} changes)`);
      for (const c of changes) console.log(c);

      if (apply) {
        fs.writeFileSync(fp, JSON.stringify(data, null, 2) + '\n', 'utf-8');
        console.log(`   ✅ Written`);
      }
      console.log('');
    }
  }
}

// ─── Phase 2: Check JS source files for hardcoded docId/path ───
const JS_FILES_TO_CHECK = [
  'src/vl/workflow-executor.js',
  'src/web/server.js',
  'src/tools/vl-parse.js',
  'src/cloud/cloud-api.js',
];

console.log('─── JS source file checks ───');
for (const relFile of JS_FILES_TO_CHECK) {
  const fp = path.join(ROOT, relFile);
  if (!fs.existsSync(fp)) continue;
  const content = fs.readFileSync(fp, 'utf-8');

  // Check for hardcoded docId numbers that should use doc-paths.js
  const docIdMatches = [...content.matchAll(/docId[:\s]*(\d+)/g)];
  for (const m of docIdMatches) {
    const docId = Number(m[1]);
    // Find if this docId is in our registry
    for (const [alias, entry] of Object.entries(DOC_REGISTRY)) {
      if (entry.docId === docId) {
        console.log(`  ⚠ ${relFile}: hardcoded docId ${docId} → should use docIdFor('${alias}') from doc-paths.js`);
        totalChanges++;
      }
    }
  }
}

// ─── Summary ────────────────────────────────────────────────────
console.log(`\n${apply ? '✅' : '📋'} Total: ${totalChanges} change(s) ${apply ? 'applied' : 'found (use --apply to write)'}\n`);
