#!/usr/bin/env node
/**
 * cli:readiness-report
 * Agregge les resultats des 3 validators (roslyn, eslint, cross-validate),
 * calcule un score /100, decide GO / NO-GO / STOP.
 *
 * Usage :
 *   npx tsx skills/validation/readiness-report/cli/index.ts \
 *     --specs <directory> --src <directory> [--json]
 *
 * Exit codes :
 *   0  GO (score >= 90)
 *   1  NO-GO (score 70-89)
 *   2  STOP (score < 70) ou erreur interne
 */
import { parseArgs } from 'node:util'
import { resolve } from 'node:path'
import { validate } from './validate'
import { execute } from './execute'
import type { ReadinessReport } from './types'

// ─── Parse args ───
const { values } = parseArgs({
  options: {
    specs: { type: 'string' },
    src: { type: 'string' },
    json: { type: 'boolean', default: false },
    help: { type: 'boolean', short: 'h' },
  },
  strict: true,
})

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

Agregge les resultats des 3 validators et calcule un score /100.

Sources:
  roslyn-validator      40 pts  (4 pts x 10 regles SS001-SS010${paren}
  eslint-smartstack     25 pts  (5 pts x 5 regles ss/${paren}
  cross-validate-stack  35 pts  (7 pts x 5 checks${paren}

Seuils:
  >= 90  GO     — Developpement Phase 6 autorise
  70-89  NO-GO  — Corrections requises
  < 70   STOP   — Retour en Phase 3 ou 4

Usage:
  npx tsx skills/validation/readiness-report/cli/index.ts \\
    --specs <directory> --src <directory> [--json]

Options:
  --specs     Repertoire des specs JSON (requis${paren}
  --src       Repertoire du code source (requis${paren}
  --json      Output JSON uniquement (pas de console fancy${paren}
  -h, --help  Affiche cette aide

Exit codes:
  0  GO (score >= 90${paren}
  1  NO-GO (score 70-89${paren}
  2  STOP (score < 70${paren} ou erreur interne`)
  process.exit(0)
}

if (!values.specs || !values.src) {
  const missing: string[] = []
  if (!values.specs) missing.push('--specs')
  if (!values.src) missing.push('--src')
  console.error(JSON.stringify({
    timestamp: new Date().toISOString(),
    scores: {},
    total: 0,
    max: 100,
    recommendation: 'STOP',
    blockers: missing.map(m => `${m} is required`),
  }, null, 2))
  process.exit(2)
}

// ─── Resolve paths ───
const specsPath = resolve(values.specs)
const srcPath = resolve(values.src)

// ─── Validate input ───
const validation = validate({ specs: specsPath, src: srcPath })
if (!validation.valid) {
  const errorReport = {
    timestamp: new Date().toISOString(),
    scores: {},
    total: 0,
    max: 100,
    recommendation: 'STOP',
    blockers: validation.blockers,
  }
  if (values.json) {
    console.log(JSON.stringify(errorReport, null, 2))
  } else {
    console.error(`[STOP] Validation failed:`)
    for (const b of validation.blockers) {
      console.error(`  - ${b}`)
    }
  }
  process.exit(2)
}

// ─── Execute ───
let report: ReadinessReport
try {
  report = execute(validation.data!)
} catch (err) {
  const message = err instanceof Error ? err.message : String(err)
  const errorReport = {
    timestamp: new Date().toISOString(),
    scores: {},
    total: 0,
    max: 100,
    recommendation: 'STOP',
    blockers: [`Internal error: ${message}`],
  }
  if (values.json) {
    console.log(JSON.stringify(errorReport, null, 2))
  } else {
    console.error(`[STOP] Internal error: ${message}`)
  }
  process.exit(2)
}

// ─── Output ───
if (values.json) {
  console.log(JSON.stringify(report, null, 2))
} else {
  printFancyReport(report)
}

// ─── Exit code ───
if (report.recommendation === 'GO') {
  process.exit(0)
} else if (report.recommendation === 'NO-GO') {
  process.exit(1)
} else {
  process.exit(2)
}

// ─── Fancy console output ───

function printFancyReport(r: ReadinessReport): void {
  const W = 42 // inner width

  const checkMark = String.fromCharCode(10003)  // ✓
  const warningMark = String.fromCharCode(9888)  // ⚠
  const crossMark = String.fromCharCode(10007)   // ✗

  function statusIcon(status: string): string {
    if (status === 'ok') return checkMark
    if (status === 'warning') return warningMark
    if (status === 'error') return crossMark
    return '?'
  }

  function recIcon(rec: string): string {
    if (rec === 'GO') return checkMark
    if (rec === 'NO-GO') return warningMark
    return crossMark
  }

  function pad(s: string, len: number): string {
    if (s.length >= len) return s.substring(0, len)
    return s + ' '.repeat(len - s.length)
  }

  function padLeft(s: string, len: number): string {
    if (s.length >= len) return s.substring(0, len)
    return ' '.repeat(len - s.length) + s
  }

  const topLine = '\u2554' + '\u2550'.repeat(W) + '\u2557'
  const midLine = '\u2560' + '\u2550'.repeat(W) + '\u2563'
  const botLine = '\u255A' + '\u2550'.repeat(W) + '\u255D'
  const pipe = '\u2551'

  console.log(topLine)
  console.log(`${pipe}   SmartStack Readiness Report${' '.repeat(W - 31)}${pipe}`)
  console.log(midLine)

  // Score lines
  const sources: Array<{ label: string; key: 'roslyn' | 'eslint' | 'cross-validate' }> = [
    { label: 'roslyn-validator', key: 'roslyn' },
    { label: 'eslint-smartstack', key: 'eslint' },
    { label: 'cross-validate-stack', key: 'cross-validate' },
  ]

  for (const s of sources) {
    const sc = r.scores[s.key]
    const scoreStr = `${sc.score}/${sc.max}`
    const icon = statusIcon(sc.status)
    // Format: "  label          score   icon    "
    const labelPart = pad(`  ${s.label}`, 24)
    const scorePart = padLeft(scoreStr, 7)
    const iconPart = `   ${icon}`
    const lineContent = labelPart + scorePart + iconPart
    const remaining = W - lineContent.length
    const line = lineContent + ' '.repeat(Math.max(0, remaining))
    console.log(`${pipe}${line}${pipe}`)
  }

  console.log(midLine)

  // Total
  const totalStr = `${r.total}/${r.max}`
  const totalLabel = pad('  SCORE TOTAL', 24)
  const totalScore = padLeft(totalStr, 7)
  const totalRemaining = W - totalLabel.length - totalScore.length
  const totalLine = totalLabel + totalScore + ' '.repeat(Math.max(0, totalRemaining))
  console.log(`${pipe}${totalLine}${pipe}`)

  // Recommendation
  const recStr = `${recIcon(r.recommendation)} ${r.recommendation}`
  const recLabel = pad('  RECOMMANDATION', 24)
  const recRemaining = W - recLabel.length - recStr.length
  const recLine = recLabel + recStr + ' '.repeat(Math.max(0, recRemaining))
  console.log(`${pipe}${recLine}${pipe}`)

  console.log(botLine)

  // Blockers summary
  if (r.blockers.length > 0) {
    console.log('')
    console.log(`Blockers (${r.blockers.length}):`)
    for (const b of r.blockers) {
      console.log(`  - ${b}`)
    }
  }
}
