#!/usr/bin/env node
/**
 * cli:scaffold-business
 * Responsabilité : Generate CQRS pattern for an entity
 */
import { parseArgs } from 'node:util'
import { mkdirSync, writeFileSync } from 'node:fs'
import { dirname, resolve, join } from 'node:path'
import { validate } from './validate.js'
import { generate } from './generate.js'
import { generateEnvelope, failGenerate, printEnvelope } from '../../../../../lib/output.js'

const COMMAND = 'scaffold-business'

function main(): void {
  const { values } = parseArgs({ options: { spec: { type: 'string' }, outdir: { type: 'string' }, dry_run: { type: 'boolean', default: false } }, strict: true })
  if (!values.spec) { printEnvelope(failGenerate(COMMAND, ['--spec is required'])); process.exit(1) }

  let raw: unknown
  try { raw = JSON.parse(values.spec) } catch { printEnvelope(failGenerate(COMMAND, ['Invalid JSON'])); process.exit(1) }

  const validation = validate(raw)
  if (!validation.valid) { printEnvelope(failGenerate(COMMAND, validation.errors)); process.exit(1) }

  const spec = raw as any
  const files = generate(spec)

  if (values.dry_run) {
    printEnvelope(generateEnvelope(COMMAND, { data: { dryRun: true, files: files.map(f => f.path) }, warnings: validation.warnings }))
    process.exit(0)
  }

  const outdir = values.outdir ?? spec.projectPath
  const written: string[] = []
  for (const file of files) {
    const fullPath = resolve(join(outdir, file.path))
    mkdirSync(dirname(fullPath), { recursive: true })
    writeFileSync(fullPath, file.content, 'utf-8')
    written.push(fullPath)
  }

  printEnvelope(generateEnvelope(COMMAND, {
    data: { entity: spec.name, fileCount: written.length },
    filesCreated: written,
    warnings: validation.warnings,
    nextSteps: [
      'Run dotnet build',
      `Register service DI: services.AddScoped<I${spec.name}Service, ${spec.name}Service>();`,
      'Register MediatR handlers: services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(Program).Assembly));',
      'Register validators: services.AddValidatorsFromAssembly(typeof(Program).Assembly);',
      '(Each of the three DI lines above is idempotent — add once per project, not per entity.)',
    ],
  }))
}

main()
