#!/usr/bin/env node
//
// audit-dev-api / index.ts — Entry point.
//
// Detects controller / pagespec drift (DEV-API-010/011) and serves as the
// Phase 2 gate of /ba-develop. Mirrors the contract of
// audit-dev-frontend/cli/audit-dev-frontend/index.ts so the orchestrator
// can chain both gates uniformly.
//
// Usage (read-only diagnostic, safe to run on any project):
//
//   npx tsx skills/development/audit-dev-api/cli/audit-dev-api/index.ts \
//     --project-path  "<backend-root>" \
//     --module-path   ".smartstack/ba/<APP>/<MODULE>" \
//     --module-code   "<MODULE>" \
//     --app-code      "<APP>" \
//     --mode audit
//
// Exit code: 0 when no `err` findings, 1 otherwise.
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 type { AuditDevApiOutput, Finding } from './types.js'

const program = new Command()

program
  .name('audit-dev-api')
  .description('Audit controller ↔ pagespec alignment (DEV-API-010/011). Phase 2 gate of /ba-develop.')
  .requiredOption('--project-path <path>', 'Absolute path to the .NET backend root (src/<Ns>.Api/Controllers/**)')
  .requiredOption('--module-path <path>', 'Absolute path to .smartstack/ba/<APP>/<MODULE>')
  .requiredOption('--module-code <code>', 'Active module code (PRD scope)')
  .requiredOption('--app-code <code>', 'Active application code (PRD scope)')
  .option('--mode <mode>', 'audit | apply (apply is a stub in MVP)', 'audit')
  .option('--rules <list>', 'Comma-separated rule codes (e.g. DEV-API-010). Default = all implemented rules')
  .option('--no-write-report', 'Skip writing _audit/dev-api-<module>.md (stdout only)')
  .parse(process.argv)

const opts = program.opts()

const raw = {
  backendPath: opts.projectPath as string,
  modulePath: opts.modulePath as string,
  moduleCode: opts.moduleCode as string,
  appCode: opts.appCode as string,
  mode: opts.mode as string,
  rules: typeof opts.rules === 'string'
    ? opts.rules.split(',').map((s: string) => s.trim()).filter(Boolean)
    : [],
}
const writeReport = opts.writeReport !== false

const validation = validateArgs(raw)
if (!validation.valid || !validation.args) {
  const output: AuditDevApiOutput = {
    success: false,
    command: 'audit-dev-api',
    data: { mode: (raw.mode as 'audit' | 'apply') ?? 'audit', rulesRun: [], valid: false },
    report: null,
    auditReport: 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 report = await audit(args)

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

    const valid = report.counts.errors === 0
    const rulesRun = args.rules.length > 0 ? args.rules : Object.keys(report.byRule)

    const stripped = report.findings.map((f: Finding) => ({
      dimension: f.dimension,
      code: f.code,
      severity: f.severity,
      label: f.label,
      params: f.params,
      solution: f.solution,
      fixSkill: f.fixSkill,
      fixPhaseKey: f.fixPhaseKey,
    }))

    const nextSteps: string[] = []
    if (report.counts.errors > 0) {
      nextSteps.push(`${report.counts.errors} ERROR finding(s) — blocking Phase 2 gate of /ba-develop.`)
      nextSteps.push('Re-run /ba-develop after fixing the pagespec ↔ controller drift listed above.')
    }

    const output: AuditDevApiOutput = {
      success: true,
      command: 'audit-dev-api',
      data: { mode: args.mode, rulesRun, valid },
      report,
      auditReport: {
        scope: 'devApi',
        applicationCode: args.appCode,
        moduleCode: args.moduleCode,
        findings: stripped,
      },
      filesModified: [],
      errors: [],
      warnings: [],
      nextSteps,
    }
    console.log(JSON.stringify(output, null, 2))
    process.exit(valid ? 0 : 1)
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err)
    const output: AuditDevApiOutput = {
      success: false,
      command: 'audit-dev-api',
      data: { mode: args.mode, rulesRun: [], valid: false },
      report: null,
      auditReport: null,
      filesModified: [],
      errors: [`Unexpected error: ${message}`],
      warnings: [],
      nextSteps: ['Review the error and retry.'],
    }
    console.log(JSON.stringify(output, null, 2))
    process.exit(1)
  }
}

void main()
