#!/usr/bin/env node
/**
 * cli:compute-page-diff — entry point.
 *
 * PURE spec-diff for ba-develop Phase 3a targeted re-runs. Compares the
 * canonical hash of every `pagespecs/<Entity>.<view>.md` machine block against
 * the previous `.run-snapshot.json` and reports added / modified / removed /
 * unchanged. `toRegenerate = added ∪ modified`.
 *
 * This CLI performs NO inspection of generated `.tsx` files — the disk-drift
 * guard (closing the silent-skip class) is the orchestrator's job. See
 * `references/gates.md` § "Phase 3 pre-entry" and `disk-drift.ts`.
 *
 * Invocation:
 *   npx tsx skills/ba-develop/cli/compute-page-diff/index.ts \
 *     --spec '{"moduleRoot":".smartstack/ba/<APP>/<MODULE>"}'
 *
 * Exit code: always 0 on a successful diff. An empty `toRegenerate` is a valid
 * "nothing changed in the specs" answer, NOT a failure — the orchestrator still
 * runs the disk-drift guard before deciding to skip Phase 3a.
 */
import { parseArgs } from 'node:util'
import { validate } from './validate.js'
import { computeDiff } from './compute-diff.js'
import { executeEnvelope, failExecute, printEnvelope } from '../../../lib/output.js'
import type { ComputePageDiffReport } from './types.js'

const COMMAND = 'compute-page-diff'

function main(): void {
  const { values } = parseArgs({
    options: { spec: { type: 'string' } },
    strict: true,
  })

  if (!values.spec) {
    printEnvelope(failExecute<ComputePageDiffReport>(COMMAND, ['--spec is required']))
    process.exit(1)
  }

  let raw: unknown
  try {
    raw = JSON.parse(values.spec)
  } catch {
    printEnvelope(failExecute<ComputePageDiffReport>(COMMAND, ['Invalid JSON in --spec']))
    process.exit(1)
  }

  const validation = validate(raw)
  if (!validation.valid || !validation.spec) {
    printEnvelope(failExecute<ComputePageDiffReport>(COMMAND, validation.errors))
    process.exit(1)
  }

  const report = computeDiff(validation.spec)

  const nextSteps: string[] = []
  if (!report.snapshotFound) {
    nextSteps.push(
      'No .run-snapshot.json found (first run): every page is "added" → regenerate all, then write the snapshot via update-snapshot.',
    )
  }
  nextSteps.push(
    'Orchestrator: regenerate = toRegenerate ∪ disk-drift. For each page in diff.unchanged, run validate-page; ' +
      'fold in any page whose .tsx is missing or has err violations. Skip Phase 3a ONLY if the union is empty. ' +
      'After a successful regeneration, run update-snapshot. See references/gates.md § "Phase 3 pre-entry".',
  )

  printEnvelope(
    executeEnvelope<ComputePageDiffReport>(COMMAND, {
      success: true,
      data: {
        added: report.diff.added.length,
        modified: report.diff.modified.length,
        removed: report.diff.removed.length,
        unchanged: report.diff.unchanged.length,
        toRegenerate: report.toRegenerate.length,
        snapshotFound: report.snapshotFound,
      },
      report,
      warnings: report.warnings,
      nextSteps,
    }),
  )

  process.exit(0)
}

main()
