/**
 * Bin shim writer for portable nexus-agents installs (#3a, child of #2301).
 *
 * Generates an executable Node script at `<binDir>/nexus-agents` that loads
 * the workspace-local nexus-agents CLI entry point. Used by the portable
 * installer to expose a stable absolute path that can be wired into
 * `.mcp.json` (#2308) without depending on the system PATH.
 *
 * Idempotent: re-emitting the same shim is a no-op success.
 *
 * @module cli/bin-shim
 */

import { existsSync, readFileSync, writeFileSync, chmodSync, mkdirSync } from 'node:fs';
import { join } from 'node:path';

/** Filename of the bin shim. */
export const SHIM_BASENAME = 'nexus-agents';

/** Mode for the bin shim — owner rwx, group rx, others rx (executable). */
const SHIM_MODE = 0o755;

/** Options accepted by {@link writeBinShim}. */
export interface WriteBinShimOptions {
  /** Directory where the shim is written (typically `.nexus-agents/bin`). */
  readonly binDir: string;
  /** Absolute path of the CLI entry point to require (typically `dist/cli.js` of the local install). */
  readonly cliEntryPath: string;
  /** Report what would be written without touching disk. Default false. */
  readonly dryRun?: boolean;
}

/** Outcome of a {@link writeBinShim} call. */
export interface WriteBinShimResult {
  readonly success: boolean;
  readonly shimPath: string;
  /** True when the shim was created or rewritten this call. */
  readonly written: boolean;
  /** True when the existing shim already matched the desired content. */
  readonly alreadyMatched: boolean;
  readonly error: string | null;
}

/** Builds the contents of the bin shim. Plain Node script, no shell. */
export function buildShimContents(cliEntryPath: string): string {
  const lines = [
    '#!/usr/bin/env node',
    '// Generated by `nexus-agents init --portable --install` (#3a).',
    '// Do not edit by hand — re-run `init --portable --install` to refresh.',
    `import('${cliEntryPath}').catch((e) => { console.error(e); process.exit(1); });`,
    '',
  ];
  return lines.join('\n');
}

/** Writes the bin shim at `<binDir>/nexus-agents`, creating the directory if missing. */
export function writeBinShim(options: WriteBinShimOptions): WriteBinShimResult {
  const shimPath = join(options.binDir, SHIM_BASENAME);
  const desired = buildShimContents(options.cliEntryPath);
  const dryRun = options.dryRun === true;

  try {
    if (existsSync(shimPath)) {
      const current = readFileSync(shimPath, 'utf-8');
      if (current === desired) {
        return { success: true, shimPath, written: false, alreadyMatched: true, error: null };
      }
    }
    if (!dryRun) {
      if (!existsSync(options.binDir)) mkdirSync(options.binDir, { recursive: true });
      writeFileSync(shimPath, desired, 'utf-8');
      chmodSync(shimPath, SHIM_MODE);
    }
    return { success: true, shimPath, written: true, alreadyMatched: false, error: null };
  } catch (error: unknown) {
    const msg = error instanceof Error ? error.message : String(error);
    return { success: false, shimPath, written: false, alreadyMatched: false, error: msg };
  }
}
