#!/usr/bin/env node
// scripts/generate-squad-workflow-stubs.js
//
// Walks `.catalog/squads/*/SQUAD.md`, extracts the workflows declared in
// each squad's embedded yaml block (the `workflows:` list under
// `components:`), and creates parse-clean stub `.yaml` files at
// `.catalog/squads/<squad-id>/workflows/<ref>` for any reference that
// lacks a corresponding file on disk.
//
// Stubs are marked `status: draft` so the framework treats them as
// pending fleshing-out (via aiobuilder evolve or manual editing).
//
// Idempotent: re-running only creates missing files, never overwrites.

const fs = require('fs');
const path = require('path');

const REPO_ROOT = path.resolve(__dirname, '..');
const SQUADS_DIR = path.join(REPO_ROOT, '.catalog', 'squads');

if (!fs.existsSync(SQUADS_DIR)) {
  console.error(`SQUADS_DIR_MISSING: ${SQUADS_DIR}`);
  process.exit(1);
}

function humanize(ref) {
  return ref
    .replace(/\.ya?ml$/, '')
    .replace(/^wf-/, '')
    .replace(/-/g, ' ')
    .replace(/\b\w/g, (c) => c.toUpperCase());
}

function extractWorkflowRefs(squadMd) {
  // Matches:
  //   workflows:
  //     - wf-foo.yaml
  //     - wf-bar.yaml
  // (possibly nested with extra indentation; we just match the list items)
  const refs = new Set();
  const lines = squadMd.split('\n');
  let inWorkflowBlock = false;
  let workflowIndent = -1;

  for (const raw of lines) {
    const trimmed = raw.trimStart();
    const indent = raw.length - trimmed.length;

    if (/^workflows:\s*$/.test(trimmed)) {
      inWorkflowBlock = true;
      workflowIndent = indent;
      continue;
    }

    if (inWorkflowBlock) {
      // Exit block on the first non-list-item line at or below the parent indent
      if (trimmed === '' || (indent <= workflowIndent && !trimmed.startsWith('-'))) {
        inWorkflowBlock = false;
        continue;
      }
      // List item: `- wf-foo.yaml` or `- "wf-foo.yaml"`
      const m = trimmed.match(/^-\s+["']?([^"'\s]+\.ya?ml)["']?\s*$/);
      if (m) refs.add(m[1]);
    }
  }

  return Array.from(refs);
}

function renderStub(ref, squadId) {
  const id = ref.replace(/\.ya?ml$/, '');
  const name = humanize(ref);
  // Stub is a parse-clean Workflow YAML. status:draft signals not-yet-fleshed.
  return `workflow:
  id: ${squadId}/${id}
  name: "${name} (${squadId})"
  description: >-
    Stub workflow scaffolded for squad ${squadId}. Declared in SQUAD.md but
    not yet fleshed out. Run \`openlife aiobuilder evolve\` or edit manually
    to define phases, sequence, and success criteria.
  type: custom
  version: "0.1"
  status: draft
  framework: openlife-method

  sequence:
    - phase: 1
      name: "TODO"
    - id: todo-step
      agent: openlife-forge
      action: define_workflow
      notes: |
        Define the squad-internal workflow logic here.
        Replace this stub with real phases and steps. When complete, change
        status from "draft" to "active".

  handoff_prompts:
    initial: "This is a stub — define the workflow before running it."
`;
}

// ─── Main ───────────────────────────────────────────────────────────────

let squadsTotal = 0;
let squadsWithRefs = 0;
let stubsCreated = 0;
let stubsSkipped = 0;
const missingDetails = [];

for (const squadId of fs.readdirSync(SQUADS_DIR).sort()) {
  const squadDir = path.join(SQUADS_DIR, squadId);
  if (!fs.statSync(squadDir).isDirectory()) continue;
  if (squadId.startsWith('test-')) continue; // test pollution

  squadsTotal++;
  const squadMdPath = path.join(squadDir, 'SQUAD.md');
  if (!fs.existsSync(squadMdPath)) continue;

  const content = fs.readFileSync(squadMdPath, 'utf-8');
  const refs = extractWorkflowRefs(content);
  if (refs.length === 0) continue;

  squadsWithRefs++;
  const workflowsDir = path.join(squadDir, 'workflows');
  fs.mkdirSync(workflowsDir, { recursive: true });

  for (const ref of refs) {
    const target = path.join(workflowsDir, ref);
    if (fs.existsSync(target)) {
      stubsSkipped++;
      continue;
    }
    fs.writeFileSync(target, renderStub(ref, squadId));
    stubsCreated++;
    missingDetails.push(`${squadId}/${ref}`);
  }
}

console.log(`[squad-workflow-stubs] scanned ${squadsTotal} squads (${squadsWithRefs} with workflow refs)`);
console.log(`[squad-workflow-stubs] stubs: ${stubsCreated} created, ${stubsSkipped} already existed`);
if (stubsCreated > 0 && process.env.VERBOSE) {
  console.log('Created:');
  for (const d of missingDetails) console.log('  +', d);
}
