#!/usr/bin/env node

/**
 * SDLC Skill Pack — npm dependency installer
 *
 * Cross-platform (Windows, Linux, macOS).
 * Installs project-local (devDependencies), not global.
 *
 * Usage:
 *   node install-deps.mjs [projectPath]
 *
 * What it does:
 *   1. Ensures package.json exists
 *   2. Checks/installs npm package: gitnexus (includes MCP server built-in)
 *   3. Provisions .mcp.json with GitNexus MCP server entry (npx gitnexus mcp — uses local binary)
 */

import { existsSync, readFileSync } from 'fs';
import { join } from 'path';
import { execSync } from 'child_process';

const projectPath = process.argv[2] || process.cwd();
const isWin = process.platform === 'win32';

// ── Node.js LTS Check ──
// Even-numbered major versions (22, 24, 26…) are LTS; odd (23, 25…) are Current/non-LTS.
// Native modules (e.g. @ladybugdb/core in gitnexus) may not build on non-LTS versions.

const nodeMajor = parseInt(process.versions.node.split('.')[0], 10);
if (nodeMajor % 2 !== 0) {
  console.warn(`\n⚠️  Node.js v${process.versions.node} is a non-LTS (Current) release.`);
  console.warn('   Native npm packages (e.g. gitnexus) may fail to build.');
  console.warn('   Recommended: switch to an LTS version (v22 or v24).');
  console.warn(isWin
    ? '   → nvm install lts   OR   winget install OpenJS.NodeJS.LTS\n'
    : '   → nvm install --lts   OR   brew install node@24\n');
}

// ── Config ──

const NPM_DEPS = [
  { pkg: 'gitnexus', bin: 'gitnexus', installAs: 'gitnexus@1.6.6-rc.76' },
];

// ── Helpers ──

function log(icon, msg) {
  console.log(`  ${icon} ${msg}`);
}

function isInstalled(pkg, bin) {
  const pkgJson = join(projectPath, 'node_modules', ...pkg.split('/'), 'package.json');
  const binPath = join(projectPath, 'node_modules', '.bin', bin);
  const binExists = existsSync(binPath) || (isWin && existsSync(binPath + '.cmd'));
  return existsSync(pkgJson) && binExists;
}

function getVersion(pkg) {
  try {
    const meta = JSON.parse(readFileSync(
      join(projectPath, 'node_modules', ...pkg.split('/'), 'package.json'), 'utf-8'
    ));
    return meta.version || 'unknown';
  } catch { return 'unknown'; }
}

// ── Step 1: Ensure package.json ──

console.log('\n[sdlc-setup] Checking npm dependencies...\n');

if (!existsSync(join(projectPath, 'package.json'))) {
  log('📦', 'No package.json found — creating...');
  execSync('npm init -y', { cwd: projectPath, stdio: 'pipe' });
  log('✅', 'package.json created');
}

// ── Step 2: Check and install npm packages ──

const missing = [];

for (const dep of NPM_DEPS) {
  if (isInstalled(dep.pkg, dep.bin)) {
    log('✅', `${dep.pkg} (${getVersion(dep.pkg)})`);
  } else {
    log('⬇️', `${dep.pkg} — missing, will install`);
    missing.push(dep.pkg);
  }
}

if (missing.length > 0) {
  console.log('');
  log('📦', `Installing ${missing.length} package(s)...`);
  try {
    // Install with --ignore-scripts to avoid rebuilding unrelated project deps,
    // then rebuild gitnexus AND its native transitive dep @ladybugdb/core.
    // @ladybugdb/core needs its install script to copy platform-specific lbugjs.node binary.
    const installNames = missing.map(pkg => {
      const dep = NPM_DEPS.find(d => d.pkg === pkg);
      return dep?.installAs || pkg;
    });
    execSync(`npm install --save-dev --ignore-scripts ${installNames.join(' ')}`, {
      cwd: projectPath,
      stdio: 'inherit',
    });
    execSync(`npm rebuild ${missing.join(' ')} @ladybugdb/core`, {
      cwd: projectPath,
      stdio: 'inherit',
    });
    console.log('');
    for (const pkg of missing) {
      const dep = NPM_DEPS.find(d => d.pkg === pkg);
      if (dep && isInstalled(dep.pkg, dep.bin)) {
        log('✅', `${dep.pkg} (${getVersion(dep.pkg)}) — installed`);
      } else {
        log('❌', `${dep.pkg} — install failed`);
      }
    }
  } catch {
    log('❌', 'npm install failed — check network and try again');
    process.exit(1);
  }
} else {
  console.log('');
  log('✅', 'All npm packages already installed');
}

// ── Done ──

console.log('\n[sdlc-setup] npm dependencies ready ✅\n');
console.log('  Next: run `/sdlc-init` to create project structure, then `/sdlc-onboard-code` to index code\n');
