#!/usr/bin/env node
/**
 * cli:roslyn-validator
 * SmartStack C# static analysis — checks per-layer conventions (SS001-SS010).
 *
 * Usage:
 *   npx --prefer-offline tsx skills/validation/roslyn/cli/index.ts --src <directory> [--layer <filter>]
 *
 * Exit codes:
 *   0  Success (0 errors)
 *   1  Errors detected
 *   2  Internal CLI error / input validation
 */
import { parseArgs } from 'node:util'
import { resolve } from 'node:path'
import { validate } from './validate'
import { execute } from './execute'
import { executeEnvelope, failExecute, printEnvelope } from '../../../lib/output.js'

const COMMAND = 'roslyn-validator'

const { values } = parseArgs({
  options: {
    src: { type: 'string' },
    layer: { type: 'string' },
    help: { type: 'boolean', short: 'h' },
  },
  strict: true,
})

if (values.help) {
  const paren = String.fromCharCode(41)
  console.log(`cli:roslyn-validator — SmartStack Studio

SmartStack C# static analysis (SS001-SS010${paren}.

Usage:
  npx --prefer-offline tsx index.ts --src <directory> [--layer <filter>]

Options:
  --src      Directory containing the .cs files (required${paren}
  --layer    Optional filter: controller, service, repository, entity, all (default: all${paren}
  -h, --help Show this help

Rules:
  SS001  Controller inherits ControllerBase + [ApiController]
  SS002  Single IService injection (no DbContext${paren}
  SS003  [NavRoute] present and module.section format
  SS004  [RequirePermission] on every public endpoint
  SS005  Returns DTOs, never entities
  SS006  CancellationToken as last async parameter
  SS007  NavRoute unique within the project
  SS008  Service without DbContext
  SS009  Repository without business logic
  SS010  Entity inherits BaseEntity

Exit codes:
  0  Success (0 errors${paren}
  1  Errors detected
  2  Internal CLI error`)
  process.exit(0)
}

if (!values.src) {
  printEnvelope(failExecute(COMMAND, ['--src is required']))
  process.exit(2)
}

const srcPath = resolve(values.src)

const validation = validate({ src: srcPath, layer: values.layer || 'all' })

if (!validation.valid) {
  printEnvelope(failExecute(COMMAND, validation.blockers))
  process.exit(2)
}

const report = execute(validation.data!)

if (report.errors === 0) {
  printEnvelope(executeEnvelope(COMMAND, { report, warnings: report.warnings > 0 ? [`${report.warnings} warning(s)`] : [] }))
} else {
  printEnvelope({ ...failExecute(COMMAND, [`${report.errors} error(s) detected`]), report })
}

process.exit(report.errors > 0 ? 1 : 0)
