#!/usr/bin/env node
// check-roles-doc-completeness.mjs
// Asserts every specialist on disk has a row in the authoritative roles doc.
// Brands: --brand maxy (default) | --brand real-agent
import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
import { resolve, join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const here = dirname(fileURLToPath(import.meta.url));
const maxyCodeRoot = resolve(here, '..', '..');

const args = process.argv.slice(2);
const brandIdx = args.indexOf('--brand');
const brand = brandIdx === -1 ? 'maxy' : args[brandIdx + 1];

const config = {
  maxy: {
    diskDir: resolve(maxyCodeRoot, 'platform/templates/specialists/agents'),
    docPath: resolve(maxyCodeRoot, 'platform/plugins/docs/references/platform.md'),
  },
  'real-agent': {
    diskDir: resolve(maxyCodeRoot, 'premium-plugins/real-agent/agents'),
    docPath: resolve(maxyCodeRoot, 'premium-plugins/real-agent/docs/references/real-agent-roles.md'),
  },
};

if (!config[brand]) {
  console.error(`[check-roles-doc] unknown brand: ${brand}`);
  process.exit(2);
}

const { diskDir, docPath } = config[brand];
const TABLE_HEADER = '| Role | What it does |';

if (!existsSync(diskDir)) {
  console.error(`[check-roles-doc] disk dir missing: ${diskDir}`);
  process.exit(2);
}

function listSpecialists(dir) {
  const out = [];
  for (const entry of readdirSync(dir)) {
    const full = join(dir, entry);
    const st = statSync(full);
    if (st.isFile() && entry.endsWith('.md')) {
      out.push(entry.replace(/\.md$/, ''));
    } else if (st.isDirectory()) {
      if (existsSync(join(full, 'IDENTITY.md'))) out.push(entry);
    }
  }
  return out.sort();
}

const diskSpecialists = listSpecialists(diskDir);

if (!existsSync(docPath)) {
  console.error(`[check-roles-doc] doc missing: ${docPath}`);
  console.error(`[check-roles-doc] disk specialists (${diskSpecialists.length}): ${diskSpecialists.join(', ')}`);
  process.exit(1);
}

const docBody = readFileSync(docPath, 'utf8');

function extractRoleRows(body, header) {
  const lines = body.split(/\r?\n/);
  const start = lines.findIndex((l) => l.trim() === header.trim());
  if (start === -1) return [];
  const rows = [];
  for (let i = start + 2; i < lines.length; i++) {
    const ln = lines[i];
    if (!ln.startsWith('|')) break;
    const cells = ln.split('|').map((c) => c.trim()).filter(Boolean);
    if (cells.length >= 2) rows.push(cells[0]);
  }
  return rows;
}

const rowLabels = extractRoleRows(docBody, TABLE_HEADER);

const slugify = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
const rowSlugs = new Set(rowLabels.map(slugify));

const missing = diskSpecialists.filter((s) => !rowSlugs.has(slugify(s)));
const stale = rowLabels.filter((r) => !diskSpecialists.some((s) => slugify(s) === slugify(r)));

if (missing.length === 0 && stale.length === 0) {
  console.log(`[check-roles-doc] brand=${brand} ok — ${diskSpecialists.length} specialists documented`);
  process.exit(0);
}

console.error(`[check-roles-doc] brand=${brand} FAIL`);
console.error(`  disk specialists (${diskSpecialists.length}): ${diskSpecialists.join(', ')}`);
console.error(`  doc rows (${rowLabels.length}): ${rowLabels.join(', ')}`);
if (missing.length) console.error(`  MISSING from doc: ${missing.join(', ')}`);
if (stale.length) console.error(`  STALE in doc (no template): ${stale.join(', ')}`);
process.exit(1);
