#!/usr/bin/env node
//
// audit-dev-actions-alignment / index.ts — Entry point.
//
// Detects and reports drift between three sources of an action's URL:
//   - pagespec files at .smartstack/ba/<APP>/<MODULE>/pagespecs/<Entity>.<view>.md
//   - controller files at <backend>/src/<Ns>.Api/Controllers/<Module>/<Entity>sController.cs
//   - service files at <frontend>/src/features/<module>/<entity>/services/<entity>Service.ts
//
// Usage (read-only diagnostic — safe to run on any project):
//
//   npx tsx skills/development/audit-dev-frontend/cli/audit-dev-actions-alignment/index.ts \
//     --project-path "<web-root>" \
//     --backend-path "<dotnet-root>" \
//     --module-path  ".smartstack/ba/APP/MODULE" \
//     --mode report-only
//
// Exit code: 0 when no `err` findings, 1 otherwise. Always writes
// `<projectPath>/_audit/actions-alignment.md` (unless --no-write-report).
import { Command } from 'commander'
import path from 'node:path'
import { mkdir, writeFile } from 'node:fs/promises'
import { validateArgs } from './validate.js'
import { audit, reportPath } from './audit.js'
import { apply } from './apply.js'
import type { ActionAlignmentOutput } from './types.js'

const program = new Command()

program
  .name('audit-dev-actions-alignment')
  .description('Detect drift between pagespec / controller / service.ts custom-action URLs')
  .requiredOption('--project-path <path>', 'Absolute path to the frontend root (src/features/**)')
  .requiredOption('--backend-path <path>', 'Absolute path to the .NET backend root (src/**/*Controller.cs)')
  .option('--module-path <path>', 'Absolute path to .smartstack/ba/<APP>/<MODULE> (otherwise auto-discover under project-path)')
  .option('--mode <mode>', 'report-only | apply', 'report-only')
  .option('--source-of-truth <side>', 'pagespec | controller (used by --mode apply)', 'pagespec')
  .option('--no-write-report', 'Skip writing _audit/actions-alignment.md (stdout only)')
  .parse(process.argv)

const opts = program.opts()

const raw = {
  projectPath: opts.projectPath as string,
  backendPath: opts.backendPath as string,
  modulePath: opts.modulePath as string | undefined,
  mode: opts.mode as string,
  sourceOfTruth: opts.sourceOfTruth as string,
  writeReport: opts.writeReport !== false,
}

const validation = validateArgs(raw)
if (!validation.valid || !validation.args) {
  const output: ActionAlignmentOutput = {
    success: false,
    command: 'audit-dev-actions-alignment',
    data: {
      mode: (raw.mode as 'report-only' | 'apply') ?? 'report-only',
      sourceOfTruth: (raw.sourceOfTruth as 'pagespec' | 'controller') ?? 'pagespec',
      moduleDir: raw.modulePath ?? null,
    },
    report: null,
    filesModified: [],
    errors: validation.errors,
    warnings: [],
    nextSteps: ['Fix the CLI arguments and retry.'],
  }
  console.log(JSON.stringify(output, null, 2))
  process.exit(1)
}

const args = validation.args

async function main(): Promise<void> {
  try {
    const result = args.mode === 'apply'
      ? await apply(args)
      : { report: await audit(args), filesModified: [], notes: [] as string[] }

    if (args.writeReport) {
      const dest = reportPath(args.projectPath)
      await mkdir(path.dirname(dest), { recursive: true })
      await writeFile(dest, result.report.markdown, 'utf8')
    }

    const success = result.report.counts.err === 0

    const output: ActionAlignmentOutput = {
      success,
      command: 'audit-dev-actions-alignment',
      data: {
        mode: args.mode,
        sourceOfTruth: args.sourceOfTruth,
        moduleDir: args.modulePath ?? null,
      },
      report: result.report,
      filesModified: result.filesModified,
      errors: [],
      warnings: [],
      nextSteps: result.notes,
    }

    console.log(JSON.stringify(output, null, 2))
    process.exit(success ? 0 : 1)
  } catch (err) {
    const output: ActionAlignmentOutput = {
      success: false,
      command: 'audit-dev-actions-alignment',
      data: {
        mode: args.mode,
        sourceOfTruth: args.sourceOfTruth,
        moduleDir: args.modulePath ?? null,
      },
      report: null,
      filesModified: [],
      errors: [err instanceof Error ? err.message : String(err)],
      warnings: [],
      nextSteps: ['Review the error and retry.'],
    }
    console.log(JSON.stringify(output, null, 2))
    process.exit(1)
  }
}

void main()
